Merge "Remove deprecated xclarity hardware type"
This commit is contained in:
commit
8a209f1372
@ -842,11 +842,6 @@ function is_deployed_by_irmc {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_deployed_by_xclarity {
|
|
||||||
[[ "$IRONIC_DEPLOY_DRIVER" == xclarity ]] && return 0
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_deployed_by_ibmc {
|
function is_deployed_by_ibmc {
|
||||||
[[ "$IRONIC_DEPLOY_DRIVER" == ibmc ]] && return 0
|
[[ "$IRONIC_DEPLOY_DRIVER" == ibmc ]] && return 0
|
||||||
return 1
|
return 1
|
||||||
@ -2603,13 +2598,6 @@ function enroll_nodes {
|
|||||||
if [[ -n "$IRONIC_DEPLOY_ISO_ID" ]]; then
|
if [[ -n "$IRONIC_DEPLOY_ISO_ID" ]]; then
|
||||||
node_options+=" --driver-info deploy_iso=$IRONIC_DEPLOY_ISO_ID"
|
node_options+=" --driver-info deploy_iso=$IRONIC_DEPLOY_ISO_ID"
|
||||||
fi
|
fi
|
||||||
elif is_deployed_by_xclarity; then
|
|
||||||
local xclarity_hardware_id
|
|
||||||
xclarity_hardware_id=$(echo $hardware_info |awk '{print $5}')
|
|
||||||
node_options+=" --driver-info xclarity_manager_ip=$bmc_address \
|
|
||||||
--driver-info xclarity_password=$bmc_passwd \
|
|
||||||
--driver-info xclarity_username=$bmc_username \
|
|
||||||
--driver-info xclarity_hardware_id=$xclarity_hardware_id"
|
|
||||||
elif is_deployed_by_ibmc; then
|
elif is_deployed_by_ibmc; then
|
||||||
node_options+=" --driver-info ibmc_address=$bmc_address \
|
node_options+=" --driver-info ibmc_address=$bmc_address \
|
||||||
--driver-info ibmc_username=$bmc_username \
|
--driver-info ibmc_username=$bmc_username \
|
||||||
|
@ -25,7 +25,6 @@ Hardware Types
|
|||||||
drivers/irmc
|
drivers/irmc
|
||||||
drivers/redfish
|
drivers/redfish
|
||||||
drivers/snmp
|
drivers/snmp
|
||||||
drivers/xclarity
|
|
||||||
drivers/fake
|
drivers/fake
|
||||||
|
|
||||||
Changing Hardware Types and Interfaces
|
Changing Hardware Types and Interfaces
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
===============
|
|
||||||
XClarity driver
|
|
||||||
===============
|
|
||||||
|
|
||||||
Overview
|
|
||||||
========
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
The ``xclarity`` driver has been deprecated and is anticipated to be removed
|
|
||||||
from Ironic at some point during or after the 2024.2 development cycle.
|
|
||||||
The anticipated forward management path is to migrate to the ``redfish``
|
|
||||||
hardware type.
|
|
||||||
|
|
||||||
The ``xclarity`` driver is targeted for IMM 2.0 and IMM 3.0 managed Lenovo
|
|
||||||
servers. The xclarity hardware type enables the user to take advantage of
|
|
||||||
`XClarity Manager`_ by using the `XClarity Python Client`_.
|
|
||||||
|
|
||||||
Prerequisites
|
|
||||||
=============
|
|
||||||
|
|
||||||
* The XClarity Client library should be installed on the ironic conductor
|
|
||||||
node(s).
|
|
||||||
|
|
||||||
For example, it can be installed with ``pip``::
|
|
||||||
|
|
||||||
sudo pip install python-xclarityclient
|
|
||||||
|
|
||||||
Enabling the XClarity driver
|
|
||||||
============================
|
|
||||||
|
|
||||||
#. Add ``xclarity`` to the list of ``enabled_hardware_types``,
|
|
||||||
``enabled_power_interfaces`` and ``enabled_management_interfaces``
|
|
||||||
in ``/etc/ironic/ironic.conf``. For example::
|
|
||||||
|
|
||||||
[DEFAULT]
|
|
||||||
...
|
|
||||||
enabled_hardware_types = ipmi,xclarity
|
|
||||||
enabled_power_interfaces = ipmitool,xclarity
|
|
||||||
enabled_management_interfaces = ipmitool,xclarity
|
|
||||||
|
|
||||||
#. Restart the ironic conductor service::
|
|
||||||
|
|
||||||
sudo service ironic-conductor restart
|
|
||||||
|
|
||||||
# Or, for RDO:
|
|
||||||
sudo systemctl restart openstack-ironic-conductor
|
|
||||||
|
|
||||||
Registering a node with the XClarity driver
|
|
||||||
===========================================
|
|
||||||
|
|
||||||
Nodes configured to use the driver should have the ``driver`` property
|
|
||||||
set to ``xclarity``.
|
|
||||||
|
|
||||||
The following properties are specified in the node's ``driver_info``
|
|
||||||
field and are required:
|
|
||||||
|
|
||||||
- ``xclarity_manager_ip``: The IP address of the XClarity Controller.
|
|
||||||
- ``xclarity_username``: User account with admin/server-profile access
|
|
||||||
privilege to the XClarity Controller.
|
|
||||||
- ``xclarity_password``: User account password corresponding to the
|
|
||||||
xclarity_username to the XClarity Controller.
|
|
||||||
- ``xclarity_hardware_id``: The hardware ID of the XClarity managed server.
|
|
||||||
|
|
||||||
The ``baremetal node create`` command can be used to enroll
|
|
||||||
a node with the ``xclarity`` driver. For example:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
baremetal node create --driver xclarity \
|
|
||||||
--driver-info xclarity_manager_ip=https://10.240.217.101 \
|
|
||||||
--driver-info xclarity_username=admin \
|
|
||||||
--driver-info xclarity_password=password \
|
|
||||||
--driver-info xclarity_hardware_id=hardware_id
|
|
||||||
|
|
||||||
For more information about enrolling nodes see :ref:`enrollment`
|
|
||||||
in the install guide.
|
|
||||||
|
|
||||||
.. _`XClarity Manager`: http://www3.lenovo.com/us/en/data-center/software/systems-management/xclarity/
|
|
||||||
.. _`XClarity Python Client`: http://pypi.org/project/python-xclarityclient/
|
|
@ -10,7 +10,6 @@ pyasn1>=0.5.1 # BSD
|
|||||||
pyasn1-modules>=0.3.0 # BSD
|
pyasn1-modules>=0.3.0 # BSD
|
||||||
python-scciclient>=0.16.0,<0.17.0
|
python-scciclient>=0.16.0,<0.17.0
|
||||||
python-dracclient>=5.1.0,<9.0.0
|
python-dracclient>=5.1.0,<9.0.0
|
||||||
python-xclarityclient>=0.1.6
|
|
||||||
|
|
||||||
# Ansible-deploy interface
|
# Ansible-deploy interface
|
||||||
ansible>=2.7
|
ansible>=2.7
|
||||||
|
@ -651,10 +651,6 @@ class InstanceUnrescueFailure(IronicException):
|
|||||||
'%(node)s: %(reason)s')
|
'%(node)s: %(reason)s')
|
||||||
|
|
||||||
|
|
||||||
class XClarityError(IronicException):
|
|
||||||
_msg_fmt = _("XClarity exception occurred. Error: %(error)s")
|
|
||||||
|
|
||||||
|
|
||||||
class BIOSSettingAlreadyExists(Conflict):
|
class BIOSSettingAlreadyExists(Conflict):
|
||||||
_msg_fmt = _('A BIOS setting %(name)s for node %(node)s already exists.')
|
_msg_fmt = _('A BIOS setting %(name)s for node %(node)s already exists.')
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ from ironic.conf import sensor_data
|
|||||||
from ironic.conf import service_catalog
|
from ironic.conf import service_catalog
|
||||||
from ironic.conf import snmp
|
from ironic.conf import snmp
|
||||||
from ironic.conf import swift
|
from ironic.conf import swift
|
||||||
from ironic.conf import xclarity
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
@ -87,4 +86,3 @@ sensor_data.register_opts(CONF)
|
|||||||
service_catalog.register_opts(CONF)
|
service_catalog.register_opts(CONF)
|
||||||
snmp.register_opts(CONF)
|
snmp.register_opts(CONF)
|
||||||
swift.register_opts(CONF)
|
swift.register_opts(CONF)
|
||||||
xclarity.register_opts(CONF)
|
|
||||||
|
@ -47,7 +47,6 @@ _opts = [
|
|||||||
('service_catalog', ironic.conf.service_catalog.list_opts()),
|
('service_catalog', ironic.conf.service_catalog.list_opts()),
|
||||||
('snmp', ironic.conf.snmp.opts),
|
('snmp', ironic.conf.snmp.opts),
|
||||||
('swift', ironic.conf.swift.list_opts()),
|
('swift', ironic.conf.swift.list_opts()),
|
||||||
('xclarity', ironic.conf.xclarity.opts),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
# Copyright 2017 LENOVO Development Company, LP
|
|
||||||
#
|
|
||||||
# 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.common.i18n import _
|
|
||||||
|
|
||||||
opts = [
|
|
||||||
cfg.StrOpt('manager_ip',
|
|
||||||
help=_('IP address of the XClarity Controller. '
|
|
||||||
'Configuration here is deprecated and will be removed '
|
|
||||||
'in the Stein release. Please update the driver_info '
|
|
||||||
'field to use "xclarity_manager_ip" instead')),
|
|
||||||
cfg.StrOpt('username',
|
|
||||||
help=_('Username for the XClarity Controller. '
|
|
||||||
'Configuration here is deprecated and will be removed '
|
|
||||||
'in the Stein release. Please update the driver_info '
|
|
||||||
'field to use "xclarity_username" instead')),
|
|
||||||
cfg.StrOpt('password',
|
|
||||||
secret=True,
|
|
||||||
help=_('Password for XClarity Controller username. '
|
|
||||||
'Configuration here is deprecated and will be removed '
|
|
||||||
'in the Stein release. Please update the driver_info '
|
|
||||||
'field to use "xclarity_password" instead')),
|
|
||||||
cfg.PortOpt('port',
|
|
||||||
default=443,
|
|
||||||
help=_('Port to be used for XClarity Controller '
|
|
||||||
'connection.')),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
|
||||||
conf.register_opts(opts, group='xclarity')
|
|
@ -1,178 +0,0 @@
|
|||||||
# Copyright 2017 Lenovo, Inc.
|
|
||||||
#
|
|
||||||
# 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_log import log as logging
|
|
||||||
from oslo_utils import importutils
|
|
||||||
|
|
||||||
from ironic.common import exception
|
|
||||||
from ironic.common.i18n import _
|
|
||||||
from ironic.common import states
|
|
||||||
from ironic.common import utils
|
|
||||||
from ironic.conf import CONF
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
client = importutils.try_import('xclarity_client.client')
|
|
||||||
xclarity_client_constants = importutils.try_import('xclarity_client.constants')
|
|
||||||
xclarity_client_exceptions = importutils.try_import(
|
|
||||||
'xclarity_client.exceptions')
|
|
||||||
|
|
||||||
REQUIRED_ON_DRIVER_INFO = {
|
|
||||||
'xclarity_manager_ip': _("IP address of the XClarity Controller."),
|
|
||||||
'xclarity_username': _("Username for the XClarity Controller "
|
|
||||||
"with administrator privileges."),
|
|
||||||
'xclarity_password': _("Password for xclarity_username."),
|
|
||||||
'xclarity_hardware_id': _("Server Hardware ID managed by XClarity."),
|
|
||||||
}
|
|
||||||
|
|
||||||
OPTIONAL_ON_DRIVER_INFO = {
|
|
||||||
'xclarity_port': _("Port to be used for XClarity Controller connection. "
|
|
||||||
"Optional"),
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMON_PROPERTIES = {}
|
|
||||||
COMMON_PROPERTIES.update(REQUIRED_ON_DRIVER_INFO)
|
|
||||||
COMMON_PROPERTIES.update(OPTIONAL_ON_DRIVER_INFO)
|
|
||||||
|
|
||||||
|
|
||||||
def get_properties():
|
|
||||||
return COMMON_PROPERTIES
|
|
||||||
|
|
||||||
|
|
||||||
def parse_driver_info(node):
|
|
||||||
"""Parse a node's driver_info values.
|
|
||||||
|
|
||||||
Parses the driver_info of the node, reads default values
|
|
||||||
and returns a dict containing the combination of both.
|
|
||||||
|
|
||||||
:param node: an ironic node object to get information from.
|
|
||||||
:returns: a dict containing information parsed from driver_info.
|
|
||||||
:raises: InvalidParameterValue if some required information
|
|
||||||
is missing on the node or inputs is invalid.
|
|
||||||
"""
|
|
||||||
driver_info = node.driver_info
|
|
||||||
parsed_driver_info = {}
|
|
||||||
|
|
||||||
error_msgs = []
|
|
||||||
for param in REQUIRED_ON_DRIVER_INFO:
|
|
||||||
if param == "xclarity_hardware_id":
|
|
||||||
try:
|
|
||||||
parsed_driver_info[param] = str(driver_info[param])
|
|
||||||
except KeyError:
|
|
||||||
error_msgs.append(_("'%s' not provided to XClarity.") % param)
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
error_msgs.append(_("'%s' contains non-ASCII symbol.") % param)
|
|
||||||
else:
|
|
||||||
# corresponding config names don't have 'xclarity_' prefix
|
|
||||||
if param in driver_info:
|
|
||||||
parsed_driver_info[param] = str(driver_info[param])
|
|
||||||
elif param not in driver_info and\
|
|
||||||
CONF.xclarity.get(param[len('xclarity_'):]) is not None:
|
|
||||||
parsed_driver_info[param] = str(
|
|
||||||
CONF.xclarity.get(param[len('xclarity_'):]))
|
|
||||||
LOG.warning('The configuration [xclarity]/%(config)s '
|
|
||||||
'is deprecated and will be removed in the '
|
|
||||||
'Stein release. Please update the node '
|
|
||||||
'%(node_uuid)s driver_info field to use '
|
|
||||||
'"%(field)s" instead',
|
|
||||||
{'config': param[len('xclarity_'):],
|
|
||||||
'node_uuid': node.uuid, 'field': param})
|
|
||||||
else:
|
|
||||||
error_msgs.append(_("'%s' not provided to XClarity.") % param)
|
|
||||||
|
|
||||||
port = driver_info.get('xclarity_port', CONF.xclarity.get('port'))
|
|
||||||
parsed_driver_info['xclarity_port'] = utils.validate_network_port(
|
|
||||||
port, 'xclarity_port')
|
|
||||||
|
|
||||||
if error_msgs:
|
|
||||||
msg = (_('The following errors were encountered while parsing '
|
|
||||||
'driver_info:\n%s') % '\n'.join(error_msgs))
|
|
||||||
raise exception.InvalidParameterValue(msg)
|
|
||||||
|
|
||||||
return parsed_driver_info
|
|
||||||
|
|
||||||
|
|
||||||
def get_xclarity_client(node):
|
|
||||||
"""Generates an instance of the XClarity client.
|
|
||||||
|
|
||||||
Generates an instance of the XClarity client using the imported
|
|
||||||
xclarity_client library.
|
|
||||||
|
|
||||||
:param node: an ironic node object.
|
|
||||||
:returns: an instance of the XClarity client
|
|
||||||
:raises: XClarityError if can't get to the XClarity client
|
|
||||||
"""
|
|
||||||
driver_info = parse_driver_info(node)
|
|
||||||
try:
|
|
||||||
xclarity_client = client.Client(
|
|
||||||
ip=driver_info.get('xclarity_manager_ip'),
|
|
||||||
username=driver_info.get('xclarity_username'),
|
|
||||||
password=driver_info.get('xclarity_password'),
|
|
||||||
port=driver_info.get('xclarity_port')
|
|
||||||
)
|
|
||||||
except xclarity_client_exceptions.XClarityError as exc:
|
|
||||||
msg = (_("Error getting connection to XClarity address: %(ip)s. "
|
|
||||||
"Error: %(exc)s"),
|
|
||||||
{'ip': driver_info.get('xclarity_manager_ip'), 'exc': exc})
|
|
||||||
raise exception.XClarityError(error=msg)
|
|
||||||
return xclarity_client
|
|
||||||
|
|
||||||
|
|
||||||
def get_server_hardware_id(node):
|
|
||||||
"""Validates node configuration and returns xclarity hardware id.
|
|
||||||
|
|
||||||
Validates whether node configuration is consistent with XClarity and
|
|
||||||
returns the XClarity Hardware ID for a specific node.
|
|
||||||
:param node: node object to get information from
|
|
||||||
:returns: the XClarity Hardware ID for a specific node
|
|
||||||
:raises: MissingParameterValue if unable to validate XClarity Hardware ID
|
|
||||||
|
|
||||||
"""
|
|
||||||
xclarity_hardware_id = node.driver_info.get('xclarity_hardware_id')
|
|
||||||
if not xclarity_hardware_id:
|
|
||||||
msg = (_("Error validating node driver info, "
|
|
||||||
"server uuid: %s missing xclarity_hardware_id") %
|
|
||||||
node.uuid)
|
|
||||||
raise exception.MissingParameterValue(err=msg)
|
|
||||||
return xclarity_hardware_id
|
|
||||||
|
|
||||||
|
|
||||||
def translate_xclarity_power_state(power_state):
|
|
||||||
"""Translates XClarity's power state strings to be consistent with Ironic.
|
|
||||||
|
|
||||||
:param power_state: power state string to be translated
|
|
||||||
:returns: the translated power state
|
|
||||||
"""
|
|
||||||
power_states_map = {
|
|
||||||
xclarity_client_constants.STATE_POWER_ON: states.POWER_ON,
|
|
||||||
xclarity_client_constants.STATE_POWER_OFF: states.POWER_OFF,
|
|
||||||
}
|
|
||||||
|
|
||||||
return power_states_map.get(power_state, states.ERROR)
|
|
||||||
|
|
||||||
|
|
||||||
def translate_xclarity_power_action(power_action):
|
|
||||||
"""Translates ironic's power action strings to XClarity's format.
|
|
||||||
|
|
||||||
:param power_action: power action string to be translated
|
|
||||||
:returns: the power action translated
|
|
||||||
"""
|
|
||||||
|
|
||||||
power_action_map = {
|
|
||||||
states.POWER_ON: xclarity_client_constants.ACTION_POWER_ON,
|
|
||||||
states.POWER_OFF: xclarity_client_constants.ACTION_POWER_OFF,
|
|
||||||
states.REBOOT: xclarity_client_constants.ACTION_REBOOT
|
|
||||||
}
|
|
||||||
|
|
||||||
return power_action_map[power_action]
|
|
@ -1,248 +0,0 @@
|
|||||||
# Copyright 2017 Lenovo, Inc.
|
|
||||||
#
|
|
||||||
# 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 ironic_lib import metrics_utils
|
|
||||||
from oslo_log import log as logging
|
|
||||||
from oslo_utils import importutils
|
|
||||||
|
|
||||||
from ironic.common import boot_devices
|
|
||||||
from ironic.common import exception
|
|
||||||
from ironic.common.i18n import _
|
|
||||||
from ironic.conductor import task_manager
|
|
||||||
from ironic.drivers import base
|
|
||||||
from ironic.drivers.modules.xclarity import common
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
METRICS = metrics_utils.get_metrics_logger(__name__)
|
|
||||||
|
|
||||||
xclarity_client_exceptions = importutils.try_import(
|
|
||||||
'xclarity_client.exceptions')
|
|
||||||
|
|
||||||
BOOT_DEVICE_MAPPING_TO_XCLARITY = {
|
|
||||||
boot_devices.PXE: 'PXE Network',
|
|
||||||
boot_devices.DISK: 'Hard Disk 0',
|
|
||||||
boot_devices.CDROM: 'CD/DVD Rom',
|
|
||||||
boot_devices.BIOS: 'Boot To F1'
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOT_DEVICE_MAPPING_FROM_XCLARITY = {
|
|
||||||
v: k for k, v in BOOT_DEVICE_MAPPING_TO_XCLARITY.items()}
|
|
||||||
|
|
||||||
SUPPORTED_BOOT_DEVICES = [
|
|
||||||
boot_devices.PXE,
|
|
||||||
boot_devices.DISK,
|
|
||||||
boot_devices.CDROM,
|
|
||||||
boot_devices.BIOS,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class XClarityManagement(base.ManagementInterface):
|
|
||||||
|
|
||||||
# NOTE(TheJulia): Deprecating November 2023 in favor of Redfish
|
|
||||||
# and due to a lack of active driver maintenance.
|
|
||||||
supported = False
|
|
||||||
|
|
||||||
def get_properties(self):
|
|
||||||
return common.COMMON_PROPERTIES
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityManagement.validate')
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the driver-specific info supplied.
|
|
||||||
|
|
||||||
This method validates if the 'driver_info' property of the supplied
|
|
||||||
task's node contains the required information for this driver to
|
|
||||||
manage the node.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
"""
|
|
||||||
common.parse_driver_info(task.node)
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityManagement.get_supported_boot_devices')
|
|
||||||
def get_supported_boot_devices(self, task):
|
|
||||||
"""Gets a list of the supported boot devices.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:returns: A list with the supported boot devices defined
|
|
||||||
in :mod:`ironic.common.boot_devices`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
return SUPPORTED_BOOT_DEVICES
|
|
||||||
|
|
||||||
def _validate_supported_boot_device(self, task, boot_device):
|
|
||||||
"""It validates if the boot device is supported by XClarity.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:param boot_device: the boot device in XClarity format, one of
|
|
||||||
['PXE Network', 'Hard Disk 0', 'CD/DVD Rom', 'Boot To F1']
|
|
||||||
:raises: InvalidParameterValue if the boot device is not supported.
|
|
||||||
"""
|
|
||||||
if boot_device not in BOOT_DEVICE_MAPPING_FROM_XCLARITY:
|
|
||||||
raise exception.InvalidParameterValue(
|
|
||||||
_("Unsupported boot device %(device)s for node: %(node)s ")
|
|
||||||
% {"device": boot_device, "node": task.node.uuid}
|
|
||||||
)
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityManagement.get_boot_device')
|
|
||||||
def get_boot_device(self, task):
|
|
||||||
"""Get the current boot device for the task's node.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:returns: a dictionary containing:
|
|
||||||
:boot_device: the boot device, one of [PXE, DISK, CDROM, BIOS]
|
|
||||||
:persistent: Whether the boot device will persist or not
|
|
||||||
It returns None if boot device is unknown.
|
|
||||||
:raises: InvalidParameterValue if the boot device is unknown
|
|
||||||
:raises: XClarityError if the communication with XClarity fails
|
|
||||||
"""
|
|
||||||
node = task.node
|
|
||||||
client = common.get_xclarity_client(node)
|
|
||||||
server_hardware_id = common.get_server_hardware_id(node)
|
|
||||||
try:
|
|
||||||
boot_info = (
|
|
||||||
client.get_node_all_boot_info(
|
|
||||||
server_hardware_id)
|
|
||||||
)
|
|
||||||
except xclarity_client_exceptions.XClarityError as xclarity_exc:
|
|
||||||
LOG.error(
|
|
||||||
"Error getting boot device from XClarity for node %(node)s. "
|
|
||||||
"Error: %(error)s", {'node': node.uuid,
|
|
||||||
'error': xclarity_exc})
|
|
||||||
raise exception.XClarityError(error=xclarity_exc)
|
|
||||||
|
|
||||||
persistent = False
|
|
||||||
primary = None
|
|
||||||
boot_order = boot_info['bootOrder']['bootOrderList']
|
|
||||||
for item in boot_order:
|
|
||||||
current = item.get('currentBootOrderDevices')
|
|
||||||
if current is None:
|
|
||||||
LOG.warning(
|
|
||||||
'Current boot order is None from XClarity for '
|
|
||||||
'node %(node)s. Please check the hardware and '
|
|
||||||
'XClarity connection', {'node': node.uuid, })
|
|
||||||
return {'boot_device': None, 'persistent': None}
|
|
||||||
else:
|
|
||||||
primary = current[0]
|
|
||||||
boot_type = item.get('bootType')
|
|
||||||
if boot_type == "SingleUse":
|
|
||||||
persistent = False
|
|
||||||
if primary != 'None':
|
|
||||||
self._validate_supported_boot_device(task, primary)
|
|
||||||
boot_device = {
|
|
||||||
'boot_device':
|
|
||||||
BOOT_DEVICE_MAPPING_FROM_XCLARITY.get(primary),
|
|
||||||
'persistent': persistent
|
|
||||||
}
|
|
||||||
return boot_device
|
|
||||||
elif boot_type == "Permanent":
|
|
||||||
persistent = True
|
|
||||||
if primary != 'None':
|
|
||||||
self._validate_supported_boot_device(task, primary)
|
|
||||||
boot_device = {
|
|
||||||
'boot_device':
|
|
||||||
BOOT_DEVICE_MAPPING_FROM_XCLARITY.get(primary),
|
|
||||||
'persistent': persistent
|
|
||||||
}
|
|
||||||
return boot_device
|
|
||||||
else:
|
|
||||||
return {'boot_device': None, 'persistent': None}
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityManagement.set_boot_device')
|
|
||||||
@task_manager.require_exclusive_lock
|
|
||||||
def set_boot_device(self, task, device, persistent=False):
|
|
||||||
"""Sets the boot device for a node.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
:param device: the boot device, one of the supported devices
|
|
||||||
listed in :mod:`ironic.common.boot_devices`.
|
|
||||||
:param persistent: Boolean value. True if the boot device will
|
|
||||||
persist to all future boots, False if not.
|
|
||||||
Default: False.
|
|
||||||
:raises: InvalidParameterValue if an invalid boot device is
|
|
||||||
specified.
|
|
||||||
:raises: XClarityError if the communication with XClarity fails
|
|
||||||
"""
|
|
||||||
node = task.node
|
|
||||||
xc_device = self._translate_ironic_to_xclarity(device)
|
|
||||||
|
|
||||||
server_hardware_id = common.get_server_hardware_id(node)
|
|
||||||
LOG.debug("Setting boot device to %(device)s for node %(node)s",
|
|
||||||
{"device": device, "node": node.uuid})
|
|
||||||
self._set_boot_device(task, server_hardware_id, xc_device,
|
|
||||||
singleuse=not persistent)
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityManagement.get_sensors_data')
|
|
||||||
def get_sensors_data(self, task):
|
|
||||||
"""Get sensors data.
|
|
||||||
|
|
||||||
:param task: a TaskManager instance.
|
|
||||||
:raises: NotImplementedError
|
|
||||||
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def _translate_ironic_to_xclarity(self, boot_device):
|
|
||||||
"""Translates Ironic boot options to Xclarity boot options.
|
|
||||||
|
|
||||||
:param boot_device: Ironic boot_device
|
|
||||||
:returns: Translated XClarity boot_device.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return BOOT_DEVICE_MAPPING_TO_XCLARITY.get(boot_device)
|
|
||||||
|
|
||||||
def _set_boot_device(self, task, server_hardware_id,
|
|
||||||
new_primary_boot_device, singleuse=False):
|
|
||||||
"""Set the current boot device for xclarity
|
|
||||||
|
|
||||||
:param server_hardware_id: the uri of the server hardware in XClarity
|
|
||||||
:param new_primary_boot_device: boot device to be set
|
|
||||||
:param task: a TaskManager instance.
|
|
||||||
:param singleuse: if this device will be used only once at next boot
|
|
||||||
"""
|
|
||||||
node = task.node
|
|
||||||
client = common.get_xclarity_client(node)
|
|
||||||
boot_info = client.get_node_all_boot_info(
|
|
||||||
server_hardware_id)
|
|
||||||
current = []
|
|
||||||
LOG.debug(
|
|
||||||
("Setting boot device to %(device)s for XClarity "
|
|
||||||
"node %(node)s"),
|
|
||||||
{'device': new_primary_boot_device, 'node': node.uuid}
|
|
||||||
)
|
|
||||||
for item in boot_info['bootOrder']['bootOrderList']:
|
|
||||||
if singleuse and item['bootType'] == 'SingleUse':
|
|
||||||
item['currentBootOrderDevices'][0] = new_primary_boot_device
|
|
||||||
elif not singleuse and item['bootType'] == 'Permanent':
|
|
||||||
current = item['currentBootOrderDevices']
|
|
||||||
if new_primary_boot_device == current[0]:
|
|
||||||
return
|
|
||||||
if new_primary_boot_device in current:
|
|
||||||
current.remove(new_primary_boot_device)
|
|
||||||
current.insert(0, new_primary_boot_device)
|
|
||||||
item['currentBootOrderDevices'] = current
|
|
||||||
|
|
||||||
try:
|
|
||||||
client.set_node_boot_info(server_hardware_id,
|
|
||||||
boot_info,
|
|
||||||
new_primary_boot_device,
|
|
||||||
singleuse)
|
|
||||||
except xclarity_client_exceptions.XClarityError as xclarity_exc:
|
|
||||||
LOG.error(
|
|
||||||
('Error setting boot device %(boot_device)s for the XClarity '
|
|
||||||
'node %(node)s. Error: %(error)s'),
|
|
||||||
{'boot_device': new_primary_boot_device, 'node': node.uuid,
|
|
||||||
'error': xclarity_exc}
|
|
||||||
)
|
|
||||||
raise exception.XClarityError(error=xclarity_exc)
|
|
@ -1,134 +0,0 @@
|
|||||||
# Copyright 2017 Lenovo, Inc.
|
|
||||||
#
|
|
||||||
# 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 ironic_lib import metrics_utils
|
|
||||||
from oslo_log import log as logging
|
|
||||||
from oslo_utils import importutils
|
|
||||||
|
|
||||||
from ironic.common import exception
|
|
||||||
from ironic.common import states
|
|
||||||
from ironic.conductor import task_manager
|
|
||||||
from ironic.drivers import base
|
|
||||||
from ironic.drivers.modules.xclarity import common
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
METRICS = metrics_utils.get_metrics_logger(__name__)
|
|
||||||
|
|
||||||
xclarity_client_exceptions = importutils.try_import(
|
|
||||||
'xclarity_client.exceptions')
|
|
||||||
|
|
||||||
|
|
||||||
class XClarityPower(base.PowerInterface):
|
|
||||||
|
|
||||||
# NOTE(TheJulia): Deprecating November 2023 in favor of Redfish
|
|
||||||
# and due to a lack of active driver maintenance.
|
|
||||||
supported = False
|
|
||||||
|
|
||||||
def get_properties(self):
|
|
||||||
return common.get_properties()
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityPower.validate')
|
|
||||||
def validate(self, task):
|
|
||||||
"""Validate the driver-specific info supplied.
|
|
||||||
|
|
||||||
This method validates if the 'driver_info' property of the supplied
|
|
||||||
task's node contains the required information for this driver to
|
|
||||||
manage the power state of the node.
|
|
||||||
|
|
||||||
:param task: a task from TaskManager.
|
|
||||||
"""
|
|
||||||
common.parse_driver_info(task.node)
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityPower.get_power_state')
|
|
||||||
def get_power_state(self, task):
|
|
||||||
"""Gets the current power state.
|
|
||||||
|
|
||||||
:param task: a TaskManager instance.
|
|
||||||
:returns: one of :mod:`ironic.common.states` POWER_OFF,
|
|
||||||
POWER_ON or ERROR.
|
|
||||||
:raises: XClarityError if fails to retrieve power state of XClarity
|
|
||||||
resource
|
|
||||||
"""
|
|
||||||
node = task.node
|
|
||||||
client = common.get_xclarity_client(node)
|
|
||||||
server_hardware_id = common.get_server_hardware_id(node)
|
|
||||||
try:
|
|
||||||
power_state = client.get_node_power_status(server_hardware_id)
|
|
||||||
except xclarity_client_exceptions.XClarityError as xclarity_exc:
|
|
||||||
LOG.error(
|
|
||||||
("Error getting power state for node %(node)s. Error: "
|
|
||||||
"%(error)s"),
|
|
||||||
{'node': node.uuid, 'error': xclarity_exc}
|
|
||||||
)
|
|
||||||
raise exception.XClarityError(error=xclarity_exc)
|
|
||||||
return common.translate_xclarity_power_state(power_state)
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityPower.set_power_state')
|
|
||||||
@task_manager.require_exclusive_lock
|
|
||||||
def set_power_state(self, task, power_state, timeout=None):
|
|
||||||
"""Turn the current power state on or off.
|
|
||||||
|
|
||||||
:param task: a TaskManager instance.
|
|
||||||
:param power_state: The desired power state POWER_ON, POWER_OFF or
|
|
||||||
REBOOT from :mod:`ironic.common.states`.
|
|
||||||
:param timeout: timeout (in seconds). Unsupported by this interface.
|
|
||||||
:raises: InvalidParameterValue if an invalid power state was specified.
|
|
||||||
:raises: XClarityError if XClarity fails setting the power state.
|
|
||||||
"""
|
|
||||||
# TODO(rloo): Support timeouts!
|
|
||||||
if timeout is not None:
|
|
||||||
LOG.warning(
|
|
||||||
"The 'xclarity' Power Interface's 'set_power_state' method "
|
|
||||||
"doesn't support the 'timeout' parameter. Ignoring "
|
|
||||||
"timeout=%(timeout)s",
|
|
||||||
{'timeout': timeout})
|
|
||||||
|
|
||||||
if power_state == states.REBOOT:
|
|
||||||
target_power_state = self.get_power_state(task)
|
|
||||||
if target_power_state == states.POWER_OFF:
|
|
||||||
power_state = states.POWER_ON
|
|
||||||
|
|
||||||
node = task.node
|
|
||||||
client = common.get_xclarity_client(node)
|
|
||||||
server_hardware_id = common.get_server_hardware_id(node)
|
|
||||||
LOG.debug("Setting power state of node %(node_uuid)s to "
|
|
||||||
"%(power_state)s",
|
|
||||||
{'node_uuid': node.uuid, 'power_state': power_state})
|
|
||||||
|
|
||||||
try:
|
|
||||||
client.set_node_power_status(server_hardware_id, power_state)
|
|
||||||
except xclarity_client_exceptions.XClarityError as xclarity_exc:
|
|
||||||
LOG.error(
|
|
||||||
"Error setting power state of node %(node_uuid)s to "
|
|
||||||
"%(power_state)s",
|
|
||||||
{'node_uuid': task.node.uuid, 'power_state': power_state})
|
|
||||||
raise exception.XClarityError(error=xclarity_exc)
|
|
||||||
|
|
||||||
@METRICS.timer('XClarityPower.reboot')
|
|
||||||
@task_manager.require_exclusive_lock
|
|
||||||
def reboot(self, task, timeout=None):
|
|
||||||
"""Soft reboot the node
|
|
||||||
|
|
||||||
:param task: a TaskManager instance.
|
|
||||||
:param timeout: timeout (in seconds). Unsupported by this interface.
|
|
||||||
"""
|
|
||||||
# TODO(rloo): Support timeouts!
|
|
||||||
if timeout is not None:
|
|
||||||
LOG.warning("The 'xclarity' Power Interface's 'reboot' method "
|
|
||||||
"doesn't support the 'timeout' parameter. Ignoring "
|
|
||||||
"timeout=%(timeout)s",
|
|
||||||
{'timeout': timeout})
|
|
||||||
|
|
||||||
self.set_power_state(task, states.REBOOT)
|
|
@ -1,35 +0,0 @@
|
|||||||
# Copyright 2017 Lenovo, Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""
|
|
||||||
XClarity Driver and supporting meta-classes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from ironic.drivers import generic
|
|
||||||
from ironic.drivers.modules.xclarity import management
|
|
||||||
from ironic.drivers.modules.xclarity import power
|
|
||||||
|
|
||||||
|
|
||||||
class XClarityHardware(generic.GenericHardware):
|
|
||||||
"""XClarity hardware type. """
|
|
||||||
|
|
||||||
@property
|
|
||||||
def supported_management_interfaces(self):
|
|
||||||
"""List of supported management interfaces."""
|
|
||||||
return [management.XClarityManagement]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def supported_power_interfaces(self):
|
|
||||||
"""List of supported power interfaces."""
|
|
||||||
return [power.XClarityPower]
|
|
@ -514,24 +514,6 @@ def create_test_node_tag(**kw):
|
|||||||
return dbapi.add_node_tag(tag['node_id'], tag['tag'])
|
return dbapi.add_node_tag(tag['node_id'], tag['tag'])
|
||||||
|
|
||||||
|
|
||||||
def get_test_xclarity_properties():
|
|
||||||
return {
|
|
||||||
"cpu_arch": "x86_64",
|
|
||||||
"local_gb": "10",
|
|
||||||
"memory_mb": "4096",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_test_xclarity_driver_info():
|
|
||||||
return {
|
|
||||||
'xclarity_manager_ip': "1.2.3.4",
|
|
||||||
'xclarity_username': "USERID",
|
|
||||||
'xclarity_password': "fake",
|
|
||||||
'xclarity_port': 443,
|
|
||||||
'xclarity_hardware_id': 'fake_sh_id',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_test_node_trait(**kw):
|
def get_test_node_trait(**kw):
|
||||||
return {
|
return {
|
||||||
'version': kw.get('version', trait.Trait.VERSION),
|
'version': kw.get('version', trait.Trait.VERSION),
|
||||||
|
@ -1,113 +0,0 @@
|
|||||||
# Copyright 2017 Lenovo, Inc.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# 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 unittest import mock
|
|
||||||
|
|
||||||
from oslo_utils import importutils
|
|
||||||
|
|
||||||
from ironic.common import exception
|
|
||||||
from ironic.drivers.modules.xclarity import common
|
|
||||||
from ironic.tests.unit.db import base as db_base
|
|
||||||
from ironic.tests.unit.db import utils as db_utils
|
|
||||||
from ironic.tests.unit.objects import utils as obj_utils
|
|
||||||
|
|
||||||
xclarity_client = importutils.try_import('xclarity_client.client')
|
|
||||||
xclarity_exceptions = importutils.try_import('xclarity_client.exceptions')
|
|
||||||
xclarity_constants = importutils.try_import('xclarity_client.constants')
|
|
||||||
|
|
||||||
INFO_DICT = db_utils.get_test_xclarity_driver_info()
|
|
||||||
|
|
||||||
|
|
||||||
class XClarityCommonTestCase(db_base.DbTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(XClarityCommonTestCase, self).setUp()
|
|
||||||
self.config(enabled_hardware_types=['xclarity'],
|
|
||||||
enabled_power_interfaces=['xclarity'],
|
|
||||||
enabled_management_interfaces=['xclarity'])
|
|
||||||
self.node = obj_utils.create_test_node(
|
|
||||||
self.context, driver='xclarity',
|
|
||||||
properties=db_utils.get_test_xclarity_properties(),
|
|
||||||
driver_info=INFO_DICT)
|
|
||||||
|
|
||||||
def test_parse_driver_info(self):
|
|
||||||
info = common.parse_driver_info(self.node)
|
|
||||||
self.assertEqual(INFO_DICT['xclarity_manager_ip'],
|
|
||||||
info['xclarity_manager_ip'])
|
|
||||||
self.assertEqual(INFO_DICT['xclarity_username'],
|
|
||||||
info['xclarity_username'])
|
|
||||||
self.assertEqual(INFO_DICT['xclarity_password'],
|
|
||||||
info['xclarity_password'])
|
|
||||||
self.assertEqual(INFO_DICT['xclarity_port'], info['xclarity_port'])
|
|
||||||
self.assertEqual(INFO_DICT['xclarity_hardware_id'],
|
|
||||||
info['xclarity_hardware_id'])
|
|
||||||
|
|
||||||
def test_parse_driver_info_missing_hardware_id(self):
|
|
||||||
del self.node.driver_info['xclarity_hardware_id']
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
common.parse_driver_info, self.node)
|
|
||||||
|
|
||||||
def test_parse_driver_info_get_param_from_config(self):
|
|
||||||
del self.node.driver_info['xclarity_manager_ip']
|
|
||||||
del self.node.driver_info['xclarity_username']
|
|
||||||
del self.node.driver_info['xclarity_password']
|
|
||||||
self.config(manager_ip='5.6.7.8', group='xclarity')
|
|
||||||
self.config(username='user', group='xclarity')
|
|
||||||
self.config(password='password', group='xclarity')
|
|
||||||
info = common.parse_driver_info(self.node)
|
|
||||||
self.assertEqual('5.6.7.8', info['xclarity_manager_ip'])
|
|
||||||
self.assertEqual('user', info['xclarity_username'])
|
|
||||||
self.assertEqual('password', info['xclarity_password'])
|
|
||||||
|
|
||||||
def test_parse_driver_info_missing_driver_info_and_config(self):
|
|
||||||
del self.node.driver_info['xclarity_manager_ip']
|
|
||||||
del self.node.driver_info['xclarity_username']
|
|
||||||
del self.node.driver_info['xclarity_password']
|
|
||||||
e = self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
common.parse_driver_info, self.node)
|
|
||||||
self.assertIn('xclarity_manager_ip', str(e))
|
|
||||||
self.assertIn('xclarity_username', str(e))
|
|
||||||
self.assertIn('xclarity_password', str(e))
|
|
||||||
|
|
||||||
def test_parse_driver_info_invalid_port(self):
|
|
||||||
self.node.driver_info['xclarity_port'] = 'asd'
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
common.parse_driver_info, self.node)
|
|
||||||
self.node.driver_info['xclarity_port'] = '65536'
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
common.parse_driver_info, self.node)
|
|
||||||
self.node.driver_info['xclarity_port'] = 'invalid'
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
common.parse_driver_info, self.node)
|
|
||||||
self.node.driver_info['xclarity_port'] = '-1'
|
|
||||||
self.assertRaises(exception.InvalidParameterValue,
|
|
||||||
common.parse_driver_info, self.node)
|
|
||||||
|
|
||||||
def test_get_xclarity_client(self):
|
|
||||||
if not mock._is_instance_mock(xclarity_client):
|
|
||||||
mock.patch.object(xclarity_client, 'Client', autospec=True).start()
|
|
||||||
mock_xclarityclient = xclarity_client.Client
|
|
||||||
expected_call = mock.call(ip='1.2.3.4', password='fake', port=443,
|
|
||||||
username='USERID')
|
|
||||||
common.get_xclarity_client(self.node)
|
|
||||||
|
|
||||||
self.assertEqual(mock_xclarityclient.mock_calls, [expected_call])
|
|
||||||
|
|
||||||
def test_get_server_hardware_id(self):
|
|
||||||
driver_info = self.node.driver_info
|
|
||||||
driver_info['xclarity_hardware_id'] = 'test'
|
|
||||||
self.node.driver_info = driver_info
|
|
||||||
result = common.get_server_hardware_id(self.node)
|
|
||||||
self.assertEqual(result, 'test')
|
|
@ -1,158 +0,0 @@
|
|||||||
# Copyright 2017 Lenovo, Inc.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
import importlib
|
|
||||||
import sys
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
from oslo_utils import importutils
|
|
||||||
|
|
||||||
from ironic.common import boot_devices
|
|
||||||
from ironic.common import exception
|
|
||||||
from ironic.conductor import task_manager
|
|
||||||
from ironic.drivers.modules.xclarity import common
|
|
||||||
from ironic.drivers.modules.xclarity import management
|
|
||||||
from ironic.tests.unit.db import base as db_base
|
|
||||||
from ironic.tests.unit.db import utils as db_utils
|
|
||||||
from ironic.tests.unit.objects import utils as obj_utils
|
|
||||||
|
|
||||||
|
|
||||||
xclarity_client_exceptions = importutils.try_import(
|
|
||||||
'xclarity_client.exceptions')
|
|
||||||
|
|
||||||
|
|
||||||
@mock.patch.object(common, 'get_xclarity_client', spect_set=True,
|
|
||||||
autospec=True)
|
|
||||||
class XClarityManagementDriverTestCase(db_base.DbTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(XClarityManagementDriverTestCase, self).setUp()
|
|
||||||
self.config(enabled_hardware_types=['xclarity'],
|
|
||||||
enabled_power_interfaces=['xclarity'],
|
|
||||||
enabled_management_interfaces=['xclarity'])
|
|
||||||
self.node = obj_utils.create_test_node(
|
|
||||||
self.context,
|
|
||||||
driver='xclarity',
|
|
||||||
driver_info=db_utils.get_test_xclarity_driver_info())
|
|
||||||
|
|
||||||
@mock.patch.object(common, 'get_server_hardware_id',
|
|
||||||
spect_set=True, autospec=True)
|
|
||||||
def test_validate(self, mock_validate, mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.driver.management.validate(task)
|
|
||||||
common.get_server_hardware_id(task.node)
|
|
||||||
mock_validate.assert_called_with(task.node)
|
|
||||||
|
|
||||||
def test_get_properties(self, mock_get_xc_client):
|
|
||||||
expected = common.COMMON_PROPERTIES
|
|
||||||
driver = management.XClarityManagement()
|
|
||||||
self.assertEqual(expected, driver.get_properties())
|
|
||||||
|
|
||||||
@mock.patch.object(management.XClarityManagement, 'get_boot_device',
|
|
||||||
return_value='pxe', autospec=True)
|
|
||||||
def test_set_boot_device(self, mock_get_boot_device,
|
|
||||||
mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.driver.management.set_boot_device(task, 'pxe')
|
|
||||||
result = task.driver.management.get_boot_device(task)
|
|
||||||
self.assertEqual(result, 'pxe')
|
|
||||||
|
|
||||||
def test_set_boot_device_fail(self, mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
xclarity_client_exceptions.XClarityError = Exception
|
|
||||||
sys.modules['xclarity_client.exceptions'] = (
|
|
||||||
xclarity_client_exceptions)
|
|
||||||
if 'ironic.drivers.modules.xclarity' in sys.modules:
|
|
||||||
importlib.reload(
|
|
||||||
sys.modules['ironic.drivers.modules.xclarity'])
|
|
||||||
ex = exception.XClarityError('E')
|
|
||||||
mock_get_xc_client.return_value.set_node_boot_info.side_effect = ex
|
|
||||||
self.assertRaises(exception.XClarityError,
|
|
||||||
task.driver.management.set_boot_device,
|
|
||||||
task,
|
|
||||||
"pxe")
|
|
||||||
|
|
||||||
def test_get_supported_boot_devices(self, mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
expected = [boot_devices.PXE, boot_devices.BIOS,
|
|
||||||
boot_devices.DISK, boot_devices.CDROM]
|
|
||||||
self.assertCountEqual(
|
|
||||||
expected,
|
|
||||||
task.driver.management.get_supported_boot_devices(task))
|
|
||||||
|
|
||||||
@mock.patch.object(
|
|
||||||
management.XClarityManagement,
|
|
||||||
'get_boot_device',
|
|
||||||
return_value={'boot_device': 'pxe', 'persistent': False},
|
|
||||||
autospec=True)
|
|
||||||
def test_get_boot_device(self, mock_get_boot_device, mock_get_xc_client):
|
|
||||||
reference = {'boot_device': 'pxe', 'persistent': False}
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
expected_boot_device = task.driver.management.get_boot_device(
|
|
||||||
task=task)
|
|
||||||
|
|
||||||
self.assertEqual(reference, expected_boot_device)
|
|
||||||
|
|
||||||
def test_get_boot_device_fail(self, mock_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
xclarity_client_exceptions.XClarityError = Exception
|
|
||||||
sys.modules['xclarity_client.exceptions'] = (
|
|
||||||
xclarity_client_exceptions)
|
|
||||||
if 'ironic.drivers.modules.xclarity' in sys.modules:
|
|
||||||
importlib.reload(
|
|
||||||
sys.modules['ironic.drivers.modules.xclarity'])
|
|
||||||
ex = exception.XClarityError('E')
|
|
||||||
mock_xc_client.return_value.get_node_all_boot_info.side_effect = ex
|
|
||||||
self.assertRaises(
|
|
||||||
exception.XClarityError,
|
|
||||||
task.driver.management.get_boot_device,
|
|
||||||
task)
|
|
||||||
|
|
||||||
def test_get_boot_device_current_none(self, mock_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
reference = {'boot_device': None, 'persistent': None}
|
|
||||||
mock_xc_client.return_value.get_node_all_boot_info.return_value = \
|
|
||||||
{
|
|
||||||
'bootOrder': {
|
|
||||||
'bootOrderList': [{
|
|
||||||
'fakeBootOrderDevices': []
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expected_boot_device = task.driver.management.get_boot_device(
|
|
||||||
task=task)
|
|
||||||
self.assertEqual(reference, expected_boot_device)
|
|
||||||
|
|
||||||
def test_get_boot_device_primary_none(self, mock_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
reference = {'boot_device': None, 'persistent': None}
|
|
||||||
mock_xc_client.return_value.get_node_all_boot_info.return_value = \
|
|
||||||
{
|
|
||||||
'bootOrder': {
|
|
||||||
'bootOrderList': [
|
|
||||||
{
|
|
||||||
'bootType': 'SingleUse',
|
|
||||||
'CurrentBootOrderDevices': []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'bootType': 'Permanent',
|
|
||||||
'CurrentBootOrderDevices': []
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expected_boot_device = task.driver.management.get_boot_device(
|
|
||||||
task=task)
|
|
||||||
self.assertEqual(reference, expected_boot_device)
|
|
@ -1,146 +0,0 @@
|
|||||||
# Copyright 2017 Lenovo, Inc.
|
|
||||||
# All Rights Reserved.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
import importlib
|
|
||||||
import sys
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
from oslo_utils import importutils
|
|
||||||
|
|
||||||
from ironic.common import exception
|
|
||||||
from ironic.common import states
|
|
||||||
from ironic.conductor import task_manager
|
|
||||||
from ironic.drivers.modules.xclarity import common
|
|
||||||
from ironic.drivers.modules.xclarity import power
|
|
||||||
from ironic.tests.unit.db import base as db_base
|
|
||||||
from ironic.tests.unit.db import utils as db_utils
|
|
||||||
from ironic.tests.unit.objects import utils as obj_utils
|
|
||||||
|
|
||||||
STATE_POWER_ON = "power on"
|
|
||||||
STATE_POWER_OFF = "power off"
|
|
||||||
STATE_POWERING_ON = "power on"
|
|
||||||
STATE_POWERING_OFF = "power on"
|
|
||||||
|
|
||||||
xclarity_constants = importutils.try_import('xclarity_client.constants')
|
|
||||||
xclarity_client_exceptions = importutils.try_import(
|
|
||||||
'xclarity_client.exceptions')
|
|
||||||
|
|
||||||
|
|
||||||
@mock.patch.object(common, 'get_xclarity_client',
|
|
||||||
spect_set=True, autospec=True)
|
|
||||||
class XClarityPowerDriverTestCase(db_base.DbTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(XClarityPowerDriverTestCase, self).setUp()
|
|
||||||
self.config(enabled_hardware_types=['xclarity'],
|
|
||||||
enabled_power_interfaces=['xclarity'],
|
|
||||||
enabled_management_interfaces=['xclarity'])
|
|
||||||
self.node = obj_utils.create_test_node(
|
|
||||||
self.context,
|
|
||||||
driver='xclarity',
|
|
||||||
driver_info=db_utils.get_test_xclarity_driver_info())
|
|
||||||
|
|
||||||
def test_get_properties(self, mock_get_xc_client):
|
|
||||||
expected = common.COMMON_PROPERTIES
|
|
||||||
driver = power.XClarityPower()
|
|
||||||
self.assertEqual(expected, driver.get_properties())
|
|
||||||
|
|
||||||
@mock.patch.object(common, 'get_server_hardware_id',
|
|
||||||
spect_set=True, autospec=True)
|
|
||||||
def test_validate(self, mock_validate_driver_info, mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.driver.power.validate(task)
|
|
||||||
common.get_server_hardware_id(task.node)
|
|
||||||
mock_validate_driver_info.assert_called_with(task.node)
|
|
||||||
|
|
||||||
@mock.patch.object(power.XClarityPower, 'get_power_state',
|
|
||||||
return_value=STATE_POWER_ON, autospec=True)
|
|
||||||
def test_get_power_state(self, mock_get_power_state, mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
result = power.XClarityPower.get_power_state(self, task)
|
|
||||||
self.assertEqual(STATE_POWER_ON, result)
|
|
||||||
|
|
||||||
@mock.patch.object(common, 'translate_xclarity_power_state',
|
|
||||||
spec_set=True, autospec=True)
|
|
||||||
def test_get_power_state_fail(self, mock_translate_state, mock_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
xclarity_client_exceptions.XClarityError = Exception
|
|
||||||
sys.modules['xclarity_client.exceptions'] = (
|
|
||||||
xclarity_client_exceptions)
|
|
||||||
if 'ironic.drivers.modules.xclarity' in sys.modules:
|
|
||||||
importlib.reload(
|
|
||||||
sys.modules['ironic.drivers.modules.xclarity'])
|
|
||||||
ex = exception.XClarityError('E')
|
|
||||||
mock_xc_client.return_value.get_node_power_status.side_effect = ex
|
|
||||||
self.assertRaises(exception.XClarityError,
|
|
||||||
task.driver.power.get_power_state,
|
|
||||||
task)
|
|
||||||
self.assertFalse(mock_translate_state.called)
|
|
||||||
|
|
||||||
@mock.patch.object(power.LOG, 'warning', autospec=True)
|
|
||||||
@mock.patch.object(power.XClarityPower, 'get_power_state',
|
|
||||||
return_value=states.POWER_ON, autospec=True)
|
|
||||||
def test_set_power(self, mock_set_power_state, mock_log,
|
|
||||||
mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.driver.power.set_power_state(task, states.POWER_ON)
|
|
||||||
expected = task.driver.power.get_power_state(task)
|
|
||||||
self.assertEqual(expected, states.POWER_ON)
|
|
||||||
self.assertFalse(mock_log.called)
|
|
||||||
|
|
||||||
@mock.patch.object(power.LOG, 'warning', autospec=True)
|
|
||||||
@mock.patch.object(power.XClarityPower, 'get_power_state',
|
|
||||||
return_value=states.POWER_ON, autospec=True)
|
|
||||||
def test_set_power_timeout(self, mock_set_power_state, mock_log,
|
|
||||||
mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.driver.power.set_power_state(task, states.POWER_ON,
|
|
||||||
timeout=21)
|
|
||||||
expected = task.driver.power.get_power_state(task)
|
|
||||||
self.assertEqual(expected, states.POWER_ON)
|
|
||||||
self.assertTrue(mock_log.called)
|
|
||||||
|
|
||||||
def test_set_power_fail(self, mock_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
xclarity_client_exceptions.XClarityError = Exception
|
|
||||||
sys.modules['xclarity_client.exceptions'] = (
|
|
||||||
xclarity_client_exceptions)
|
|
||||||
if 'ironic.drivers.modules.xclarity' in sys.modules:
|
|
||||||
importlib.reload(
|
|
||||||
sys.modules['ironic.drivers.modules.xclarity'])
|
|
||||||
ex = exception.XClarityError('E')
|
|
||||||
mock_xc_client.return_value.set_node_power_status.side_effect = ex
|
|
||||||
self.assertRaises(exception.XClarityError,
|
|
||||||
task.driver.power.set_power_state,
|
|
||||||
task, states.POWER_OFF)
|
|
||||||
|
|
||||||
@mock.patch.object(power.LOG, 'warning', autospec=True)
|
|
||||||
@mock.patch.object(power.XClarityPower, 'set_power_state', autospec=True)
|
|
||||||
def test_reboot(self, mock_set_power_state, mock_log, mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.driver.power.reboot(task)
|
|
||||||
mock_set_power_state.assert_called_with(
|
|
||||||
mock.ANY, task, states.REBOOT)
|
|
||||||
self.assertFalse(mock_log.called)
|
|
||||||
|
|
||||||
@mock.patch.object(power.LOG, 'warning', autospec=True)
|
|
||||||
@mock.patch.object(power.XClarityPower, 'set_power_state', autospec=True)
|
|
||||||
def test_reboot_timeout(self, mock_set_power_state, mock_log,
|
|
||||||
mock_get_xc_client):
|
|
||||||
with task_manager.acquire(self.context, self.node.uuid) as task:
|
|
||||||
task.driver.power.reboot(task, timeout=55)
|
|
||||||
mock_set_power_state.assert_called_with(
|
|
||||||
mock.ANY, task, states.REBOOT)
|
|
||||||
self.assertTrue(mock_log.called)
|
|
@ -1,46 +0,0 @@
|
|||||||
# Copyright 2017 Lenovo, Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Test class for XClarity Driver
|
|
||||||
"""
|
|
||||||
|
|
||||||
from ironic.conductor import task_manager
|
|
||||||
from ironic.drivers.modules import agent
|
|
||||||
from ironic.drivers.modules import pxe
|
|
||||||
from ironic.drivers.xclarity import management as xc_management
|
|
||||||
from ironic.drivers.xclarity import power as xc_power
|
|
||||||
from ironic.tests.unit.db import base as db_base
|
|
||||||
from ironic.tests.unit.objects import utils as obj_utils
|
|
||||||
|
|
||||||
|
|
||||||
class XClarityHardwareTestCase(db_base.DbTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(XClarityHardwareTestCase, self).setUp()
|
|
||||||
self.config(enabled_hardware_types=['xclarity'],
|
|
||||||
enabled_power_interfaces=['xclarity'],
|
|
||||||
enabled_management_interfaces=['xclarity'])
|
|
||||||
|
|
||||||
def test_default_interfaces(self):
|
|
||||||
node = obj_utils.create_test_node(self.context, driver='xclarity')
|
|
||||||
with task_manager.acquire(self.context, node.id) as task:
|
|
||||||
self.assertIsInstance(task.driver.boot,
|
|
||||||
pxe.PXEBoot)
|
|
||||||
self.assertIsInstance(task.driver.deploy,
|
|
||||||
agent.AgentDeploy)
|
|
||||||
self.assertIsInstance(task.driver.management,
|
|
||||||
xc_management.XClarityManagement)
|
|
||||||
self.assertIsInstance(task.driver.power,
|
|
||||||
xc_power.XClarityPower)
|
|
@ -122,24 +122,6 @@ REDFISH_SPEC = (
|
|||||||
'redfish',
|
'redfish',
|
||||||
)
|
)
|
||||||
|
|
||||||
XCLARITY_SPEC = (
|
|
||||||
'client',
|
|
||||||
'states',
|
|
||||||
'exceptions',
|
|
||||||
'models',
|
|
||||||
'utils',
|
|
||||||
)
|
|
||||||
|
|
||||||
XCLARITY_CLIENT_CLS_SPEC = (
|
|
||||||
)
|
|
||||||
|
|
||||||
XCLARITY_STATES_SPEC = (
|
|
||||||
'STATE_POWERING_OFF',
|
|
||||||
'STATE_POWERING_ON',
|
|
||||||
'STATE_POWER_OFF',
|
|
||||||
'STATE_POWER_ON',
|
|
||||||
)
|
|
||||||
|
|
||||||
# python-ibmcclient
|
# python-ibmcclient
|
||||||
IBMCCLIENT_SPEC = (
|
IBMCCLIENT_SPEC = (
|
||||||
'connect',
|
'connect',
|
||||||
|
@ -196,25 +196,6 @@ class MockKwargsException(Exception):
|
|||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
|
||||||
xclarity_client = importutils.try_import('xclarity_client')
|
|
||||||
if not xclarity_client:
|
|
||||||
xclarity_client = mock.MagicMock(spec_set=mock_specs.XCLARITY_SPEC)
|
|
||||||
sys.modules['xclarity_client'] = xclarity_client
|
|
||||||
sys.modules['xclarity_client.client'] = xclarity_client.client
|
|
||||||
states = mock.MagicMock(
|
|
||||||
spec_set=mock_specs.XCLARITY_STATES_SPEC,
|
|
||||||
STATE_POWER_ON="power on",
|
|
||||||
STATE_POWER_OFF="power off",
|
|
||||||
STATE_POWERING_ON="powering_on",
|
|
||||||
STATE_POWERING_OFF="powering_off")
|
|
||||||
sys.modules['xclarity_client.states'] = states
|
|
||||||
sys.modules['xclarity_client.exceptions'] = xclarity_client.exceptions
|
|
||||||
sys.modules['xclarity_client.utils'] = xclarity_client.utils
|
|
||||||
xclarity_client.exceptions.XClarityException = type('XClarityException',
|
|
||||||
(Exception,), {})
|
|
||||||
sys.modules['xclarity_client.models'] = xclarity_client.models
|
|
||||||
|
|
||||||
|
|
||||||
# python-ibmcclient mocks for HUAWEI rack server driver
|
# python-ibmcclient mocks for HUAWEI rack server driver
|
||||||
ibmc_client = importutils.try_import('ibmc_client')
|
ibmc_client = importutils.try_import('ibmc_client')
|
||||||
if not ibmc_client:
|
if not ibmc_client:
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
The deprecated ``xclarity`` hardware type has been removed from Ironic.
|
@ -130,7 +130,6 @@ ironic.hardware.interfaces.management =
|
|||||||
irmc = ironic.drivers.modules.irmc.management:IRMCManagement
|
irmc = ironic.drivers.modules.irmc.management:IRMCManagement
|
||||||
noop = ironic.drivers.modules.noop_mgmt:NoopManagement
|
noop = ironic.drivers.modules.noop_mgmt:NoopManagement
|
||||||
redfish = ironic.drivers.modules.redfish.management:RedfishManagement
|
redfish = ironic.drivers.modules.redfish.management:RedfishManagement
|
||||||
xclarity = ironic.drivers.modules.xclarity.management:XClarityManagement
|
|
||||||
|
|
||||||
ironic.hardware.interfaces.network =
|
ironic.hardware.interfaces.network =
|
||||||
flat = ironic.drivers.modules.network.flat:FlatNetwork
|
flat = ironic.drivers.modules.network.flat:FlatNetwork
|
||||||
@ -149,7 +148,6 @@ ironic.hardware.interfaces.power =
|
|||||||
irmc = ironic.drivers.modules.irmc.power:IRMCPower
|
irmc = ironic.drivers.modules.irmc.power:IRMCPower
|
||||||
redfish = ironic.drivers.modules.redfish.power:RedfishPower
|
redfish = ironic.drivers.modules.redfish.power:RedfishPower
|
||||||
snmp = ironic.drivers.modules.snmp:SNMPPower
|
snmp = ironic.drivers.modules.snmp:SNMPPower
|
||||||
xclarity = ironic.drivers.modules.xclarity.power:XClarityPower
|
|
||||||
|
|
||||||
ironic.hardware.interfaces.raid =
|
ironic.hardware.interfaces.raid =
|
||||||
agent = ironic.drivers.modules.agent:AgentRAID
|
agent = ironic.drivers.modules.agent:AgentRAID
|
||||||
@ -198,7 +196,6 @@ ironic.hardware.types =
|
|||||||
manual-management = ironic.drivers.generic:ManualManagementHardware
|
manual-management = ironic.drivers.generic:ManualManagementHardware
|
||||||
redfish = ironic.drivers.redfish:RedfishHardware
|
redfish = ironic.drivers.redfish:RedfishHardware
|
||||||
snmp = ironic.drivers.snmp:SNMPHardware
|
snmp = ironic.drivers.snmp:SNMPHardware
|
||||||
xclarity = ironic.drivers.xclarity:XClarityHardware
|
|
||||||
|
|
||||||
ironic.database.migration_backend =
|
ironic.database.migration_backend =
|
||||||
sqlalchemy = ironic.db.sqlalchemy.migration
|
sqlalchemy = ironic.db.sqlalchemy.migration
|
||||||
|
Loading…
x
Reference in New Issue
Block a user