Add hardware types

Classic drivers will be deprecated, add hardware types for
staging drivers. "staging-" prefix used for entrypoints.

The DevStack plugin is amended to enable all hardware types and
interfaces registered by the ironic-staging-driver package
to test that they do not break ironic-conductor start when enabled
For this a new script is added to read entrypoints registered by a Python
package.
As previousely, by default `iboot` drivers are not enabled
as they require a client library not available on PyPI.

Change-Id: I26541adc9b99f7a436be0e3f8ef31c0ff64ff5d4
This commit is contained in:
Yuriy Zveryanskyy 2017-05-18 17:58:54 +03:00 committed by Pavlo Shchelokovskyy
parent ae929e98a4
commit c1d9f44dbd
11 changed files with 327 additions and 28 deletions

View File

@ -1,13 +0,0 @@
fake_wol_fake
pxe_wol_iscsi
pxe_wol_agent
agent_ipmitool_nm
fake_nm
pxe_libvirt_agent
pxe_libvirt_iscsi
fake_libvirt_fake
fake_amt_fake
pxe_amt_iscsi
pxe_amt_agent
pxe_libvirt_ansible
pxe_ipmitool_ansible

View File

@ -4,26 +4,74 @@
IRONIC_STAGING_DRIVERS_DIR=$DEST/ironic-staging-drivers
IRONIC_DRIVERS_EXCLUDED_DIRS='tests common'
IRONIC_STAGING_DRIVER=${IRONIC_STAGING_DRIVER:-}
# NOTE(pas-ha) skip iboot drivers by default as they require package not available on PyPI
IRONIC_STAGING_DRIVERS_SKIPS=${IRONIC_STAGING_DRIVERS_SKIPS:-"iboot"}
IRONIC_STAGING_DRIVERS_FILTERS=${IRONIC_STAGING_DRIVERS_FILTERS:-}
IRONIC_STAGING_LIST_EP_CMD="$PYTHON $IRONIC_STAGING_DRIVERS_DIR/tools/list-package-entrypoints.py ironic-staging-drivers"
if [[ -n "$IRONIC_STAGING_DRIVERS_SKIPS" ]]; then
IRONIC_STAGING_LIST_EP_CMD+=" -s $IRONIC_STAGING_DRIVERS_SKIPS"
fi
if [[ -n "$IRONIC_STAGING_DRIVERS_FILTERS" ]]; then
IRONIC_STAGING_LIST_EP_CMD+=" -f $IRONIC_STAGING_DRIVERS_FILTERS"
fi
function setup_ironic_enabled_interfaces_for {
local iface=$1
local iface_var
local ironic_iface_var
local staging_ifs
iface_var=$(echo $iface | tr '[:lower:]' '[:upper:]')
ironic_iface_var="IRONIC_ENABLED_${iface_var}_INTERFACES"
staging_ifs=$($IRONIC_STAGING_LIST_EP_CMD -t ironic.hardware.interfaces.${iface})
# NOTE(pas-ha) need fake management interface enabled for staging-wol hw type,
# and even if WoL is disabled by skips or filters, no harm in enabling it any way
if [[ $iface == 'management' ]]; then
if [[ -n ${staging_ifs} ]]; then
staging_ifs+=",fake"
else
staging_ifs='fake'
fi
fi
if [[ -n ${staging_ifs} ]]; then
iniset $IRONIC_CONF_FILE DEFAULT "enabled_${iface}_interfaces" "${!ironic_iface_var},$staging_ifs"
fi
}
function update_ironic_enabled_drivers {
local saveIFS
saveIFS=$IFS
IFS=","
while read driver; do
if [[ ! $IRONIC_ENABLED_DRIVERS =~ $(echo "\<$driver\>") ]]; then
if [[ -z "$IRONIC_ENABLED_DRIVERS" ]]; then
IRONIC_ENABLED_DRIVERS="$driver"
else
IRONIC_ENABLED_DRIVERS+=",$driver"
fi
fi
done < $IRONIC_STAGING_DRIVERS_DIR/devstack/enabled-drivers.txt
IFS=$saveIFS
# NOTE(pas-ha) not carying about possible duplicates any more,
# as it was fixed in ironic already
# NOTE(vsaienko) if ironic-staging-drivers are called after ironic
# setting IRONIC_ENABLED_DRIVERS will not take affect. Update ironic
# configuration explicitly.
# setting IRONIC_ENABLED_* will not take affect. Update ironic
# configuration explicitly for each option.
local staging_drivers
local staging_hw_types
staging_drivers=$($IRONIC_STAGING_LIST_EP_CMD -t ironic.drivers)
if [[ -z "$IRONIC_ENABLED_DRIVERS" ]]; then
IRONIC_ENABLED_DRIVERS="$staging_drivers"
else
IRONIC_ENABLED_DRIVERS+=",$staging_drivers"
fi
iniset $IRONIC_CONF_FILE DEFAULT enabled_drivers "$IRONIC_ENABLED_DRIVERS"
# hardware types
staging_hw_types=$($IRONIC_STAGING_LIST_EP_CMD -t ironic.hardware.types)
if [[ -z "$IRONIC_ENABLED_HARDWARE_TYPES" ]]; then
IRONIC_ENABLED_HARDWARE_TYPES="$staging_hw_types"
else
IRONIC_ENABLED_HARDWARE_TYPES+=",$staging_hw_types"
fi
iniset $IRONIC_CONF_FILE DEFAULT enabled_hardware_types "$IRONIC_ENABLED_HARDWARE_TYPES"
# NOTE(pas-ha) find and enable any type of ironic hardware interface
# registered by ironic-staging-drivers package (minding skips and filters)
for i in $IRONIC_DRIVER_INTERFACE_TYPES; do
setup_ironic_enabled_interfaces_for $i
done
# set logging for ansible-deploy
# NOTE(pas-ha) w/o systemd or syslog, there will be no output of single
# ansible tasks to ironic log, only in the stdout returned by processutils

View File

@ -15,6 +15,7 @@
from ironic.common import exception as ironic_exception
from ironic.drivers import base
from ironic.drivers import generic
from ironic.drivers.modules import agent
from ironic.drivers.modules import fake
from ironic.drivers.modules import pxe
@ -79,3 +80,25 @@ class PXEAndAMTAgentDriver(base.BaseDriver):
self.boot = pxe.PXEBoot()
self.deploy = agent.AgentDeploy()
self.management = amt_management.AMTManagement()
class AMTHardware(generic.GenericHardware):
"""AMT hardware type.
Hardware type for Intel AMT.
"""
@property
def supported_deploy_interfaces(self):
"""List of supported deploy interfaces."""
return [amt_deploy.AMTISCSIDeploy, agent.AgentDeploy]
@property
def supported_management_interfaces(self):
"""List of supported management interfaces."""
return [amt_management.AMTManagement]
@property
def supported_power_interfaces(self):
"""List of supported power interfaces."""
return [amt_power.AMTPower]

View File

@ -11,6 +11,7 @@
# limitations under the License.
from ironic.drivers import base
from ironic.drivers import ipmi
from ironic.drivers.modules import fake
from ironic.drivers.modules import ipmitool
from ironic.drivers.modules import pxe
@ -51,3 +52,14 @@ class AnsibleAndLibvirtDriver(base.BaseDriver):
self.boot = pxe.PXEBoot()
self.deploy = ansible_deploy.AnsibleDeploy()
self.management = libvirt_power.LibvirtManagement()
# NOTE(yuriyz): This class is not a "real" hardware.
# Added to support the ansible deploy interface in 'ipmi' hardware
class AnsibleDeployIPMI(ipmi.IPMIHardware):
@property
def supported_deploy_interfaces(self):
"""List of supported deploy interfaces."""
return (super(AnsibleDeployIPMI, self).supported_deploy_interfaces +
[ansible_deploy.AnsibleDeploy])

View File

@ -17,6 +17,7 @@
from ironic.common import exception as ironic_exception
from ironic.common.i18n import _
from ironic.drivers import base
from ironic.drivers import generic
from ironic.drivers.modules import agent
from ironic.drivers.modules import fake
from ironic.drivers.modules import iscsi_deploy
@ -77,3 +78,20 @@ class PXEIBootAgentDriver(base.BaseDriver):
self.power = iboot_power.IBootPower()
self.boot = pxe.PXEBoot()
self.deploy = agent.AgentDeploy()
class IBootHardware(generic.GenericHardware):
"""IBoot hardware type.
Uses IBoot for power management.
"""
@property
def supported_management_interfaces(self):
"""List of supported management interfaces."""
return [fake.FakeManagement]
@property
def supported_power_interfaces(self):
"""List of supported power interfaces."""
return [iboot_power.IBootPower]

View File

@ -11,6 +11,7 @@
# under the License.
from ironic.drivers import base
from ironic.drivers import ipmi
from ironic.drivers.modules import agent
from ironic.drivers.modules import fake
from ironic.drivers.modules import inspector
@ -57,3 +58,16 @@ class AgentAndIPMIToolIntelNMDriver(base.BaseDriver):
self.raid = agent.AgentRAID()
self.inspect = inspector.Inspector.create_if_enabled(
'AgentAndIPMIToolDriver')
class IntelNMHardware(ipmi.IPMIHardware):
"""Intel NM hardware type.
Hardware type with Intel Node Manager vendor methods.
"""
@property
def supported_vendor_interfaces(self):
"""List of supported vendor interfaces."""
return (super(IntelNMHardware, self).supported_vendor_interfaces +
[nm_vendor.IntelNMVendorPassthru])

View File

@ -11,11 +11,13 @@
# under the License.
from ironic.drivers import base
from ironic.drivers import generic
from ironic.drivers.modules import agent
from ironic.drivers.modules import fake
from ironic.drivers.modules import iscsi_deploy
from ironic.drivers.modules import pxe
from ironic_staging_drivers.ansible import deploy as ansible_deploy
from ironic_staging_drivers.libvirt import power
@ -65,3 +67,27 @@ class PXELibvirtISCSIDriver(base.BaseDriver):
self.boot = pxe.PXEBoot()
self.deploy = iscsi_deploy.ISCSIDeploy()
self.management = power.LibvirtManagement()
class LibvirtHardware(generic.GenericHardware):
"""Libvirt hardware type.
Uses Libvirt for power and management.
Also support ansible-deploy.
"""
@property
def supported_deploy_interfaces(self):
"""List of supported deploy interfaces."""
return (super(LibvirtHardware, self).supported_deploy_interfaces +
[ansible_deploy.AnsibleDeploy])
@property
def supported_management_interfaces(self):
"""List of supported management interfaces."""
return [power.LibvirtManagement]
@property
def supported_power_interfaces(self):
"""List of supported power interfaces."""
return [power.LibvirtPower]

View File

@ -14,6 +14,7 @@
# under the License.
from ironic.drivers import base
from ironic.drivers import generic
from ironic.drivers.modules import agent
from ironic.drivers.modules import fake
from ironic.drivers.modules import iscsi_deploy
@ -63,3 +64,20 @@ class PXEWakeOnLanAgentDriver(base.BaseDriver):
self.boot = pxe.PXEBoot()
self.power = wol_power.WakeOnLanPower()
self.deploy = agent.AgentDeploy()
class WOLHardware(generic.GenericHardware):
"""WOL hardware type.
Uses wake on lan for power on.
"""
@property
def supported_management_interfaces(self):
"""List of supported management interfaces."""
return [fake.FakeManagement]
@property
def supported_power_interfaces(self):
"""List of supported power interfaces."""
return [wol_power.WakeOnLanPower]

View File

@ -0,0 +1,45 @@
---
features:
- |
Adds 'staging-amt' hardware type for AMT hardware.
Supported driver interfaces different from Generic Hardware are:
- power: staging-amt
- management: staging-amt
- deploy: direct, staging-amt
- |
Adds 'staging-wol' hardware type for Wake-on-Lan hardware.
Supported driver interfaces different from Generic Hardware are:
- power: staging-wol
- management: fake
- |
Adds 'staging-iboot' hardware type for iBoot hardware.
Supported driver interfaces different from Generic Hardware are:
- power: staging-iboot
- management: fake
- |
Adds 'staging-libvirt' hardware type for libvirt-managed virtual hardware.
Supported driver interfaces different from Generic Hardware are:
- power: staging-libvirt
- management: staging-libvirt
- deploy: direct, iscsi, staging-ansible
- |
Adds 'staging-nm' hardware type for Intel NodeManager hardware.
Supported driver interfaces different from ``ipmi`` hardware type are:
- vendor: ipmitool, no-vendor, staging-nm
- |
Adds 'staging-ansible-ipmi' hardware type for IPMI hardware.
This is not a real hardware type, but it is needed to enable
ansible-deploy interface for standard ``ipmi`` hardware type.
Supported driver interfaces different from ``ipmi`` hardware are:
- deploy: direct, iscsi, staging-ansible

View File

@ -42,6 +42,31 @@ ironic.drivers =
pxe_ipmitool_ansible = ironic_staging_drivers.ansible:AnsibleAndIPMIToolDriver
pxe_libvirt_ansible = ironic_staging_drivers.ansible:AnsibleAndLibvirtDriver
ironic.hardware.interfaces.deploy =
staging-ansible = ironic_staging_drivers.ansible.deploy:AnsibleDeploy
staging-amt = ironic_staging_drivers.amt.deploy:AMTISCSIDeploy
ironic.hardware.interfaces.management =
staging-amt = ironic_staging_drivers.amt.management:AMTManagement
staging-libvirt = ironic_staging_drivers.libvirt.power:LibvirtManagement
ironic.hardware.interfaces.power =
staging-amt = ironic_staging_drivers.amt.power:AMTPower
staging-iboot = ironic_staging_drivers.iboot.power:IBootPower
staging-libvirt = ironic_staging_drivers.libvirt.power:LibvirtPower
staging-wol = ironic_staging_drivers.wol.power:WakeOnLanPower
ironic.hardware.interfaces.vendor =
staging-nm = ironic_staging_drivers.intel_nm.nm_vendor:IntelNMVendorPassthru
ironic.hardware.types =
staging-amt = ironic_staging_drivers.amt.drivers:AMTHardware
staging-ansible-ipmi = ironic_staging_drivers.ansible:AnsibleDeployIPMI
staging-iboot = ironic_staging_drivers.iboot:IBootHardware
staging-nm = ironic_staging_drivers.intel_nm:IntelNMHardware
staging-libvirt = ironic_staging_drivers.libvirt:LibvirtHardware
staging-wol = ironic_staging_drivers.wol:WOLHardware
[build_sphinx]
source-dir = doc/source
build-dir = doc/build

View File

@ -0,0 +1,83 @@
# 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.
"""List entrypoint names registered by package, possibly per type"""
from __future__ import print_function
import argparse
import sys
import pkg_resources
def filter_ep_names(eps, ep_type, skips=None, filters=None):
if not skips:
skips = []
if not filters:
filters = []
def filter_func(name):
return (all([s not in name for s in skips]) and
all([f in name for f in filters]))
return filter(filter_func, list(eps.get(ep_type, {}).keys()))
def list_package_entrypoints(package_name, ep_types=None, skips=None,
filters=None):
eps = pkg_resources.get_entry_map(
pkg_resources.get_distribution(package_name))
if not ep_types:
ep_types = eps.keys()
if not skips:
skips = []
if not filters:
filters = []
if len(ep_types) == 1:
names = filter_ep_names(eps, ep_types[0], skips=skips,
filters=filters)
if names:
print(','.join(names))
else:
for ep_t in ep_types:
print("%s=%s" % (ep_t,
','.join(filter_ep_names(eps, ep_t,
skips=skips,
filters=filters))))
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('package', metavar='PACKAGE_NAME', type=str,
help='Name of Python package')
parser.add_argument('-t', '--entrypoint-types', dest='ep_types', nargs='+',
metavar="ENTRYPOINT_TYPE",
help='type of entrypoints to find, all if not set')
parser.add_argument('-s', '--skip-names', dest='ep_skips', nargs='+',
metavar='SKIP_ENTRYPOINT',
help='do not output entrypoint names containing any '
'of these substrings, ignored if not set')
parser.add_argument('-f', '--filter-names', dest='ep_filters', nargs='+',
metavar='FILTER_ENTRYPOINT',
help='only output entrypoint names containing all '
'these substrings, ignored if not set')
args = parser.parse_args()
sys.exit(list_package_entrypoints(args.package,
ep_types=args.ep_types,
skips=args.ep_skips,
filters=args.ep_filters))