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_STAGING_DRIVERS_DIR=$DEST/ironic-staging-drivers
IRONIC_DRIVERS_EXCLUDED_DIRS='tests common' IRONIC_DRIVERS_EXCLUDED_DIRS='tests common'
IRONIC_STAGING_DRIVER=${IRONIC_STAGING_DRIVER:-} 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 { function update_ironic_enabled_drivers {
local saveIFS # NOTE(pas-ha) not carying about possible duplicates any more,
saveIFS=$IFS # as it was fixed in ironic already
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(vsaienko) if ironic-staging-drivers are called after ironic # NOTE(vsaienko) if ironic-staging-drivers are called after ironic
# setting IRONIC_ENABLED_DRIVERS will not take affect. Update ironic # setting IRONIC_ENABLED_* will not take affect. Update ironic
# configuration explicitly. # 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" 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 # set logging for ansible-deploy
# NOTE(pas-ha) w/o systemd or syslog, there will be no output of single # 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 # 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.common import exception as ironic_exception
from ironic.drivers import base from ironic.drivers import base
from ironic.drivers import generic
from ironic.drivers.modules import agent from ironic.drivers.modules import agent
from ironic.drivers.modules import fake from ironic.drivers.modules import fake
from ironic.drivers.modules import pxe from ironic.drivers.modules import pxe
@ -79,3 +80,25 @@ class PXEAndAMTAgentDriver(base.BaseDriver):
self.boot = pxe.PXEBoot() self.boot = pxe.PXEBoot()
self.deploy = agent.AgentDeploy() self.deploy = agent.AgentDeploy()
self.management = amt_management.AMTManagement() 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. # limitations under the License.
from ironic.drivers import base from ironic.drivers import base
from ironic.drivers import ipmi
from ironic.drivers.modules import fake from ironic.drivers.modules import fake
from ironic.drivers.modules import ipmitool from ironic.drivers.modules import ipmitool
from ironic.drivers.modules import pxe from ironic.drivers.modules import pxe
@ -51,3 +52,14 @@ class AnsibleAndLibvirtDriver(base.BaseDriver):
self.boot = pxe.PXEBoot() self.boot = pxe.PXEBoot()
self.deploy = ansible_deploy.AnsibleDeploy() self.deploy = ansible_deploy.AnsibleDeploy()
self.management = libvirt_power.LibvirtManagement() 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 import exception as ironic_exception
from ironic.common.i18n import _ from ironic.common.i18n import _
from ironic.drivers import base from ironic.drivers import base
from ironic.drivers import generic
from ironic.drivers.modules import agent from ironic.drivers.modules import agent
from ironic.drivers.modules import fake from ironic.drivers.modules import fake
from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import iscsi_deploy
@ -77,3 +78,20 @@ class PXEIBootAgentDriver(base.BaseDriver):
self.power = iboot_power.IBootPower() self.power = iboot_power.IBootPower()
self.boot = pxe.PXEBoot() self.boot = pxe.PXEBoot()
self.deploy = agent.AgentDeploy() 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. # under the License.
from ironic.drivers import base from ironic.drivers import base
from ironic.drivers import ipmi
from ironic.drivers.modules import agent from ironic.drivers.modules import agent
from ironic.drivers.modules import fake from ironic.drivers.modules import fake
from ironic.drivers.modules import inspector from ironic.drivers.modules import inspector
@ -57,3 +58,16 @@ class AgentAndIPMIToolIntelNMDriver(base.BaseDriver):
self.raid = agent.AgentRAID() self.raid = agent.AgentRAID()
self.inspect = inspector.Inspector.create_if_enabled( self.inspect = inspector.Inspector.create_if_enabled(
'AgentAndIPMIToolDriver') '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. # under the License.
from ironic.drivers import base from ironic.drivers import base
from ironic.drivers import generic
from ironic.drivers.modules import agent from ironic.drivers.modules import agent
from ironic.drivers.modules import fake from ironic.drivers.modules import fake
from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import iscsi_deploy
from ironic.drivers.modules import pxe from ironic.drivers.modules import pxe
from ironic_staging_drivers.ansible import deploy as ansible_deploy
from ironic_staging_drivers.libvirt import power from ironic_staging_drivers.libvirt import power
@ -65,3 +67,27 @@ class PXELibvirtISCSIDriver(base.BaseDriver):
self.boot = pxe.PXEBoot() self.boot = pxe.PXEBoot()
self.deploy = iscsi_deploy.ISCSIDeploy() self.deploy = iscsi_deploy.ISCSIDeploy()
self.management = power.LibvirtManagement() 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. # under the License.
from ironic.drivers import base from ironic.drivers import base
from ironic.drivers import generic
from ironic.drivers.modules import agent from ironic.drivers.modules import agent
from ironic.drivers.modules import fake from ironic.drivers.modules import fake
from ironic.drivers.modules import iscsi_deploy from ironic.drivers.modules import iscsi_deploy
@ -63,3 +64,20 @@ class PXEWakeOnLanAgentDriver(base.BaseDriver):
self.boot = pxe.PXEBoot() self.boot = pxe.PXEBoot()
self.power = wol_power.WakeOnLanPower() self.power = wol_power.WakeOnLanPower()
self.deploy = agent.AgentDeploy() 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_ipmitool_ansible = ironic_staging_drivers.ansible:AnsibleAndIPMIToolDriver
pxe_libvirt_ansible = ironic_staging_drivers.ansible:AnsibleAndLibvirtDriver 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] [build_sphinx]
source-dir = doc/source source-dir = doc/source
build-dir = doc/build 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))