Merge "Centralize config options"

This commit is contained in:
Zuul 2018-01-09 12:07:50 +00:00 committed by Gerrit Code Review
commit c0c1dd813d
26 changed files with 705 additions and 439 deletions

View File

@ -1,11 +1,6 @@
[DEFAULT]
output_file = example.conf
namespace = ironic_inspector
namespace = ironic_inspector.common.ironic
namespace = ironic_inspector.common.swift
namespace = ironic_inspector.plugins.capabilities
namespace = ironic_inspector.plugins.discovery
namespace = ironic_inspector.plugins.pci_devices
namespace = keystonemiddleware.auth_token
namespace = oslo.db
namespace = oslo.log

View File

@ -183,7 +183,7 @@
[capabilities]
#
# From ironic_inspector.plugins.capabilities
# From ironic_inspector
#
# Whether to store the boot mode (BIOS or UEFI). (boolean value)
@ -340,7 +340,7 @@
[discovery]
#
# From ironic_inspector.plugins.discovery
# From ironic_inspector
#
# The name of the Ironic driver used by the enroll hook when creating
@ -408,7 +408,7 @@
[ironic]
#
# From ironic_inspector.common.ironic
# From ironic_inspector
#
# Authentication URL (string value)
@ -763,7 +763,7 @@
[pci_devices]
#
# From ironic_inspector.plugins.pci_devices
# From ironic_inspector
#
# An alias for PCI device identified by 'vendor_id' and 'product_id'
@ -868,7 +868,7 @@
[swift]
#
# From ironic_inspector.common.swift
# From ironic_inspector
#
# Authentication URL (string value)

View File

