diff --git a/etc/ironic/ironic.conf.sample b/etc/ironic/ironic.conf.sample index 144112b72b..02dd040e0e 100644 --- a/etc/ironic/ironic.conf.sample +++ b/etc/ironic/ironic.conf.sample @@ -56,7 +56,7 @@ # this value, please make sure that every enabled hardware # type will have the same set of enabled boot interfaces on # every ironic-conductor service. (list value) -#enabled_boot_interfaces = +#enabled_boot_interfaces = pxe # WARNING: This configuration option is part of the incomplete # driver composition work, changing it's setting has no @@ -104,7 +104,7 @@ # this value, please make sure that every enabled hardware # type will have the same set of enabled deploy interfaces on # every ironic-conductor service. (list value) -#enabled_deploy_interfaces = +#enabled_deploy_interfaces = iscsi,direct # WARNING: This configuration option is part of the incomplete # driver composition work, changing it's setting has no @@ -222,7 +222,7 @@ # this value, please make sure that every enabled hardware # type will have the same set of enabled raid interfaces on # every ironic-conductor service. (list value) -#enabled_raid_interfaces = no-raid +#enabled_raid_interfaces = agent,no-raid # WARNING: This configuration option is part of the incomplete # driver composition work, changing it's setting has no diff --git a/ironic/conf/default.py b/ironic/conf/default.py index 6df090ad08..690a346dd8 100644 --- a/ironic/conf/default.py +++ b/ironic/conf/default.py @@ -108,9 +108,8 @@ driver_opts = [ 'A complete list of hardware types present on your ' 'system may be found by enumerating the ' '"ironic.hardware.types" entrypoint.')), - # TODO(dtantsur): populate with production-ready values cfg.ListOpt('enabled_boot_interfaces', - default=[], + default=['pxe'], help=_ENABLED_IFACE_HELP_WITH_WARNING.format('boot')), cfg.StrOpt('default_boot_interface', help=_DEFAULT_IFACE_HELP_WITH_WARNING.format('boot')), @@ -120,7 +119,7 @@ driver_opts = [ cfg.StrOpt('default_console_interface', help=_DEFAULT_IFACE_HELP_WITH_WARNING.format('console')), cfg.ListOpt('enabled_deploy_interfaces', - default=[], + default=['iscsi', 'direct'], help=_ENABLED_IFACE_HELP_WITH_WARNING.format('deploy')), cfg.StrOpt('default_deploy_interface', help=_DEFAULT_IFACE_HELP_WITH_WARNING.format('deploy')), @@ -145,7 +144,7 @@ driver_opts = [ cfg.StrOpt('default_power_interface', help=_DEFAULT_IFACE_HELP_WITH_WARNING.format('power')), cfg.ListOpt('enabled_raid_interfaces', - default=['no-raid'], + default=['agent', 'no-raid'], help=_ENABLED_IFACE_HELP_WITH_WARNING.format('raid')), cfg.StrOpt('default_raid_interface', help=_DEFAULT_IFACE_HELP_WITH_WARNING.format('raid')), diff --git a/ironic/drivers/generic.py b/ironic/drivers/generic.py new file mode 100644 index 0000000000..4178d4995d --- /dev/null +++ b/ironic/drivers/generic.py @@ -0,0 +1,86 @@ +# Copyright 2016 Red Hat, 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. + +""" +Generic hardware types. +""" + +from ironic.drivers import hardware_type +from ironic.drivers.modules import agent +from ironic.drivers.modules import fake +from ironic.drivers.modules import inspector +from ironic.drivers.modules import iscsi_deploy +from ironic.drivers.modules.network import flat as flat_net +from ironic.drivers.modules.network import neutron +from ironic.drivers.modules.network import noop as noop_net +from ironic.drivers.modules import noop +from ironic.drivers.modules import pxe + + +class GenericHardware(hardware_type.AbstractHardwareType): + """Abstract base class representing generic hardware. + + This class provides reasonable defaults for boot, deploy, inspect, network + and raid interfaces. + """ + + @property + def supported_boot_interfaces(self): + """List of supported boot interfaces.""" + return [pxe.PXEBoot] + + @property + def supported_deploy_interfaces(self): + """List of supported deploy interfaces.""" + return [iscsi_deploy.ISCSIDeploy, agent.AgentDeploy] + + @property + def supported_inspect_interfaces(self): + """List of supported inspect interfaces.""" + # Inspector support should be the default if it's enabled by an + # operator (implying that the service is installed). + return [inspector.Inspector, noop.NoInspect] + + @property + def supported_network_interfaces(self): + """List of supported network interfaces.""" + return [flat_net.FlatNetwork, neutron.NeutronNetwork, + noop_net.NoopNetwork] + + @property + def supported_raid_interfaces(self): + """List of supported raid interfaces.""" + # AgentRAID requires RAID bits on the IPA image that are not shipped by + # default. Hence, even if AgentRAID is enabled, NoRAID is the default. + return [noop.NoRAID, agent.AgentRAID] + + +class ManualManagementHardware(GenericHardware): + """Hardware type that uses manual power and boot management. + + Using this hardware type assumes that an operator manages reboot + and setting boot devices manually. This hardware type should only be used + when no suitable hardware type exists in ironic, or the existing hardware + type misbehaves for any reason. + """ + + @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 [fake.FakePower] diff --git a/ironic/tests/unit/drivers/test_generic.py b/ironic/tests/unit/drivers/test_generic.py new file mode 100644 index 0000000000..c70999167f --- /dev/null +++ b/ironic/tests/unit/drivers/test_generic.py @@ -0,0 +1,59 @@ +# Copyright 2016 Red Hat, 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.conductor import task_manager +from ironic.drivers.modules import agent +from ironic.drivers.modules import fake +from ironic.drivers.modules import inspector +from ironic.drivers.modules import iscsi_deploy +from ironic.drivers.modules import noop +from ironic.drivers.modules import pxe +from ironic.tests.unit.db import base as db_base +from ironic.tests.unit.objects import utils as obj_utils + + +class ManualManagementHardwareTestCase(db_base.DbTestCase): + + def setUp(self): + super(ManualManagementHardwareTestCase, self).setUp() + self.config(enabled_hardware_types=['manual-management'], + enabled_power_interfaces=['fake'], + enabled_management_interfaces=['fake'], + enabled_inspect_interfaces=['no-inspect']) + self.config(enabled=True, group='inspector') + + def test_default_interfaces(self): + node = obj_utils.create_test_node(self.context, + driver='manual-management') + with task_manager.acquire(self.context, node.id) as task: + self.assertIsInstance(task.driver.management, fake.FakeManagement) + self.assertIsInstance(task.driver.power, fake.FakePower) + self.assertIsInstance(task.driver.boot, pxe.PXEBoot) + self.assertIsInstance(task.driver.deploy, iscsi_deploy.ISCSIDeploy) + self.assertIsInstance(task.driver.inspect, noop.NoInspect) + self.assertIsInstance(task.driver.raid, noop.NoRAID) + + def test_supported_interfaces(self): + self.config(enabled_inspect_interfaces=['inspector', 'no-inspect']) + node = obj_utils.create_test_node(self.context, + driver='manual-management', + deploy_interface='direct', + raid_interface='agent') + with task_manager.acquire(self.context, node.id) as task: + self.assertIsInstance(task.driver.management, fake.FakeManagement) + self.assertIsInstance(task.driver.power, fake.FakePower) + self.assertIsInstance(task.driver.boot, pxe.PXEBoot) + self.assertIsInstance(task.driver.deploy, agent.AgentDeploy) + self.assertIsInstance(task.driver.inspect, inspector.Inspector) + self.assertIsInstance(task.driver.raid, agent.AgentRAID) diff --git a/setup.cfg b/setup.cfg index 085e419409..ad29b69993 100644 --- a/setup.cfg +++ b/setup.cfg @@ -99,16 +99,20 @@ ironic.drivers = ironic.hardware.interfaces.boot = fake = ironic.drivers.modules.fake:FakeBoot + pxe = ironic.drivers.modules.pxe:PXEBoot ironic.hardware.interfaces.console = fake = ironic.drivers.modules.fake:FakeConsole no-console = ironic.drivers.modules.noop:NoConsole ironic.hardware.interfaces.deploy = + direct = ironic.drivers.modules.agent:AgentDeploy + iscsi = ironic.drivers.modules.iscsi_deploy:ISCSIDeploy fake = ironic.drivers.modules.fake:FakeDeploy ironic.hardware.interfaces.inspect = fake = ironic.drivers.modules.fake:FakeInspect + inspector = ironic.drivers.modules.inspector:Inspector no-inspect = ironic.drivers.modules.noop:NoInspect ironic.hardware.interfaces.management = @@ -123,6 +127,7 @@ ironic.hardware.interfaces.power = fake = ironic.drivers.modules.fake:FakePower ironic.hardware.interfaces.raid = + agent = ironic.drivers.modules.agent:AgentRAID fake = ironic.drivers.modules.fake:FakeRAID no-raid = ironic.drivers.modules.noop:NoRAID @@ -135,6 +140,7 @@ ironic.hardware.interfaces.vendor = ironic.hardware.types = fake-hardware = ironic.drivers.fake_hardware:FakeHardware + manual-management = ironic.drivers.generic:ManualManagementHardware ironic.database.migration_backend = sqlalchemy = ironic.db.sqlalchemy.migration