@ -31,41 +31,6 @@ VALID_STATES = {'enroll', 'manageable', 'inspecting', 'inspect failed'}
# 1.19 is API version, which supports port.pxe_enabled
DEFAULT_IRONIC_API_VERSION = '1.19'
IRONIC_GROUP = 'ironic'
IRONIC_OPTS = [
cfg.StrOpt('os_region',
help=_('Keystone region used to get Ironic endpoints.')),
cfg.StrOpt('auth_strategy',
default='keystone',
choices=('keystone', 'noauth'),
help=_('Method to use for authentication: noauth or '
'keystone.')),
cfg.StrOpt('ironic_url',
default='http://localhost:6385/',
help=_('Ironic API URL, used to set Ironic API URL when '
'auth_strategy option is noauth to work with standalone '
'Ironic without keystone.')),
cfg.StrOpt('os_service_type',
default='baremetal',
help=_('Ironic service type.')),
cfg.StrOpt('os_endpoint_type',
default='internalURL',
help=_('Ironic endpoint type.')),
cfg.IntOpt('retry_interval',
default=2,
help=_('Interval between retries in case of conflict error '
'(HTTP 409).')),
cfg.IntOpt('max_retries',
default=30,
help=_('Maximum number of retries in case of conflict error '
'(HTTP 409).')),
]
CONF.register_opts(IRONIC_OPTS, group=IRONIC_GROUP)
keystone.register_auth_opts(IRONIC_GROUP)
IRONIC_SESSION = None
@ -124,7 +89,7 @@ def get_client(token=None,
else:
global IRONIC_SESSION
if not IRONIC_SESSION:
IRONIC_SESSION = keystone.get_session(IRONIC_GROUP)
IRONIC_SESSION = keystone.get_session('ironic')
if token is None:
args = {'session': IRONIC_SESSION,
'region_name': CONF.ironic.os_region}
@ -182,7 +147,3 @@ def get_node(node_id, ironic=None, **kwargs):
except ironic_exc.HttpError as exc:
raise utils.Error(_("Cannot get node %(node)s: %(exc)s") %
{'node': node_id, 'exc': exc})
def list_opts():
return keystone.add_auth_options(IRONIC_OPTS, IRONIC_GROUP)

View File

@ -33,7 +33,7 @@ def get_session(group):
return session
def add_auth_options(options, group):
def add_auth_options(options):
def add_options(opts, opts_to_add):
for new_opt in opts_to_add:
@ -53,4 +53,4 @@ def add_auth_options(options, group):
add_options(opts, loading.get_auth_plugin_conf_options(plugin))
add_options(opts, loading.get_session_conf_options())
opts.sort(key=lambda x: x.name)
return [(group, opts)]
return opts

View File

@ -10,19 +10,20 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_config import cfg
from oslo_log import log
from ironic_inspector import conf
from ironic_inspector.conf import opts
LOG = log.getLogger(__name__)
CONF = conf.cfg.CONF
CONF = cfg.CONF
def prepare_service(args=None):
args = [] if args is None else args
log.register_options(CONF)
conf.set_config_defaults()
conf.parse_args(args)
opts.set_config_defaults()
opts.parse_args(args)
log.setup(CONF, 'ironic_inspector')
LOG.debug("Configuration:")

View File

@ -26,34 +26,6 @@ from ironic_inspector import utils
CONF = cfg.CONF
SWIFT_GROUP = 'swift'
SWIFT_OPTS = [
cfg.IntOpt('max_retries',
default=2,
help=_('Maximum number of times to retry a Swift request, '
'before failing.')),
cfg.IntOpt('delete_after',
default=0,
help=_('Number of seconds that the Swift object will last '
'before being deleted. (set to 0 to never delete the '
'object).')),
cfg.StrOpt('container',
default='ironic-inspector',
help=_('Default Swift container to use when creating '
'objects.')),
cfg.StrOpt('os_service_type',
default='object-store',
help=_('Swift service type.')),
cfg.StrOpt('os_endpoint_type',
default='internalURL',
help=_('Swift endpoint type.')),
cfg.StrOpt('os_region',
help=_('Keystone region to get endpoint for.')),
]
CONF.register_opts(SWIFT_OPTS, group=SWIFT_GROUP)
keystone.register_auth_opts(SWIFT_GROUP)
OBJECT_NAME_PREFIX = 'inspector_data'
SWIFT_SESSION = None
@ -77,7 +49,7 @@ class SwiftAPI(object):
"""
global SWIFT_SESSION
if not SWIFT_SESSION:
SWIFT_SESSION = keystone.get_session(SWIFT_GROUP)
SWIFT_SESSION = keystone.get_session('swift')
self.connection = swift_client.Connection(session=SWIFT_SESSION)
@ -166,7 +138,3 @@ def get_introspection_data(uuid, suffix=None):
if suffix is not None:
swift_object_name = '%s-%s' % (swift_object_name, suffix)
return swift_api.get_object(swift_object_name)
def list_opts():
return keystone.add_auth_options(SWIFT_OPTS, SWIFT_GROUP)

View File

@ -1,283 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from oslo_log import log
from oslo_middleware import cors
from ironic_inspector.common.i18n import _
from ironic_inspector import version
MIN_VERSION_HEADER = 'X-OpenStack-Ironic-Inspector-API-Minimum-Version'
MAX_VERSION_HEADER = 'X-OpenStack-Ironic-Inspector-API-Maximum-Version'
VERSION_HEADER = 'X-OpenStack-Ironic-Inspector-API-Version'
VALID_ADD_PORTS_VALUES = ('all', 'active', 'pxe', 'disabled')
VALID_KEEP_PORTS_VALUES = ('all', 'present', 'added')
VALID_STORE_DATA_VALUES = ('none', 'swift')
IPTABLES_OPTS = [
cfg.BoolOpt('manage_firewall',
default=True,
# NOTE(milan) this filter driver will be replaced by
# a dnsmasq filter driver
deprecated_for_removal=True,
deprecated_group='firewall',
help=_('Whether to manage firewall rules for PXE port. '
'This configuration option was deprecated in favor of '
'the ``driver`` option in the ``pxe_filter`` section. '
'Please, use the ``noop`` filter driver to disable the '
'firewall filtering or the ``iptables`` filter driver '
'to enable it.')),
cfg.StrOpt('dnsmasq_interface',
default='br-ctlplane',
deprecated_group='firewall',
help=_('Interface on which dnsmasq listens, the default is for '
'VM\'s.')),
cfg.StrOpt('firewall_chain',
default='ironic-inspector',
deprecated_group='firewall',
help=_('iptables chain name to use.')),
cfg.ListOpt('ethoib_interfaces',
deprecated_group='firewall',
default=[],
help=_('List of Etherent Over InfiniBand interfaces '
'on the Inspector host which are used for physical '
'access to the DHCP network. Multiple interfaces would '
'be attached to a bond or bridge specified in '
'dnsmasq_interface. The MACs of the InfiniBand nodes '
'which are not in desired state are going to be '
'blacklisted based on the list of neighbor MACs '
'on these interfaces.')),
]
PROCESSING_OPTS = [
cfg.StrOpt('add_ports',
default='pxe',
help=_('Which MAC addresses to add as ports during '
'introspection. Possible values: all '
'(all MAC addresses), active (MAC addresses of NIC with '
'IP addresses), pxe (only MAC address of NIC node PXE '
'booted from, falls back to "active" if PXE MAC is not '
'supplied by the ramdisk).'),
choices=VALID_ADD_PORTS_VALUES),
cfg.StrOpt('keep_ports',
default='all',
help=_('Which ports (already present on a node) to keep after '
'introspection. Possible values: all (do not delete '
'anything), present (keep ports which MACs were present '
'in introspection data), added (keep only MACs that we '
'added during introspection).'),
choices=VALID_KEEP_PORTS_VALUES),
cfg.BoolOpt('overwrite_existing',
default=True,
help=_('Whether to overwrite existing values in node '
'database. Disable this option to make '
'introspection a non-destructive operation.')),
cfg.StrOpt('default_processing_hooks',
default='ramdisk_error,root_disk_selection,scheduler,'
'validate_interfaces,capabilities,pci_devices',
help=_('Comma-separated list of default hooks for processing '
'pipeline. Hook \'scheduler\' updates the node with the '
'minimum properties required by the Nova scheduler. '
'Hook \'validate_interfaces\' ensures that valid NIC '
'data was provided by the ramdisk. '
'Do not exclude these two unless you really know what '
'you\'re doing.')),
cfg.StrOpt('processing_hooks',
default='$default_processing_hooks',
help=_('Comma-separated list of enabled hooks for processing '
'pipeline. The default for this is '
'$default_processing_hooks, hooks can be added before '
'or after the defaults like this: '
'"prehook,$default_processing_hooks,posthook".')),
cfg.StrOpt('ramdisk_logs_dir',
help=_('If set, logs from ramdisk will be stored in this '
'directory.')),
cfg.BoolOpt('always_store_ramdisk_logs',
default=False,
help=_('Whether to store ramdisk logs even if it did not '
'return an error message (dependent upon '
'"ramdisk_logs_dir" option being set).')),
cfg.StrOpt('node_not_found_hook',
help=_('The name of the hook to run when inspector receives '
'inspection information from a node it isn\'t already '
'aware of. This hook is ignored by default.')),
cfg.StrOpt('store_data',
default='none',
choices=VALID_STORE_DATA_VALUES,
help=_('Method for storing introspection data. If set to \'none'
'\', introspection data will not be stored.')),
cfg.StrOpt('store_data_location',
help=_('Name of the key to store the location of stored data '
'in the extra column of the Ironic database.')),
cfg.BoolOpt('disk_partitioning_spacing',
default=True,
help=_('Whether to leave 1 GiB of disk size untouched for '
'partitioning. Only has effect when used with the IPA '
'as a ramdisk, for older ramdisk local_gb is '
'calculated on the ramdisk side.')),
cfg.StrOpt('ramdisk_logs_filename_format',
default='{uuid}_{dt:%Y%m%d-%H%M%S.%f}.tar.gz',
help=_('File name template for storing ramdisk logs. The '
'following replacements can be used: '
'{uuid} - node UUID or "unknown", '
'{bmc} - node BMC address or "unknown", '
'{dt} - current UTC date and time, '
'{mac} - PXE booting MAC or "unknown".')),
cfg.BoolOpt('power_off',
default=True,
help=_('Whether to power off a node after introspection.')),
]
SERVICE_OPTS = [
cfg.StrOpt('listen_address',
default='0.0.0.0',
help=_('IP to listen on.')),
cfg.PortOpt('listen_port',
default=5050,
help=_('Port to listen on.')),
cfg.StrOpt('auth_strategy',
default='keystone',
choices=('keystone', 'noauth'),
help=_('Authentication method used on the ironic-inspector '
'API. Either "noauth" or "keystone" are currently valid '
'options. "noauth" will disable all authentication.')),
cfg.IntOpt('timeout',
default=3600,
help=_('Timeout after which introspection is considered '
'failed, set to 0 to disable.')),
cfg.IntOpt('node_status_keep_time',
default=0,
help=_('For how much time (in seconds) to keep status '
'information about nodes after introspection was '
'finished for them. Set to 0 (the default) '
'to disable the timeout.'),
deprecated_for_removal=True),
cfg.IntOpt('clean_up_period',
default=60,
help=_('Amount of time in seconds, after which repeat clean up '
'of timed out nodes and old nodes status information.')),
cfg.BoolOpt('use_ssl',
default=False,
help=_('SSL Enabled/Disabled')),
cfg.StrOpt('ssl_cert_path',
default='',
help=_('Path to SSL certificate')),
cfg.StrOpt('ssl_key_path',
default='',
help=_('Path to SSL key')),
cfg.IntOpt('max_concurrency',
default=1000, min=2,
help=_('The green thread pool size.')),
cfg.IntOpt('introspection_delay',
default=5,
help=_('Delay (in seconds) between two introspections.')),
cfg.ListOpt('ipmi_address_fields',
default=['ilo_address', 'drac_host', 'drac_address',
'cimc_address'],
help=_('Ironic driver_info fields that are equivalent '
'to ipmi_address.')),
cfg.StrOpt('rootwrap_config',
default="/etc/ironic-inspector/rootwrap.conf",
help=_('Path to the rootwrap configuration file to use for '
'running commands as root')),
cfg.IntOpt('api_max_limit', default=1000, min=1,
help=_('Limit the number of elements an API list-call returns'))
]
PXE_FILTER_OPTS = [
cfg.StrOpt('driver', default='iptables',
help=_('PXE boot filter driver to use, such as iptables')),
cfg.IntOpt('sync_period', default=15, min=0,
deprecated_name='firewall_update_period',
deprecated_group='firewall',
help=_('Amount of time in seconds, after which repeat periodic '
'update of the filter.')),
]
DNSMASQ_PXE_FILTER_OPTS = [
cfg.StrOpt('dhcp_hostsdir',
default='/var/lib/ironic-inspector/dhcp-hostsdir',
help=_('The MAC address cache directory, exposed to dnsmasq.'
'This directory is expected to be in exclusive control '
'of the driver.')),
cfg.BoolOpt('purge_dhcp_hostsdir', default=True,
help=_('Purge the hostsdir upon driver initialization. '
'Setting to false should only be performed when the '
'deployment of inspector is such that there are '
'multiple processes executing inside of the same host '
'and namespace. In this case, the Operator is '
'responsible for setting up a custom cleaning '
'facility.')),
cfg.StrOpt('dnsmasq_start_command', default='',
help=_('A (shell) command line to start the dnsmasq service '
'upon filter initialization. Default: don\'t start.')),
cfg.StrOpt('dnsmasq_stop_command', default='',
help=_('A (shell) command line to stop the dnsmasq service '
'upon inspector (error) exit. Default: don\'t stop.')),
]
cfg.CONF.register_opts(SERVICE_OPTS)
cfg.CONF.register_opts(IPTABLES_OPTS, group='iptables')
cfg.CONF.register_opts(PROCESSING_OPTS, group='processing')
cfg.CONF.register_opts(PXE_FILTER_OPTS, 'pxe_filter')
cfg.CONF.register_opts(DNSMASQ_PXE_FILTER_OPTS, group='dnsmasq_pxe_filter')
def list_opts():
return [
('', SERVICE_OPTS),
('iptables', IPTABLES_OPTS),
('processing', PROCESSING_OPTS),
('pxe_filter', PXE_FILTER_OPTS),
('dnsmasq_pxe_filter', DNSMASQ_PXE_FILTER_OPTS),
]
def set_config_defaults():
"""This method updates all configuration default values."""
log.set_defaults(default_log_levels=['sqlalchemy=WARNING',
'iso8601=WARNING',
'requests=WARNING',
'urllib3.connectionpool=WARNING',
'keystonemiddleware=WARNING',
'swiftclient=WARNING',
'keystoneauth=WARNING',
'ironicclient=WARNING'])
set_cors_middleware_defaults()
def set_cors_middleware_defaults():
"""Update default configuration options for oslo.middleware."""
# TODO(krotscheck): Update with https://review.openstack.org/#/c/285368/
cfg.set_defaults(
cors.CORS_OPTS,
allow_headers=['X-Auth-Token',
MIN_VERSION_HEADER,
MAX_VERSION_HEADER,
VERSION_HEADER],
allow_methods=['GET', 'POST', 'PUT', 'HEAD',
'PATCH', 'DELETE', 'OPTIONS']
)
def parse_args(args, default_config_files=None):
cfg.CONF(args,
project='ironic-inspector',
version=version.version_info.release_string(),
default_config_files=default_config_files)

View File

@ -0,0 +1,39 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.from oslo_config import cfg
from oslo_config import cfg
from ironic_inspector.conf import capabilities
from ironic_inspector.conf import default
from ironic_inspector.conf import discovery
from ironic_inspector.conf import dnsmasq_pxe_filter
from ironic_inspector.conf import iptables
from ironic_inspector.conf import ironic
from ironic_inspector.conf import pci_devices
from ironic_inspector.conf import processing
from ironic_inspector.conf import pxe_filter
from ironic_inspector.conf import swift
CONF = cfg.CONF
capabilities.register_opts(CONF)
discovery.register_opts(CONF)
default.register_opts(CONF)
dnsmasq_pxe_filter.register_opts(CONF)
iptables.register_opts(CONF)
ironic.register_opts(CONF)
pci_devices.register_opts(CONF)
processing.register_opts(CONF)
pxe_filter.register_opts(CONF)
swift.register_opts(CONF)

View File

@ -0,0 +1,45 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
DEFAULT_CPU_FLAGS_MAPPING = {
'vmx': 'cpu_vt',
'svm': 'cpu_vt',
'aes': 'cpu_aes',
'pse': 'cpu_hugepages',
'pdpe1gb': 'cpu_hugepages_1g',
'smx': 'cpu_txt',
}
_OPTS = [
cfg.BoolOpt('boot_mode',
default=False,
help=_('Whether to store the boot mode (BIOS or UEFI).')),
cfg.DictOpt('cpu_flags',
default=DEFAULT_CPU_FLAGS_MAPPING,
help=_('Mapping between a CPU flag and a capability to set '
'if this flag is present.')),
]
def register_opts(conf):
conf.register_opts(_OPTS, 'capabilities')
def list_opts():
return _OPTS

View File

@ -0,0 +1,81 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
_OPTS = [
cfg.StrOpt('listen_address',
default='0.0.0.0',
help=_('IP to listen on.')),
cfg.PortOpt('listen_port',
default=5050,
help=_('Port to listen on.')),
cfg.StrOpt('auth_strategy',
default='keystone',
choices=('keystone', 'noauth'),
help=_('Authentication method used on the ironic-inspector '
'API. Either "noauth" or "keystone" are currently valid '
'options. "noauth" will disable all authentication.')),
cfg.IntOpt('timeout',
default=3600,
help=_('Timeout after which introspection is considered '
'failed, set to 0 to disable.')),
cfg.IntOpt('node_status_keep_time',
default=0,
help=_('For how much time (in seconds) to keep status '
'information about nodes after introspection was '
'finished for them. Set to 0 (the default) '
'to disable the timeout.'),
deprecated_for_removal=True),
cfg.IntOpt('clean_up_period',
default=60,
help=_('Amount of time in seconds, after which repeat clean up '
'of timed out nodes and old nodes status information.')),
cfg.BoolOpt('use_ssl',
default=False,
help=_('SSL Enabled/Disabled')),
cfg.StrOpt('ssl_cert_path',
default='',
help=_('Path to SSL certificate')),
cfg.StrOpt('ssl_key_path',
default='',
help=_('Path to SSL key')),
cfg.IntOpt('max_concurrency',
default=1000, min=2,
help=_('The green thread pool size.')),
cfg.IntOpt('introspection_delay',
default=5,
help=_('Delay (in seconds) between two introspections.')),
cfg.ListOpt('ipmi_address_fields',
default=['ilo_address', 'drac_host', 'drac_address',
'cimc_address'],
help=_('Ironic driver_info fields that are equivalent '
'to ipmi_address.')),
cfg.StrOpt('rootwrap_config',
default="/etc/ironic-inspector/rootwrap.conf",
help=_('Path to the rootwrap configuration file to use for '
'running commands as root')),
cfg.IntOpt('api_max_limit', default=1000, min=1,
help=_('Limit the number of elements an API list-call returns'))
]
def register_opts(conf):
conf.register_opts(_OPTS)
def list_opts():
return _OPTS

View File

@ -0,0 +1,32 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
_OPTS = [
cfg.StrOpt('enroll_node_driver',
default='fake',
help=_('The name of the Ironic driver used by the enroll '
'hook when creating a new node in Ironic.')),
]
def register_opts(conf):
conf.register_opts(_OPTS, 'discovery')
def list_opts():
return _OPTS

View File

@ -0,0 +1,48 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
_OPTS = [
cfg.StrOpt('dhcp_hostsdir',
default='/var/lib/ironic-inspector/dhcp-hostsdir',
help=_('The MAC address cache directory, exposed to dnsmasq.'
'This directory is expected to be in exclusive control '
'of the driver.')),
cfg.BoolOpt('purge_dhcp_hostsdir', default=True,
help=_('Purge the hostsdir upon driver initialization. '
'Setting to false should only be performed when the '
'deployment of inspector is such that there are '
'multiple processes executing inside of the same host '
'and namespace. In this case, the Operator is '
'responsible for setting up a custom cleaning '
'facility.')),
cfg.StrOpt('dnsmasq_start_command', default='',
help=_('A (shell) command line to start the dnsmasq service '
'upon filter initialization. Default: don\'t start.')),
cfg.StrOpt('dnsmasq_stop_command', default='',
help=_('A (shell) command line to stop the dnsmasq service '
'upon inspector (error) exit. Default: don\'t stop.')),
]
def register_opts(conf):
conf.register_opts(_OPTS, 'dnsmasq_pxe_filter')
def list_opts():
return _OPTS

View File

@ -0,0 +1,60 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
_OPTS = [
cfg.BoolOpt('manage_firewall',
default=True,
# NOTE(milan) this filter driver will be replaced by
# a dnsmasq filter driver
deprecated_for_removal=True,
deprecated_group='firewall',
help=_('Whether to manage firewall rules for PXE port. '
'This configuration option was deprecated in favor of '
'the ``driver`` option in the ``pxe_filter`` section. '
'Please, use the ``noop`` filter driver to disable the '
'firewall filtering or the ``iptables`` filter driver '
'to enable it.')),
cfg.StrOpt('dnsmasq_interface',
default='br-ctlplane',
deprecated_group='firewall',
help=_('Interface on which dnsmasq listens, the default is for '
'VM\'s.')),
cfg.StrOpt('firewall_chain',
default='ironic-inspector',
deprecated_group='firewall',
help=_('iptables chain name to use.')),
cfg.ListOpt('ethoib_interfaces',
deprecated_group='firewall',
default=[],
help=_('List of Etherent Over InfiniBand interfaces '
'on the Inspector host which are used for physical '
'access to the DHCP network. Multiple interfaces would '
'be attached to a bond or bridge specified in '
'dnsmasq_interface. The MACs of the InfiniBand nodes '
'which are not in desired state are going to be '
'blacklisted based on the list of neighbor MACs '
'on these interfaces.')),
]
def register_opts(conf):
conf.register_opts(_OPTS, 'iptables')
def list_opts():
return _OPTS

View File

@ -0,0 +1,59 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
from ironic_inspector.common import keystone
IRONIC_GROUP = 'ironic'
_OPTS = [
cfg.StrOpt('os_region',
help=_('Keystone region used to get Ironic endpoints.')),
cfg.StrOpt('auth_strategy',
default='keystone',
choices=('keystone', 'noauth'),
help=_('Method to use for authentication: noauth or '
'keystone.')),
cfg.StrOpt('ironic_url',
default='http://localhost:6385/',
help=_('Ironic API URL, used to set Ironic API URL when '
'auth_strategy option is noauth to work with standalone '
'Ironic without keystone.')),
cfg.StrOpt('os_service_type',
default='baremetal',
help=_('Ironic service type.')),
cfg.StrOpt('os_endpoint_type',
default='internalURL',
help=_('Ironic endpoint type.')),
cfg.IntOpt('retry_interval',
default=2,
help=_('Interval between retries in case of conflict error '
'(HTTP 409).')),
cfg.IntOpt('max_retries',
default=30,
help=_('Maximum number of retries in case of conflict error '
'(HTTP 409).')),
]
def register_opts(conf):
conf.register_opts(_OPTS, IRONIC_GROUP)
keystone.register_auth_opts(IRONIC_GROUP)
def list_opts():
return keystone.add_auth_options(_OPTS)

View File

@ -0,0 +1,74 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from oslo_log import log
from oslo_middleware import cors
import ironic_inspector.conf
from ironic_inspector import version
MIN_VERSION_HEADER = 'X-OpenStack-Ironic-Inspector-API-Minimum-Version'
MAX_VERSION_HEADER = 'X-OpenStack-Ironic-Inspector-API-Maximum-Version'
VERSION_HEADER = 'X-OpenStack-Ironic-Inspector-API-Version'
def set_config_defaults():
"""Return a list of oslo.config options available in Inspector code."""
log.set_defaults(default_log_levels=['sqlalchemy=WARNING',
'iso8601=WARNING',
'requests=WARNING',
'urllib3.connectionpool=WARNING',
'keystonemiddleware=WARNING',
'swiftclient=WARNING',
'keystoneauth=WARNING',
'ironicclient=WARNING'])
set_cors_middleware_defaults()
def set_cors_middleware_defaults():
"""Update default configuration options for oslo.middleware."""
# TODO(krotscheck): Update with https://review.openstack.org/#/c/285368/
cfg.set_defaults(
cors.CORS_OPTS,
allow_headers=['X-Auth-Token',
MIN_VERSION_HEADER,
MAX_VERSION_HEADER,
VERSION_HEADER],
allow_methods=['GET', 'POST', 'PUT', 'HEAD',
'PATCH', 'DELETE', 'OPTIONS']
)
def parse_args(args, default_config_files=None):
cfg.CONF(args,
project='ironic-inspector',
version=version.version_info.release_string(),
default_config_files=default_config_files)
def list_opts():
return [
('capabilities', ironic_inspector.conf.capabilities.list_opts()),
('DEFAULT', ironic_inspector.conf.default.list_opts()),
('discovery', ironic_inspector.conf.discovery.list_opts()),
('dnsmasq_pxe_filter',
ironic_inspector.conf.dnsmasq_pxe_filter.list_opts()),
('swift', ironic_inspector.conf.swift.list_opts()),
('ironic', ironic_inspector.conf.ironic.list_opts()),
('iptables', ironic_inspector.conf.iptables.list_opts()),
('processing', ironic_inspector.conf.processing.list_opts()),
('pci_devices', ironic_inspector.conf.pci_devices.list_opts()),
('pxe_filter', ironic_inspector.conf.pxe_filter.list_opts()),
]

View File

@ -0,0 +1,34 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
_OPTS = [
cfg.MultiStrOpt('alias',
default=[],
help=_('An alias for PCI device identified by '
'\'vendor_id\' and \'product_id\' fields. Format: '
'{"vendor_id": "1234", "product_id": "5678", '
'"name": "pci_dev1"}')),
]
def register_opts(conf):
conf.register_opts(_OPTS, group='pci_devices')
def list_opts():
return _OPTS

View File

@ -0,0 +1,109 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
VALID_ADD_PORTS_VALUES = ('all', 'active', 'pxe', 'disabled')
VALID_KEEP_PORTS_VALUES = ('all', 'present', 'added')
VALID_STORE_DATA_VALUES = ('none', 'swift')
_OPTS = [
cfg.StrOpt('add_ports',
default='pxe',
help=_('Which MAC addresses to add as ports during '
'introspection. Possible values: all '
'(all MAC addresses), active (MAC addresses of NIC with '
'IP addresses), pxe (only MAC address of NIC node PXE '
'booted from, falls back to "active" if PXE MAC is not '
'supplied by the ramdisk).'),
choices=VALID_ADD_PORTS_VALUES),
cfg.StrOpt('keep_ports',
default='all',
help=_('Which ports (already present on a node) to keep after '
'introspection. Possible values: all (do not delete '
'anything), present (keep ports which MACs were present '
'in introspection data), added (keep only MACs that we '
'added during introspection).'),
choices=VALID_KEEP_PORTS_VALUES),
cfg.BoolOpt('overwrite_existing',
default=True,
help=_('Whether to overwrite existing values in node '
'database. Disable this option to make '
'introspection a non-destructive operation.')),
cfg.StrOpt('default_processing_hooks',
default='ramdisk_error,root_disk_selection,scheduler,'
'validate_interfaces,capabilities,pci_devices',
help=_('Comma-separated list of default hooks for processing '
'pipeline. Hook \'scheduler\' updates the node with the '
'minimum properties required by the Nova scheduler. '
'Hook \'validate_interfaces\' ensures that valid NIC '
'data was provided by the ramdisk. '
'Do not exclude these two unless you really know what '
'you\'re doing.')),
cfg.StrOpt('processing_hooks',
default='$default_processing_hooks',
help=_('Comma-separated list of enabled hooks for processing '
'pipeline. The default for this is '
'$default_processing_hooks, hooks can be added before '
'or after the defaults like this: '
'"prehook,$default_processing_hooks,posthook".')),
cfg.StrOpt('ramdisk_logs_dir',
help=_('If set, logs from ramdisk will be stored in this '
'directory.')),
cfg.BoolOpt('always_store_ramdisk_logs',
default=False,
help=_('Whether to store ramdisk logs even if it did not '
'return an error message (dependent upon '
'"ramdisk_logs_dir" option being set).')),
cfg.StrOpt('node_not_found_hook',
help=_('The name of the hook to run when inspector receives '
'inspection information from a node it isn\'t already '
'aware of. This hook is ignored by default.')),
cfg.StrOpt('store_data',
default='none',
choices=VALID_STORE_DATA_VALUES,
help=_('Method for storing introspection data. If set to \'none'
'\', introspection data will not be stored.')),
cfg.StrOpt('store_data_location',
help=_('Name of the key to store the location of stored data '
'in the extra column of the Ironic database.')),
cfg.BoolOpt('disk_partitioning_spacing',
default=True,
help=_('Whether to leave 1 GiB of disk size untouched for '
'partitioning. Only has effect when used with the IPA '
'as a ramdisk, for older ramdisk local_gb is '
'calculated on the ramdisk side.')),
cfg.StrOpt('ramdisk_logs_filename_format',
default='{uuid}_{dt:%Y%m%d-%H%M%S.%f}.tar.gz',
help=_('File name template for storing ramdisk logs. The '
'following replacements can be used: '
'{uuid} - node UUID or "unknown", '
'{bmc} - node BMC address or "unknown", '
'{dt} - current UTC date and time, '
'{mac} - PXE booting MAC or "unknown".')),
cfg.BoolOpt('power_off',
default=True,
help=_('Whether to power off a node after introspection.')),
]
def register_opts(conf):
conf.register_opts(_OPTS, 'processing')
def list_opts():
return _OPTS

View File

@ -0,0 +1,35 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
_OPTS = [
cfg.StrOpt('driver', default='iptables',
help=_('PXE boot filter driver to use, such as iptables')),
cfg.IntOpt('sync_period', default=15, min=0,
deprecated_name='firewall_update_period',
deprecated_group='firewall',
help=_('Amount of time in seconds, after which repeat periodic '
'update of the filter.')),
]
def register_opts(conf):
conf.register_opts(_OPTS, 'pxe_filter')
def list_opts():
return _OPTS

View File

@ -0,0 +1,54 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_config import cfg
from ironic_inspector.common.i18n import _
from ironic_inspector.common import keystone
SWIFT_GROUP = 'swift'
_OPTS = [
cfg.IntOpt('max_retries',
default=2,
help=_('Maximum number of times to retry a Swift request, '
'before failing.')),
cfg.IntOpt('delete_after',
default=0,
help=_('Number of seconds that the Swift object will last '
'before being deleted. (set to 0 to never delete the '
'object).')),
cfg.StrOpt('container',
default='ironic-inspector',
help=_('Default Swift container to use when creating '
'objects.')),
cfg.StrOpt('os_service_type',
default='object-store',
help=_('Swift service type.')),
cfg.StrOpt('os_endpoint_type',
default='internalURL',
help=_('Swift endpoint type.')),
cfg.StrOpt('os_region',
help=_('Keystone region to get endpoint for.')),
]
def register_opts(conf):
conf.register_opts(_OPTS, SWIFT_GROUP)
keystone.register_auth_opts(SWIFT_GROUP)
def list_opts():
return keystone.add_auth_options(_OPTS)

View File

@ -16,7 +16,6 @@ import os
import re
import flask
from oslo_config import cfg
from oslo_utils import uuidutils
import werkzeug
@ -25,14 +24,15 @@ from ironic_inspector.common import context
from ironic_inspector.common.i18n import _
from ironic_inspector.common import ironic as ir_utils
from ironic_inspector.common import swift
from ironic_inspector import conf # noqa
import ironic_inspector.conf
from ironic_inspector.conf import opts as conf_opts
from ironic_inspector import introspect
from ironic_inspector import node_cache
from ironic_inspector import process
from ironic_inspector import rules
from ironic_inspector import utils
CONF = cfg.CONF
CONF = ironic_inspector.conf.CONF
app = flask.Flask(__name__)
@ -45,7 +45,7 @@ _LOGGING_EXCLUDED_KEYS = ('logs',)
def _get_version():
ver = flask.request.headers.get(conf.VERSION_HEADER,
ver = flask.request.headers.get(conf_opts.VERSION_HEADER,
_DEFAULT_API_VERSION)
try:
requested = tuple(int(x) for x in ver.split('.'))
@ -103,8 +103,8 @@ def check_api_version():
@app.after_request
def add_version_headers(res):
res.headers[conf.MIN_VERSION_HEADER] = '%s.%s' % MINIMUM_API_VERSION
res.headers[conf.MAX_VERSION_HEADER] = '%s.%s' % CURRENT_API_VERSION
res.headers[conf_opts.MIN_VERSION_HEADER] = '%s.%s' % MINIMUM_API_VERSION
res.headers[conf_opts.MAX_VERSION_HEADER] = '%s.%s' % CURRENT_API_VERSION
return res

View File

@ -15,38 +15,11 @@
from oslo_config import cfg
from ironic_inspector.common.i18n import _
from ironic_inspector.plugins import base
from ironic_inspector import utils
DEFAULT_CPU_FLAGS_MAPPING = {
'vmx': 'cpu_vt',
'svm': 'cpu_vt',
'aes': 'cpu_aes',
'pse': 'cpu_hugepages',
'pdpe1gb': 'cpu_hugepages_1g',
'smx': 'cpu_txt',
}
CAPABILITIES_OPTS = [
cfg.BoolOpt('boot_mode',
default=False,
help=_('Whether to store the boot mode (BIOS or UEFI).')),
cfg.DictOpt('cpu_flags',
default=DEFAULT_CPU_FLAGS_MAPPING,
help=_('Mapping between a CPU flag and a capability to set '
'if this flag is present.')),
]
def list_opts():
return [
('capabilities', CAPABILITIES_OPTS)
]
CONF = cfg.CONF
CONF.register_opts(CAPABILITIES_OPTS, group='capabilities')
LOG = utils.getProcessingLogger(__name__)

View File

@ -21,21 +21,7 @@ from ironic_inspector import node_cache
from ironic_inspector import utils
DISCOVERY_OPTS = [
cfg.StrOpt('enroll_node_driver',
default='fake',
help=_('The name of the Ironic driver used by the enroll '
'hook when creating a new node in Ironic.')),
]
def list_opts():
return [
('discovery', DISCOVERY_OPTS)
]
CONF = cfg.CONF
CONF.register_opts(DISCOVERY_OPTS, group='discovery')
LOG = utils.getProcessingLogger(__name__)

View File

@ -25,7 +25,8 @@ from oslo_utils import uuidutils
from oslotest import base as test_base
from ironic_inspector.common import i18n
from ironic_inspector import conf
import ironic_inspector.conf
from ironic_inspector.conf import opts as conf_opts
from ironic_inspector import db
from ironic_inspector import introspection_state as istate
from ironic_inspector import node_cache
@ -33,7 +34,7 @@ from ironic_inspector.plugins import base as plugins_base
from ironic_inspector.test.unit import policy_fixture
from ironic_inspector import utils
CONF = conf.cfg.CONF
CONF = ironic_inspector.conf.CONF
class BaseTest(test_base.BaseTestCase):
@ -64,7 +65,7 @@ class BaseTest(test_base.BaseTestCase):
self.cfg.set_default('connection', "sqlite:///", group='database')
self.cfg.set_default('slave_connection', None, group='database')
self.cfg.set_default('max_retries', 10, group='database')
conf.parse_args([], default_config_files=[])
conf_opts.parse_args([], default_config_files=[])
self.policy = self.useFixture(policy_fixture.PolicyFixture())
def assertPatchEqual(self, expected, actual):

View File

@ -48,8 +48,7 @@ class KeystoneTest(base.BaseTest):
self.assertEqual(auth1, sess.auth)
def test_add_auth_options(self):
group, opts = keystone.add_auth_options([], TESTGROUP)[0]
self.assertEqual(TESTGROUP, group)
opts = keystone.add_auth_options([])
# check that there is no duplicates
names = {o.dest for o in opts}
self.assertEqual(len(names), len(opts))

View File

@ -16,11 +16,11 @@ import json
import unittest
import mock
from oslo_config import cfg
from oslo_utils import uuidutils
from ironic_inspector.common import ironic as ir_utils
from ironic_inspector import conf
import ironic_inspector.conf
from ironic_inspector.conf import opts as conf_opts
from ironic_inspector import introspect
from ironic_inspector import introspection_state as istate
from ironic_inspector import main
@ -32,7 +32,7 @@ from ironic_inspector import rules
from ironic_inspector.test import base as test_base
from ironic_inspector import utils
CONF = cfg.CONF
CONF = ironic_inspector.conf.CONF
def _get_error(res):
@ -431,7 +431,7 @@ class TestApiRules(BaseAPITest):
create_mock.return_value = mock.Mock(spec=rules.IntrospectionRule,
**{'as_dict.return_value': exp})
headers = {conf.VERSION_HEADER:
headers = {conf_opts.VERSION_HEADER:
main._format_version((1, 5))}
res = self.app.post('/v1/rules', data=json.dumps(data),
@ -510,9 +510,9 @@ class TestApiMisc(BaseAPITest):
class TestApiVersions(BaseAPITest):
def _check_version_present(self, res):
self.assertEqual('%d.%d' % main.MINIMUM_API_VERSION,
res.headers.get(conf.MIN_VERSION_HEADER))
res.headers.get(conf_opts.MIN_VERSION_HEADER))
self.assertEqual('%d.%d' % main.CURRENT_API_VERSION,
res.headers.get(conf.MAX_VERSION_HEADER))
res.headers.get(conf_opts.MAX_VERSION_HEADER))
def test_root_endpoint(self):
res = self.app.get("/")
@ -578,14 +578,14 @@ class TestApiVersions(BaseAPITest):
self.app.post('/v1/introspection/foobar'))
def test_request_correct_version(self):
headers = {conf.VERSION_HEADER:
headers = {conf_opts.VERSION_HEADER:
main._format_version(main.CURRENT_API_VERSION)}
self._check_version_present(self.app.get('/', headers=headers))
def test_request_unsupported_version(self):
bad_version = (main.CURRENT_API_VERSION[0],
main.CURRENT_API_VERSION[1] + 1)
headers = {conf.VERSION_HEADER:
headers = {conf_opts.VERSION_HEADER:
main._format_version(bad_version)}
res = self.app.get('/', headers=headers)
self._check_version_present(res)

View File

@ -62,14 +62,9 @@ ironic_inspector.pxe_filter =
iptables = ironic_inspector.pxe_filter.iptables:IptablesFilter
noop = ironic_inspector.pxe_filter.base:NoopFilter
oslo.config.opts =
ironic_inspector = ironic_inspector.conf:list_opts
ironic_inspector.common.ironic = ironic_inspector.common.ironic:list_opts
ironic_inspector.common.swift = ironic_inspector.common.swift:list_opts
ironic_inspector.plugins.discovery = ironic_inspector.plugins.discovery:list_opts
ironic_inspector.plugins.capabilities = ironic_inspector.plugins.capabilities:list_opts
ironic_inspector.plugins.pci_devices = ironic_inspector.plugins.pci_devices:list_opts
ironic_inspector = ironic_inspector.conf.opts:list_opts
oslo.config.opts.defaults =
ironic_inspector = ironic_inspector.conf:set_config_defaults
ironic_inspector = ironic_inspector.conf.opts:set_config_defaults
oslo.policy.enforcer =
ironic_inspector = ironic_inspector.policy:get_oslo_policy_enforcer
oslo.policy.policies =