summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavlo Shchelokovskyy <shchelokovskyy@gmail.com>2017-02-09 00:32:40 +0200
committerPavlo Shchelokovskyy <shchelokovskyy@gmail.com>2017-02-09 08:09:03 +0000
commit02ce7246ecb20daae3883a45099434caa13a7f08 (patch)
treef0526adce1623bb361b5e3515e9a932e5b09f6aa
parentd601a11e91e2010cf10f6438147b6a015984d5f2 (diff)
downloadironic-02ce7246ecb20daae3883a45099434caa13a7f08.tar.gz
Remove most unsupported drivers
In accordance with ironic CI policies, this patch removesi some drivers that are not tested on upstream or third-party CI and for which maintainers have not communicated any plans to have such testing. This includes: - virtualbox drivers - seamicro drivers - msftocs drivers Change-Id: Ia3a7d798c877f4628946ee6c56d850b9847e6c3e Closes-Bug: #1663018
-rw-r--r--doc/source/deploy/console.rst5
-rw-r--r--doc/source/deploy/drivers.rst20
-rw-r--r--doc/source/drivers/seamicro.rst117
-rw-r--r--doc/source/drivers/vbox.rst121
-rw-r--r--driver-requirements.txt6
-rw-r--r--etc/ironic/ironic.conf.sample27
-rw-r--r--install-guide/source/standalone.rst4
-rw-r--r--ironic/common/exception.py9
-rw-r--r--ironic/conf/__init__.py4
-rw-r--r--ironic/conf/opts.py2
-rw-r--r--ironic/conf/seamicro.py34
-rw-r--r--ironic/conf/virtualbox.py27
-rw-r--r--ironic/drivers/agent.py28
-rw-r--r--ironic/drivers/fake.py47
-rw-r--r--ironic/drivers/modules/msftocs/__init__.py0
-rw-r--r--ironic/drivers/modules/msftocs/common.py110
-rw-r--r--ironic/drivers/modules/msftocs/management.py121
-rw-r--r--ironic/drivers/modules/msftocs/msftocsclient.py176
-rw-r--r--ironic/drivers/modules/msftocs/power.py105
-rw-r--r--ironic/drivers/modules/seamicro.py672
-rw-r--r--ironic/drivers/modules/virtualbox.py393
-rw-r--r--ironic/drivers/pxe.py76
-rw-r--r--ironic/tests/unit/conductor/test_manager.py14
-rw-r--r--ironic/tests/unit/db/utils.py18
-rw-r--r--ironic/tests/unit/drivers/modules/msftocs/__init__.py0
-rw-r--r--ironic/tests/unit/drivers/modules/msftocs/test_common.py110
-rw-r--r--ironic/tests/unit/drivers/modules/msftocs/test_management.py132
-rw-r--r--ironic/tests/unit/drivers/modules/msftocs/test_msftocsclient.py182
-rw-r--r--ironic/tests/unit/drivers/modules/msftocs/test_power.py163
-rw-r--r--ironic/tests/unit/drivers/modules/test_seamicro.py689
-rw-r--r--ironic/tests/unit/drivers/modules/test_virtualbox.py420
-rw-r--r--ironic/tests/unit/drivers/test_pxe.py61
-rw-r--r--ironic/tests/unit/drivers/third_party_driver_mock_specs.py27
-rw-r--r--ironic/tests/unit/drivers/third_party_driver_mocks.py34
-rw-r--r--releasenotes/notes/remove-most-unsupported-049f3401c2554a3c.yaml32
-rw-r--r--setup.cfg7
36 files changed, 39 insertions, 3954 deletions
diff --git a/doc/source/deploy/console.rst b/doc/source/deploy/console.rst
index 55d12ba16..8be1ea669 100644
--- a/doc/source/deploy/console.rst
+++ b/doc/source/deploy/console.rst
@@ -125,9 +125,8 @@ The web console can be configured in Bare Metal service in the following way:
ironic driver-properties <driver>
For ``*_ipmitool`` and ``*_ipminative`` drivers, this option is ``ipmi_terminal_port``.
- For ``seamicro`` driver, this option is ``seamicro_terminal_port``. Give a customized port
- number to ``<customized_port>``, for example ``8023``, this customized port is used in
- web console url.
+ Give a customized port number to ``<customized_port>``,
+ for example ``8023``, this customized port is used in web console url.
Get web console information for a node as follows::
diff --git a/doc/source/deploy/drivers.rst b/doc/source/deploy/drivers.rst
index 55bf35f56..56a286a6c 100644
--- a/doc/source/deploy/drivers.rst
+++ b/doc/source/deploy/drivers.rst
@@ -48,14 +48,6 @@ iLO driver
../drivers/ilo
-SeaMicro driver
----------------
-
-.. toctree::
- :maxdepth: 1
-
- ../drivers/seamicro
-
iRMC driver
-----------
@@ -64,15 +56,6 @@ iRMC driver
../drivers/irmc
-VirtualBox driver
------------------
-
-.. toctree::
- :maxdepth: 1
-
- ../drivers/vbox
-
-
Cisco UCS driver
----------------
@@ -118,5 +101,8 @@ and as of Ocata release they are removed form ironic:
- AMT driver - available as part of ironic-staging-drivers_
- iBoot driver - available as part of ironic-staging-drivers_
- Wake-On-Lan driver - available as part of ironic-staging-drivers_
+- Virtualbox drivers
+- SeaMicro drivers
+- MSFT OCS drivers
.. _ironic-staging-drivers: http://ironic-staging-drivers.readthedocs.io
diff --git a/doc/source/drivers/seamicro.rst b/doc/source/drivers/seamicro.rst
deleted file mode 100644
index c475278d9..000000000
--- a/doc/source/drivers/seamicro.rst
+++ /dev/null
@@ -1,117 +0,0 @@
-.. _SeaMicro:
-
-===============
-SeaMicro driver
-===============
-
-Overview
-========
-The SeaMicro power driver enables you to take advantage of power cycle
-management of servers (nodes) within the SeaMicro chassis. The SeaMicro
-driver is targeted for SeaMicro Fabric Compute systems.
-
-Prerequisites
-=============
-
-* ``python-seamicroclient`` is a python package which contains a set of modules
- for managing SeaMicro Fabric Compute systems.
-
- Install ``python-seamicroclient`` [1]_ module on the Ironic conductor node.
- Minimum version required is 0.4.0::
-
- $ pip install "python-seamicroclient>=0.4.0"
-
-Drivers
-=======
-
-pxe_seamicro driver
-^^^^^^^^^^^^^^^^^^^
-
-Overview
-~~~~~~~~
-``pxe_seamicro`` driver uses PXE/iSCSI (just like ``pxe_ipmitool`` driver) to
-deploy the image and uses SeaMicro to do all management operations on the
-baremetal node (instead of using IPMI).
-
-Target Users
-~~~~~~~~~~~~
-* Users who want to use PXE/iSCSI for deployment in their environment.
-* Users who want to use SeaMicro Fabric Compute systems.
-
-Tested Platforms
-~~~~~~~~~~~~~~~~
-This driver works on SeaMicro Fabric Compute system.
-It has been tested with the following servers:
-
-* SeaMicro SM15000-XN
-* SeaMicro SM15000-OP
-
-Requirements
-~~~~~~~~~~~~
-None.
-
-Configuring and Enabling the driver
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-1. Build or download a deploy image, see `Building or downloading a deploy ramdisk image`_.
-
-2. Upload these images to Glance::
-
- glance image-create --name deploy-ramdisk.kernel --disk-format aki --container-format aki < deploy-ramdisk.kernel
- glance image-create --name deploy-ramdisk.initramfs --disk-format ari --container-format ari < deploy-ramdisk.initramfs
-
-3. Add ``pxe_seamicro`` to the list of ``enabled_drivers`` in
- ``/etc/ironic/ironic.conf``. For example::
-
- enabled_drivers = pxe_ipmitool,pxe_seamicro
-
-4. Restart the Ironic conductor service::
-
- service ironic-conductor restart
-
-Registering SeaMicro node in Ironic
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Nodes configured for SeaMicro driver should have the ``driver`` property set to
-``pxe_seamicro``. The following configuration values are also required in
-``driver_info``:
-
-- ``seamicro_api_endpoint``: IP address or hostname of the SeaMicro with valid
- URL as http://<IP_address/hostname>/v2.0
-- ``seamicro_server_id``: SeaMicro Server ID. Expected format is <int>/<int>
-- ``seamicro_username``: SeaMicro Username with administrator privileges.
-- ``seamicro_password``: Password for the above SeaMicro user.
-- ``deploy_kernel``: The Glance UUID of the deployment kernel.
-- ``deploy_ramdisk``: The Glance UUID of the deployment ramdisk.
-- ``seamicro_api_version``: (optional) SeaMicro API Version defaults to "2".
-- ``seamicro_terminal_port``: (optional) Node's UDP port for console access.
- Any unused port on the Ironic conductor node may be used.
-
-The following sequence of commands can be used to enroll a SeaMicro node and
-boot an instance on it:
-
- Create nova baremetal flavor corresponding to SeaMicro server's config::
-
- nova flavor-create baremetal auto <memory_size_in_MB> <disk_size_in_GB> <number_of_cpus>
-
- Create Node::
-
- ironic node-create -d pxe_seamicro -i seamicro_api_endpoint=https://<seamicro_ip_address>/ -i seamicro_server_id=<seamicro_server_id> -i seamicro_username=<seamicro_username> -i seamicro_password=<seamicro_password> -i seamicro_api_version=<seamicro_api_version> -i seamicro_terminal_port=<seamicro_terminal_port> -i deploy_kernel=<glance_uuid_of_deploy_kernel> -i deploy_ramdisk=<glance_uuid_of_deploy_ramdisk> -p cpus=<number_of_cpus> -p memory_mb=<memory_size_in_MB> -p local_gb=<local_disk_size_in_GB> -p cpu_arch=<cpu_arch>
-
- Associate port with the node created::
-
- ironic port-create -n $NODE -a <MAC_address_of_SeaMicro_server's_NIC>
-
- Associate properties with the flavor::
-
- nova flavor-key baremetal set "cpu_arch"=<cpu_arch>
-
- Boot the Instance::
-
- nova boot --flavor baremetal --image test-image instance-1
-
-References
-==========
-.. [1] Python-seamicroclient - https://pypi.python.org/pypi/python-seamicroclient
-.. [2] DiskImage-Builder - http://docs.openstack.org/developer/diskimage-builder/
-
-.. _`Building or downloading a deploy ramdisk image`: http://docs.openstack.org/project-install-guide/baremetal/draft/deploy-ramdisk.html
diff --git a/doc/source/drivers/vbox.rst b/doc/source/drivers/vbox.rst
deleted file mode 100644
index 0380478d4..000000000
--- a/doc/source/drivers/vbox.rst
+++ /dev/null
@@ -1,121 +0,0 @@
-.. _vbox:
-
-==================
-VirtualBox drivers
-==================
-
-Overview
-========
-
-VirtualBox drivers can be used to test Ironic by using VirtualBox VMs to
-simulate bare metal nodes.
-
-Ironic provides support via the ``pxe_ssh`` and ``agent_ssh`` drivers for using
-a VirtualBox VM as a bare metal target and do provisioning on it. It works by
-connecting via SSH into the VirtualBox host and running commands using
-VBoxManage. This works well if you have VirtualBox installed on a Linux box.
-But when VirtualBox is installed on a Windows box, configuring and getting SSH
-to work with VBoxManage is difficult (if not impossible) due to the following
-reasons:
-
-* Windows doesn't come with native SSH support and one needs to use some
- third-party software to enable SSH support on Windows.
-* Even after configuring SSH, VBoxManage doesn't work remotely due to how
- Windows manages user accounts -- the native Windows user account is different
- from the corresponding SSH user account, and VBoxManage doesn't work
- properly when done with the SSH user account.
-* Even after tweaking the policies of the VirtualBox application, the remote
- VBoxManage and VBoxSvc don't sync each other properly and often results in
- a crash.
-
-VirtualBox drivers use SOAP to talk to the VirtualBox web service running on
-the VirtualBox host. These drivers are primarily intended for Ironic developers
-running Windows on their laptops/desktops, although they can be used on other
-operating systems as well. Using these drivers, a developer could configure a
-cloud controller on one VirtualBox VM and use other VMs in the same VirtualBox
-as bare metals for that cloud controller.
-
-These VirtualBox drivers are available :
-
-* ``pxe_vbox``: uses iSCSI-based deployment mechanism.
-* ``agent_vbox``: uses agent-based deployment mechanism.
-* ``fake_vbox``: uses VirtualBox for power and management, but uses fake
- deploy.
-
-
-Setting up development environment
-==================================
-
-* Install VirtualBox on your desktop or laptop.
-
-* Create a VM for the cloud controller. Do not power on the VM now.
- For example, ``cloud-controller``.
-
-* In VirtualBox Manager, Select ``cloud-controller`` VM -> Click Settings ->
- Network -> Adapter 2 -> Select 'Enable Network Adapter' ->
- Select Attached to: Internal Network -> Select Name: intnet
-
-* Create a VM in VirtualBox to act as bare metal. A VM with 1 CPU,
- 1 GB memory should be sufficient. Let's name this VM as ``baremetal``.
-
-* In VirtualBox Manager, Select ``baremetal`` VM -> Click Settings ->
- Network -> Adapter 1 -> Select 'Enable Network Adapter' ->
- Select Attached to: Internal Network -> Select Name: intnet
-
-* Configure the VirtualBox web service to disable authentication. (This is
- only a suggestion. If you want, enable authentication with the appropriate
- web service authentication library.)
-
- ::
-
- VBoxManage setproperty websrvauthlibrary null
-
-* Run VirtualBox web service::
-
- C:\Program Files\Oracle\VirtualBox\VBoxWebSrv.exe
-
-* Power on the ``cloud-controller`` VM.
-
-* All the following instructions are to be done in the ``cloud-controller`` VM.
-
-* Install the GNU/Linux distribution of your choice.
-
-* Set up devstack.
-
-* Install pyremotevbox::
-
- sudo pip install "pyremotevbox>=0.5.0"
-
-* Enable one (or more) of the VirtualBox drivers (``pxe_vbox``, ``agent_vbox``,
- or ``fake_vbox``) via the ``enabled_drivers`` configuration option in
- ``/etc/ironic/ironic.conf``, and restart Ironic conductor.
-
-* Set up flat networking on ``eth1``. For details on how to do this, see
- `Configure Networking to communicate with the bare metal server`_.
-
-* Enroll a VirtualBox node. The following examples use the ``pxe_vbox``
- driver.
-
- ::
-
- ironic node-create -d pxe_vbox -i virtualbox_host='10.0.2.2' -i virtualbox_vmname='baremetal'
-
- If you are using authentication with VirtualBox web service, your username
- and password need to be provided. The ironic node-create command will look
- like::
-
- ironic node-create -d pxe_vbox -i virtualbox_host='10.0.2.2' -i virtualbox_vmname='baremetal' -i virtualbox_username=<username> -i virtualbox_password=<password>
-
- If VirtualBox web service is listening on a different port than the default
- 18083, then that port may be specified using the driver_info
- parameter ``virtualbox_port``.
-
-* Add other Node properties and trigger provisioning on the bare metal node.
-
- .. note::
- When a newly created bare metal VM is powered on for the first time by
- Ironic (during provisioning), VirtualBox will automatically pop up a
- dialog box asking to 'Select start-up disk'. Just press 'Cancel' to
- continue booting the VM.
-
-.. _`Configure Networking to communicate with the bare metal server`: http://docs.openstack.org/project-install-guide/baremetal/draft/configure-integration.html#configure-networking-to-communicate-with-the-bare-metal-server
diff --git a/driver-requirements.txt b/driver-requirements.txt
index 1c38fb195..af57659d0 100644
--- a/driver-requirements.txt
+++ b/driver-requirements.txt
@@ -10,14 +10,8 @@ pysnmp
python-ironic-inspector-client>=1.5.0
python-oneviewclient<3.0.0,>=2.5.2
python-scciclient>=0.4.0
-python-seamicroclient>=0.4.0
UcsSdk==0.8.2.2
python-dracclient>=0.1.0
-# 'pxe_vbox' and 'agent_vbox' drivers require pyremotevbox library.
-# Refer documentation on how to install and configure this:
-# http://docs.openstack.org/developer/ironic/drivers/vbox.html
-pyremotevbox>=0.5.0
-
# The CIMC drivers use the Cisco IMC SDK version 0.7.2 or greater
ImcSdk>=0.7.2
diff --git a/etc/ironic/ironic.conf.sample b/etc/ironic/ironic.conf.sample
index 13f44e9db..d5e1196c2 100644
--- a/etc/ironic/ironic.conf.sample
+++ b/etc/ironic/ironic.conf.sample
@@ -3291,20 +3291,6 @@
#ipxe_use_swift = false
-[seamicro]
-
-#
-# From ironic
-#
-
-# Maximum retries for SeaMicro operations (integer value)
-#max_retry = 3
-
-# Seconds to wait for power action to be completed (integer
-# value)
-#action_timeout = 10
-
-
[service_catalog]
#
@@ -3543,16 +3529,3 @@
# Username (string value)
# Deprecated group/name - [swift]/user-name
#username = <None>
-
-
-[virtualbox]
-
-#
-# From ironic
-#
-
-# Port on which VirtualBox web service is listening. (port
-# value)
-# Minimum value: 0
-# Maximum value: 65535
-#port = 18083
diff --git a/install-guide/source/standalone.rst b/install-guide/source/standalone.rst
index 6e83c0079..0cbf17851 100644
--- a/install-guide/source/standalone.rst
+++ b/install-guide/source/standalone.rst
@@ -43,8 +43,8 @@ service via hrefs.
There are however some limitations for different drivers:
* If you're using one of the drivers that use agent deploy method (namely,
- ``agent_ilo``, ``agent_ipmitool``, ``agent_pyghmi``, ``agent_ssh`` or
- ``agent_vbox``) you have to know MD5 checksum for your instance image. To
+ ``agent_ilo``, ``agent_ipmitool``, ``agent_pyghmi`` or ``agent_ssh``)
+ you have to know MD5 checksum for your instance image. To
compute it, you can use the following command::
md5sum image.qcow2
diff --git a/ironic/common/exception.py b/ironic/common/exception.py
index bc1e5facc..823c261a2 100644
--- a/ironic/common/exception.py
+++ b/ironic/common/exception.py
@@ -476,10 +476,6 @@ class IPMIFailure(IronicException):
_msg_fmt = _("IPMI call failed: %(cmd)s.")
-class MSFTOCSClientApiException(IronicException):
- _msg_fmt = _("MSFT OCS call failed.")
-
-
class SSHConnectFailed(IronicException):
_msg_fmt = _("Failed to establish SSH connection to host %(host)s.")
@@ -666,11 +662,6 @@ class IRMCSharedFileSystemNotMounted(IronicException):
_msg_fmt = _("iRMC shared file system '%(share)s' is not mounted.")
-class VirtualBoxOperationFailed(IronicException):
- _msg_fmt = _("VirtualBox operation '%(operation)s' failed. "
- "Error: %(error)s")
-
-
class HardwareInspectionFailure(IronicException):
_msg_fmt = _("Failed to inspect hardware. Reason: %(error)s")
diff --git a/ironic/conf/__init__.py b/ironic/conf/__init__.py
index 6456ddc6c..9c2097c24 100644
--- a/ironic/conf/__init__.py
+++ b/ironic/conf/__init__.py
@@ -38,12 +38,10 @@ from ironic.conf import metrics_statsd
from ironic.conf import neutron
from ironic.conf import oneview
from ironic.conf import pxe
-from ironic.conf import seamicro
from ironic.conf import service_catalog
from ironic.conf import snmp
from ironic.conf import ssh
from ironic.conf import swift
-from ironic.conf import virtualbox
CONF = cfg.CONF
@@ -70,9 +68,7 @@ metrics_statsd.register_opts(CONF)
neutron.register_opts(CONF)
oneview.register_opts(CONF)
pxe.register_opts(CONF)
-seamicro.register_opts(CONF)
service_catalog.register_opts(CONF)
snmp.register_opts(CONF)
ssh.register_opts(CONF)
swift.register_opts(CONF)
-virtualbox.register_opts(CONF)
diff --git a/ironic/conf/opts.py b/ironic/conf/opts.py
index b365037d0..3c9caf76d 100644
--- a/ironic/conf/opts.py
+++ b/ironic/conf/opts.py
@@ -54,12 +54,10 @@ _opts = [
('neutron', ironic.conf.neutron.list_opts()),
('oneview', ironic.conf.oneview.opts),
('pxe', ironic.conf.pxe.opts),
- ('seamicro', ironic.conf.seamicro.opts),
('service_catalog', ironic.conf.service_catalog.list_opts()),
('snmp', ironic.conf.snmp.opts),
('ssh', ironic.conf.ssh.opts),
('swift', ironic.conf.swift.list_opts()),
- ('virtualbox', ironic.conf.virtualbox.opts),
]
diff --git a/ironic/conf/seamicro.py b/ironic/conf/seamicro.py
deleted file mode 100644
index 821112245..000000000
--- a/ironic/conf/seamicro.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2016 Intel Corporation
-#
-# 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.IntOpt('max_retry',
- default=3,
- help=_('Maximum retries for SeaMicro operations')),
- cfg.IntOpt('action_timeout',
- default=10,
- help=_('Seconds to wait for power action to be completed'))
-]
-
-opt_group = cfg.OptGroup(name='seamicro',
- title='Options for the seamicro power driver')
-
-
-def register_opts(conf):
- conf.register_group(opt_group)
- conf.register_opts(opts, group=opt_group)
diff --git a/ironic/conf/virtualbox.py b/ironic/conf/virtualbox.py
deleted file mode 100644
index 24a619338..000000000
--- a/ironic/conf/virtualbox.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2016 Intel Corporation
-#
-# 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.PortOpt('port',
- default=18083,
- help=_('Port on which VirtualBox web service is listening.')),
-]
-
-
-def register_opts(conf):
- conf.register_opts(opts, group='virtualbox')
diff --git a/ironic/drivers/agent.py b/ironic/drivers/agent.py
index 44065a971..c4c36f02c 100644
--- a/ironic/drivers/agent.py
+++ b/ironic/drivers/agent.py
@@ -27,7 +27,6 @@ from ironic.drivers.modules import pxe
from ironic.drivers.modules import ssh
from ironic.drivers.modules.ucs import management as ucs_mgmt
from ironic.drivers.modules.ucs import power as ucs_power
-from ironic.drivers.modules import virtualbox
# For backward compatibility
@@ -87,33 +86,6 @@ class AgentAndSSHDriver(base.BaseDriver):
self.console = ssh.ShellinaboxConsole()
-class AgentAndVirtualBoxDriver(base.BaseDriver):
- """Agent + VirtualBox driver.
-
- NOTE: This driver is meant only for testing environments.
-
- This driver implements the `core` functionality, combining
- :class:`ironic.drivers.modules.virtualbox.VirtualBoxPower` (for power
- on/off and reboot of VirtualBox virtual machines), with
- :class:`ironic.drivers.modules.agent.AgentDeploy` (for image
- deployment). Implementations are in those respective classes; this class
- is merely the glue between them.
- """
-
- supported = False
-
- def __init__(self):
- if not importutils.try_import('pyremotevbox'):
- raise exception.DriverLoadError(
- driver=self.__class__.__name__,
- reason=_("Unable to import pyremotevbox library"))
- self.power = virtualbox.VirtualBoxPower()
- self.boot = pxe.PXEBoot()
- self.deploy = agent.AgentDeploy()
- self.management = virtualbox.VirtualBoxManagement()
- self.raid = agent.AgentRAID()
-
-
class AgentAndUcsDriver(base.BaseDriver):
"""Agent + Cisco UCSM driver.
diff --git a/ironic/drivers/fake.py b/ironic/drivers/fake.py
index be838e975..e926aaa8f 100644
--- a/ironic/drivers/fake.py
+++ b/ironic/drivers/fake.py
@@ -42,18 +42,14 @@ from ironic.drivers.modules.irmc import inspect as irmc_inspect
from ironic.drivers.modules.irmc import management as irmc_management
from ironic.drivers.modules.irmc import power as irmc_power
from ironic.drivers.modules import iscsi_deploy
-from ironic.drivers.modules.msftocs import management as msftocs_management
-from ironic.drivers.modules.msftocs import power as msftocs_power
from ironic.drivers.modules.oneview import common as oneview_common
from ironic.drivers.modules.oneview import management as oneview_management
from ironic.drivers.modules.oneview import power as oneview_power
from ironic.drivers.modules import pxe
-from ironic.drivers.modules import seamicro
from ironic.drivers.modules import snmp
from ironic.drivers.modules import ssh
from ironic.drivers.modules.ucs import management as ucs_mgmt
from ironic.drivers.modules.ucs import power as ucs_power
-from ironic.drivers.modules import virtualbox
from ironic.drivers import utils
@@ -146,23 +142,6 @@ class FakeIPMINativeDriver(base.BaseDriver):
self.management = ipminative.NativeIPMIManagement()
-class FakeSeaMicroDriver(base.BaseDriver):
- """Fake SeaMicro driver."""
-
- supported = False
-
- def __init__(self):
- if not importutils.try_import('seamicroclient'):
- raise exception.DriverLoadError(
- driver=self.__class__.__name__,
- reason=_("Unable to import seamicroclient library"))
- self.power = seamicro.Power()
- self.deploy = fake.FakeDeploy()
- self.management = seamicro.Management()
- self.vendor = seamicro.VendorPassthru()
- self.console = seamicro.ShellinaboxConsole()
-
-
class FakeAgentDriver(base.BaseDriver):
"""Example implementation of an AgentDriver."""
@@ -230,21 +209,6 @@ class FakeIRMCDriver(base.BaseDriver):
self.inspect = irmc_inspect.IRMCInspect()
-class FakeVirtualBoxDriver(base.BaseDriver):
- """Fake VirtualBox driver."""
-
- supported = False
-
- def __init__(self):
- if not importutils.try_import('pyremotevbox'):
- raise exception.DriverLoadError(
- driver=self.__class__.__name__,
- reason=_("Unable to import pyremotevbox library"))
- self.power = virtualbox.VirtualBoxPower()
- self.deploy = fake.FakeDeploy()
- self.management = virtualbox.VirtualBoxManagement()
-
-
class FakeIPMIToolInspectorDriver(base.BaseDriver):
"""Fake Inspector driver."""
@@ -260,17 +224,6 @@ class FakeIPMIToolInspectorDriver(base.BaseDriver):
self.inspect = inspector.Inspector()
-class FakeMSFTOCSDriver(base.BaseDriver):
- """Fake MSFT OCS driver."""
-
- supported = False
-
- def __init__(self):
- self.power = msftocs_power.MSFTOCSPower()
- self.deploy = fake.FakeDeploy()
- self.management = msftocs_management.MSFTOCSManagement()
-
-
class FakeUcsDriver(base.BaseDriver):
"""Fake UCS driver."""
diff --git a/ironic/drivers/modules/msftocs/__init__.py b/ironic/drivers/modules/msftocs/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/ironic/drivers/modules/msftocs/__init__.py
+++ /dev/null
diff --git a/ironic/drivers/modules/msftocs/common.py b/ironic/drivers/modules/msftocs/common.py
deleted file mode 100644
index 97d069967..000000000
--- a/ironic/drivers/modules/msftocs/common.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright 2015 Cloudbase Solutions Srl
-# 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 copy
-import re
-
-import six
-
-from ironic.common import exception
-from ironic.common.i18n import _
-from ironic.drivers.modules.msftocs import msftocsclient
-
-REQUIRED_PROPERTIES = {
- 'msftocs_base_url': _('Base url of the OCS chassis manager REST API, '
- 'e.g.: http://10.0.0.1:8000. Required.'),
- 'msftocs_blade_id': _('Blade id, must be a number between 1 and the '
- 'maximum number of blades available in the chassis. '
- 'Required.'),
- 'msftocs_username': _('Username to access the chassis manager REST API. '
- 'Required.'),
- 'msftocs_password': _('Password to access the chassis manager REST API. '
- 'Required.'),
-}
-
-
-def get_client_info(driver_info):
- """Returns an instance of the REST API client and the blade id.
-
- :param driver_info: the node's driver_info dict.
- """
- client = msftocsclient.MSFTOCSClientApi(driver_info['msftocs_base_url'],
- driver_info['msftocs_username'],
- driver_info['msftocs_password'])
- return client, driver_info['msftocs_blade_id']
-
-
-def get_properties():
- """Returns the driver's properties."""
- return copy.deepcopy(REQUIRED_PROPERTIES)
-
-
-def _is_valid_url(url):
- """Checks whether a URL is valid.
-
- :param url: a url string.
- :returns: True if the url is valid or None, False otherwise.
- """
- r = re.compile(
- r'^https?://'
- r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)*[A-Z]{2,6}\.?|'
- r'localhost|'
- r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
- r'(?::\d+)?'
- r'(?:/?|[/?]\S+)$', re.IGNORECASE)
-
- return bool(isinstance(url, six.string_types) and r.search(url))
-
-
-def _check_required_properties(driver_info):
- """Checks if all required properties are present.
-
- :param driver_info: the node's driver_info dict.
- :raises: MissingParameterValue if one or more required properties are
- missing.
- """
- missing_properties = set(REQUIRED_PROPERTIES) - set(driver_info)
- if missing_properties:
- raise exception.MissingParameterValue(
- _('The following parameters were missing: %s') %
- ' '.join(missing_properties))
-
-
-def parse_driver_info(node):
- """Checks for the required properties and values validity.
-
- :param node: the target node.
- :raises: MissingParameterValue if one or more required properties are
- missing.
- :raises: InvalidParameterValue if a parameter value is invalid.
- """
- driver_info = node.driver_info
- _check_required_properties(driver_info)
-
- base_url = driver_info.get('msftocs_base_url')
- if not _is_valid_url(base_url):
- raise exception.InvalidParameterValue(
- _('"%s" is not a valid "msftocs_base_url"') % base_url)
-
- blade_id = driver_info.get('msftocs_blade_id')
- try:
- blade_id = int(blade_id)
- except ValueError:
- raise exception.InvalidParameterValue(
- _('"%s" is not a valid "msftocs_blade_id"') % blade_id)
- if blade_id < 1:
- raise exception.InvalidParameterValue(
- _('"msftocs_blade_id" must be greater than 0. The provided value '
- 'is: %s') % blade_id)
diff --git a/ironic/drivers/modules/msftocs/management.py b/ironic/drivers/modules/msftocs/management.py
deleted file mode 100644
index f148c4394..000000000
--- a/ironic/drivers/modules/msftocs/management.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# Copyright 2015 Cloudbase Solutions Srl
-# 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 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.msftocs import common as msftocs_common
-from ironic.drivers.modules.msftocs import msftocsclient
-from ironic.drivers import utils as drivers_utils
-
-BOOT_TYPE_TO_DEVICE_MAP = {
- msftocsclient.BOOT_TYPE_FORCE_PXE: boot_devices.PXE,
- msftocsclient.BOOT_TYPE_FORCE_DEFAULT_HDD: boot_devices.DISK,
- msftocsclient.BOOT_TYPE_FORCE_INTO_BIOS_SETUP: boot_devices.BIOS,
-}
-DEVICE_TO_BOOT_TYPE_MAP = {v: k for k, v in BOOT_TYPE_TO_DEVICE_MAP.items()}
-
-DEFAULT_BOOT_DEVICE = boot_devices.DISK
-
-
-class MSFTOCSManagement(base.ManagementInterface):
- def get_properties(self):
- """Returns the driver's properties."""
- return msftocs_common.get_properties()
-
- def validate(self, task):
- """Validate the driver_info in the node.
-
- Check if the driver_info contains correct required fields.
-
- :param task: a TaskManager instance containing the target node.
- :raises: MissingParameterValue if any required parameters are missing.
- :raises: InvalidParameterValue if any parameters have invalid values.
- """
- msftocs_common.parse_driver_info(task.node)
-
- def get_supported_boot_devices(self, task):
- """Get a list of the supported boot devices.
-
- :param task: a task from TaskManager.
- :returns: A list with the supported boot devices.
- """
- return list(BOOT_TYPE_TO_DEVICE_MAP.values())
-
- def _check_valid_device(self, device, node):
- """Checks if the desired boot device is valid for this driver.
-
- :param device: a boot device.
- :param node: the target node.
- :raises: InvalidParameterValue if the boot device is not valid.
- """
- if device not in DEVICE_TO_BOOT_TYPE_MAP:
- raise exception.InvalidParameterValue(
- _("set_boot_device called with invalid device %(device)s for "
- "node %(node_id)s.") %
- {'device': device, 'node_id': node.uuid})
-
- @task_manager.require_exclusive_lock
- def set_boot_device(self, task, device, persistent=False):
- """Set the boot device for the task's node.
-
- Set the boot device to use on next boot of the node.
-
- :param task: a task from TaskManager.
- :param device: the boot device.
- :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.
- """
- self._check_valid_device(device, task.node)
- client, blade_id = msftocs_common.get_client_info(
- task.node.driver_info)
-
- boot_mode = drivers_utils.get_node_capability(task.node, 'boot_mode')
- uefi = (boot_mode == 'uefi')
-
- boot_type = DEVICE_TO_BOOT_TYPE_MAP[device]
- client.set_next_boot(blade_id, boot_type, persistent, uefi)
-
- def get_boot_device(self, task):
- """Get the current boot device for the task's node.
-
- Returns the current boot device of the node.
-
- :param task: a task from TaskManager.
- :returns: a dictionary containing:
-
- :boot_device: the boot device
- :persistent: Whether the boot device will persist to all
- future boots or not, None if it is unknown.
-
- """
- client, blade_id = msftocs_common.get_client_info(
- task.node.driver_info)
- device = BOOT_TYPE_TO_DEVICE_MAP.get(
- client.get_next_boot(blade_id), DEFAULT_BOOT_DEVICE)
-
- # Note(alexpilotti): Although the ChasssisManager REST API allows to
- # specify the persistent boot status in SetNextBoot, currently it does
- # not provide a way to retrieve the value with GetNextBoot.
- # This is being addressed in the ChassisManager API.
- return {'boot_device': device,
- 'persistent': None}
-
- def get_sensors_data(self, task):
- raise NotImplementedError()
diff --git a/ironic/drivers/modules/msftocs/msftocsclient.py b/ironic/drivers/modules/msftocs/msftocsclient.py
deleted file mode 100644
index d511c68ad..000000000
--- a/ironic/drivers/modules/msftocs/msftocsclient.py
+++ /dev/null
@@ -1,176 +0,0 @@
-# Copyright 2015 Cloudbase Solutions Srl
-# 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.
-
-"""
-MSFT OCS ChassisManager v2.0 REST API client
-https://github.com/MSOpenTech/ChassisManager
-"""
-
-import posixpath
-from xml import etree
-
-from oslo_log import log
-import requests
-from requests import auth
-from requests import exceptions as requests_exceptions
-
-from ironic.common import exception
-from ironic.common.i18n import _, _LE
-
-LOG = log.getLogger(__name__)
-
-WCSNS = 'http://schemas.datacontract.org/2004/07/Microsoft.GFS.WCS.Contracts'
-COMPLETION_CODE_SUCCESS = "Success"
-
-BOOT_TYPE_UNKNOWN = 0
-BOOT_TYPE_NO_OVERRIDE = 1
-BOOT_TYPE_FORCE_PXE = 2
-BOOT_TYPE_FORCE_DEFAULT_HDD = 3
-BOOT_TYPE_FORCE_INTO_BIOS_SETUP = 4
-BOOT_TYPE_FORCE_FLOPPY_OR_REMOVABLE = 5
-
-BOOT_TYPE_MAP = {
- 'Unknown': BOOT_TYPE_UNKNOWN,
- 'NoOverride': BOOT_TYPE_NO_OVERRIDE,
- 'ForcePxe': BOOT_TYPE_FORCE_PXE,
- 'ForceDefaultHdd': BOOT_TYPE_FORCE_DEFAULT_HDD,
- 'ForceIntoBiosSetup': BOOT_TYPE_FORCE_INTO_BIOS_SETUP,
- 'ForceFloppyOrRemovable': BOOT_TYPE_FORCE_FLOPPY_OR_REMOVABLE,
-}
-
-POWER_STATUS_ON = "ON"
-POWER_STATUS_OFF = "OFF"
-
-
-class MSFTOCSClientApi(object):
- def __init__(self, base_url, username, password):
- self._base_url = base_url
- self._username = username
- self._password = password
-
- def _exec_cmd(self, rel_url):
- """Executes a command by calling the chassis manager API."""
- url = posixpath.join(self._base_url, rel_url)
- try:
- response = requests.get(
- url, auth=auth.HTTPBasicAuth(self._username, self._password))
- response.raise_for_status()
- except requests_exceptions.RequestException as ex:
- msg = _("HTTP call failed: %s") % ex
- LOG.exception(msg)
- raise exception.MSFTOCSClientApiException(msg)
-
- xml_response = response.text
- LOG.debug("Call to %(url)s got response: %(xml_response)s",
- {"url": url, "xml_response": xml_response})
- return xml_response
-
- def _check_completion_code(self, xml_response):
- try:
- et = etree.ElementTree.fromstring(xml_response)
- except etree.ElementTree.ParseError as ex:
- LOG.exception(_LE("XML parsing failed: %s"), ex)
- raise exception.MSFTOCSClientApiException(
- _("Invalid XML: %s") % xml_response)
- item = et.find("./n:completionCode", namespaces={'n': WCSNS})
- if item is None or item.text != COMPLETION_CODE_SUCCESS:
- raise exception.MSFTOCSClientApiException(
- _("Operation failed: %s") % xml_response)
- return et
-
- def get_blade_state(self, blade_id):
- """Returns whether a blade's chipset is receiving power (soft-power).
-
- :param blade_id: the blade id
- :returns: one of:
- POWER_STATUS_ON,
- POWER_STATUS_OFF
- :raises: MSFTOCSClientApiException
- """
- et = self._check_completion_code(
- self._exec_cmd("GetBladeState?bladeId=%d" % blade_id))
- return et.find('./n:bladeState', namespaces={'n': WCSNS}).text
-
- def set_blade_on(self, blade_id):
- """Supplies power to a blade chipset (soft-power state).
-
- :param blade_id: the blade id
- :raises: MSFTOCSClientApiException
- """
- self._check_completion_code(
- self._exec_cmd("SetBladeOn?bladeId=%d" % blade_id))
-
- def set_blade_off(self, blade_id):
- """Shuts down a given blade (soft-power state).
-
- :param blade_id: the blade id
- :raises: MSFTOCSClientApiException
- """
- self._check_completion_code(
- self._exec_cmd("SetBladeOff?bladeId=%d" % blade_id))
-
- def set_blade_power_cycle(self, blade_id, off_time=0):
- """Performs a soft reboot of a given blade.
-
- :param blade_id: the blade id
- :param off_time: seconds to wait between shutdown and boot
- :raises: MSFTOCSClientApiException
- """
- self._check_completion_code(
- self._exec_cmd("SetBladeActivePowerCycle?bladeId=%(blade_id)d&"
- "offTime=%(off_time)d" %
- {"blade_id": blade_id, "off_time": off_time}))
-
- def get_next_boot(self, blade_id):
- """Returns the next boot device configured for a given blade.
-
- :param blade_id: the blade id
- :returns: one of:
- BOOT_TYPE_UNKNOWN,
- BOOT_TYPE_NO_OVERRIDE,
- BOOT_TYPE_FORCE_PXE, BOOT_TYPE_FORCE_DEFAULT_HDD,
- BOOT_TYPE_FORCE_INTO_BIOS_SETUP,
- BOOT_TYPE_FORCE_FLOPPY_OR_REMOVABLE
- :raises: MSFTOCSClientApiException
- """
- et = self._check_completion_code(
- self._exec_cmd("GetNextBoot?bladeId=%d" % blade_id))
- return BOOT_TYPE_MAP[
- et.find('./n:nextBoot', namespaces={'n': WCSNS}).text]
-
- def set_next_boot(self, blade_id, boot_type, persistent=True, uefi=True):
- """Sets the next boot device for a given blade.
-
- :param blade_id: the blade id
- :param boot_type: possible values:
- BOOT_TYPE_UNKNOWN,
- BOOT_TYPE_NO_OVERRIDE,
- BOOT_TYPE_FORCE_PXE,
- BOOT_TYPE_FORCE_DEFAULT_HDD,
- BOOT_TYPE_FORCE_INTO_BIOS_SETUP,
- BOOT_TYPE_FORCE_FLOPPY_OR_REMOVABLE
- :param persistent: whether this setting affects the next boot only or
- every subsequent boot
- :param uefi: True if UEFI, False otherwise
- :raises: MSFTOCSClientApiException
- """
- self._check_completion_code(
- self._exec_cmd(
- "SetNextBoot?bladeId=%(blade_id)d&bootType=%(boot_type)d&"
- "uefi=%(uefi)s&persistent=%(persistent)s" %
- {"blade_id": blade_id,
- "boot_type": boot_type,
- "uefi": str(uefi).lower(),
- "persistent": str(persistent).lower()}))
diff --git a/ironic/drivers/modules/msftocs/power.py b/ironic/drivers/modules/msftocs/power.py
deleted file mode 100644
index e5ce62066..000000000
--- a/ironic/drivers/modules/msftocs/power.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2015 Cloudbase Solutions Srl
-# 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.
-
-"""
-MSFT OCS Power Driver
-"""
-from oslo_log import log
-
-from ironic.common import exception
-from ironic.common.i18n import _, _LE
-from ironic.common import states
-from ironic.conductor import task_manager
-from ironic.drivers import base
-from ironic.drivers.modules.msftocs import common as msftocs_common
-from ironic.drivers.modules.msftocs import msftocsclient
-
-LOG = log.getLogger(__name__)
-
-POWER_STATES_MAP = {
- msftocsclient.POWER_STATUS_ON: states.POWER_ON,
- msftocsclient.POWER_STATUS_OFF: states.POWER_OFF,
-}
-
-
-class MSFTOCSPower(base.PowerInterface):
- def get_properties(self):
- """Returns the driver's properties."""
- return msftocs_common.get_properties()
-
- def validate(self, task):
- """Validate the driver_info in the node.
-
- Check if the driver_info contains correct required fields.
-
- :param task: a TaskManager instance containing the target node.
- :raises: MissingParameterValue if any required parameters are missing.
- :raises: InvalidParameterValue if any parameters have invalid values.
- """
- msftocs_common.parse_driver_info(task.node)
-
- def get_power_state(self, task):
- """Get the power state from the node.
-
- :param task: a TaskManager instance containing the target node.
- :raises: MSFTOCSClientApiException.
- """
- client, blade_id = msftocs_common.get_client_info(
- task.node.driver_info)
- return POWER_STATES_MAP[client.get_blade_state(blade_id)]
-
- @task_manager.require_exclusive_lock
- def set_power_state(self, task, pstate):
- """Set the power state of the node.
-
- Turn the node power on or off.
-
- :param task: a TaskManager instance contains the target node.
- :param pstate: The desired power state of the node.
- :raises: PowerStateFailure if the power cannot set to pstate.
- :raises: InvalidParameterValue
- """
- client, blade_id = msftocs_common.get_client_info(
- task.node.driver_info)
-
- try:
- if pstate == states.POWER_ON:
- client.set_blade_on(blade_id)
- elif pstate == states.POWER_OFF:
- client.set_blade_off(blade_id)
- else:
- raise exception.InvalidParameterValue(
- _('Unsupported target_state: %s') % pstate)
- except exception.MSFTOCSClientApiException as ex:
- LOG.exception(_LE("Changing the power state to %(pstate)s failed. "
- "Error: %(err_msg)s"),
- {"pstate": pstate, "err_msg": ex})
- raise exception.PowerStateFailure(pstate=pstate)
-
- @task_manager.require_exclusive_lock
- def reboot(self, task):
- """Cycle the power of the node
-
- :param task: a TaskManager instance contains the target node.
- :raises: PowerStateFailure if failed to reboot.
- """
- client, blade_id = msftocs_common.get_client_info(
- task.node.driver_info)
- try:
- client.set_blade_power_cycle(blade_id)
- except exception.MSFTOCSClientApiException as ex:
- LOG.exception(_LE("Reboot failed. Error: %(err_msg)s"),
- {"err_msg": ex})
- raise exception.PowerStateFailure(pstate=states.REBOOT)
diff --git a/ironic/drivers/modules/seamicro.py b/ironic/drivers/modules/seamicro.py
deleted file mode 100644
index cf45bb6d0..000000000
--- a/ironic/drivers/modules/seamicro.py
+++ /dev/null
@@ -1,672 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""
-Ironic SeaMicro interfaces.
-
-Provides basic power control of servers in SeaMicro chassis via
-python-seamicroclient.
-
-Provides vendor passthru methods for SeaMicro specific functionality.
-"""
-import os
-import re
-
-from oslo_log import log as logging
-from oslo_service import loopingcall
-from oslo_utils import importutils
-from six.moves.urllib import parse as urlparse
-
-from ironic.common import boot_devices
-from ironic.common import exception
-from ironic.common.i18n import _, _LE, _LW
-from ironic.common import states
-from ironic.common import utils
-from ironic.conductor import task_manager
-from ironic.conf import CONF
-from ironic.drivers import base
-from ironic.drivers.modules import console_utils
-
-seamicroclient = importutils.try_import('seamicroclient')
-if seamicroclient:
- from seamicroclient import client as seamicro_client
- from seamicroclient import exceptions as seamicro_client_exception
-
-LOG = logging.getLogger(__name__)
-
-_BOOT_DEVICES_MAP = {
- boot_devices.DISK: 'hd0',
- boot_devices.PXE: 'pxe',
-}
-
-REQUIRED_PROPERTIES = {
- 'seamicro_api_endpoint': _("API endpoint. Required."),
- 'seamicro_password': _("password. Required."),
- 'seamicro_server_id': _("server ID. Required."),
- 'seamicro_username': _("username. Required."),
-}
-OPTIONAL_PROPERTIES = {
- 'seamicro_api_version': _("version of SeaMicro API client; default is 2. "
- "Optional.")
-}
-COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
-COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES)
-CONSOLE_PROPERTIES = {
- 'seamicro_terminal_port': _("node's UDP port to connect to. "
- "Only required for console access.")
-}
-PORT_BASE = 2000
-
-
-def _get_client(*args, **kwargs):
- """Creates the python-seamicro_client
-
- :param kwargs: A dict of keyword arguments to be passed to the method,
- which should contain: 'username', 'password',
- 'auth_url', 'api_version' parameters.
- :returns: SeaMicro API client.
- """
-
- cl_kwargs = {'username': kwargs['username'],
- 'password': kwargs['password'],
- 'auth_url': kwargs['api_endpoint']}
- try:
- return seamicro_client.Client(kwargs['api_version'], **cl_kwargs)
- except seamicro_client_exception.UnsupportedVersion as e:
- raise exception.InvalidParameterValue(_(
- "Invalid 'seamicro_api_version' parameter. Reason: %s.") % e)
-
-
-def _parse_driver_info(node):
- """Parses and creates seamicro driver info
-
- :param node: An Ironic node object.
- :returns: SeaMicro driver info.
- :raises: MissingParameterValue if any required parameters are missing.
- :raises: InvalidParameterValue if required parameter are invalid.
- """
-
- info = node.driver_info or {}
- missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)]
- if missing_info:
- raise exception.MissingParameterValue(_(
- "SeaMicro driver requires the following parameters to be set in"
- " node's driver_info: %s.") % missing_info)
-
- api_endpoint = info.get('seamicro_api_endpoint')
- username = info.get('seamicro_username')
- password = info.get('seamicro_password')
- server_id = info.get('seamicro_server_id')
- api_version = info.get('seamicro_api_version', "2")
- port = info.get('seamicro_terminal_port')
-
- if port is not None:
- port = utils.validate_network_port(port, 'seamicro_terminal_port')
-
- r = re.compile(r"(^[0-9]+)/([0-9]+$)")
- if not r.match(server_id):
- raise exception.InvalidParameterValue(_(
- "Invalid 'seamicro_server_id' parameter in node's "
- "driver_info. Expected format of 'seamicro_server_id' "
- "is <int>/<int>"))
-
- url = urlparse.urlparse(api_endpoint)
- if (not (url.scheme == "http") or not url.netloc):
- raise exception.InvalidParameterValue(_(
- "Invalid 'seamicro_api_endpoint' parameter in node's "
- "driver_info."))
-
- res = {'username': username,
- 'password': password,
- 'api_endpoint': api_endpoint,
- 'server_id': server_id,
- 'api_version': api_version,
- 'uuid': node.uuid,
- 'port': port}
-
- return res
-
-
-def _get_server(driver_info):
- """Get server from server_id."""
-
- s_client = _get_client(**driver_info)
- return s_client.servers.get(driver_info['server_id'])
-
-
-def _get_volume(driver_info, volume_id):
- """Get volume from volume_id."""
-
- s_client = _get_client(**driver_info)
- return s_client.volumes.get(volume_id)
-
-
-def _get_power_status(node):
- """Get current power state of this node
-
- :param node: Ironic node one of :class:`ironic.db.models.Node`
- :raises: InvalidParameterValue if a seamicro parameter is invalid.
- :raises: MissingParameterValue if required seamicro parameters are
- missing.
- :raises: ServiceUnavailable on an error from SeaMicro Client.
- :returns: Power state of the given node
- """
-
- seamicro_info = _parse_driver_info(node)
- try:
- server = _get_server(seamicro_info)
- if not hasattr(server, 'active') or server.active is None:
- return states.ERROR
- if not server.active:
- return states.POWER_OFF
- elif server.active:
- return states.POWER_ON
-
- except seamicro_client_exception.NotFound:
- raise exception.NodeNotFound(node=node.uuid)
- except seamicro_client_exception.ClientException as ex:
- LOG.error(_LE("SeaMicro client exception %(msg)s for node %(uuid)s"),
- {'msg': ex.message, 'uuid': node.uuid})
- raise exception.ServiceUnavailable(message=ex.message)
-
-
-def _power_on(node, timeout=None):
- """Power ON this node
-
- :param node: An Ironic node object.
- :param timeout: Time in seconds to wait till power on is complete.
- :raises: InvalidParameterValue if a seamicro parameter is invalid.
- :raises: MissingParameterValue if required seamicro parameters are
- missing.
- :returns: Power state of the given node.
- """
- if timeout is None:
- timeout = CONF.seamicro.action_timeout
- state = [None]
- retries = [0]
- seamicro_info = _parse_driver_info(node)
- server = _get_server(seamicro_info)
-
- def _wait_for_power_on(state, retries):
- """Called at an interval until the node is powered on."""
-
- state[0] = _get_power_status(node)
- if state[0] == states.POWER_ON:
- raise loopingcall.LoopingCallDone()
-
- if retries[0] > CONF.seamicro.max_retry:
- state[0] = states.ERROR
- raise loopingcall.LoopingCallDone()
- try:
- retries[0] += 1
- server.power_on()
- except seamicro_client_exception.ClientException:
- LOG.warning(_LW("Power-on failed for node %s."),
- node.uuid)
-
- timer = loopingcall.FixedIntervalLoopingCall(_wait_for_power_on,
- state, retries)
- timer.start(interval=timeout).wait()
- return state[0]
-
-
-def _power_off(node, timeout=None):
- """Power OFF this node
-
- :param node: Ironic node one of :class:`ironic.db.models.Node`
- :param timeout: Time in seconds to wait till power off is compelete
- :raises: InvalidParameterValue if a seamicro parameter is invalid.
- :raises: MissingParameterValue if required seamicro parameters are
- missing.
- :returns: Power state of the given node
- """
- if timeout is None:
- timeout = CONF.seamicro.action_timeout
- state = [None]
- retries = [0]
- seamicro_info = _parse_driver_info(node)
- server = _get_server(seamicro_info)
-
- def _wait_for_power_off(state, retries):
- """Called at an interval until the node is powered off."""
-
- state[0] = _get_power_status(node)
- if state[0] == states.POWER_OFF:
- raise loopingcall.LoopingCallDone()
-
- if retries[0] > CONF.seamicro.max_retry:
- state[0] = states.ERROR
- raise loopingcall.LoopingCallDone()
- try:
- retries[0] += 1
- server.power_off()
- except seamicro_client_exception.ClientException:
- LOG.warning(_LW("Power-off failed for node %s."),
- node.uuid)
-
- timer = loopingcall.FixedIntervalLoopingCall(_wait_for_power_off,
- state, retries)
- timer.start(interval=timeout).wait()
- return state[0]
-
-
-def _reboot(node, timeout=None):
- """Reboot this node.
-
- :param node: Ironic node one of :class:`ironic.db.models.Node`
- :param timeout: Time in seconds to wait till reboot is compelete
- :raises: InvalidParameterValue if a seamicro parameter is invalid.
- :raises: MissingParameterValue if required seamicro parameters are
- missing.
- :returns: Power state of the given node
- """
- if timeout is None:
- timeout = CONF.seamicro.action_timeout
- state = [None]
- retries = [0]
- seamicro_info = _parse_driver_info(node)
- server = _get_server(seamicro_info)
-
- def _wait_for_reboot(state, retries):
- """Called at an interval until the node is rebooted successfully."""
-
- state[0] = _get_power_status(node)
- if state[0] == states.POWER_ON:
- raise loopingcall.LoopingCallDone()
-
- if retries[0] > CONF.seamicro.max_retry:
- state[0] = states.ERROR
- raise loopingcall.LoopingCallDone()
-
- try:
- retries[0] += 1
- server.reset()
- except seamicro_client_exception.ClientException:
- LOG.warning(_LW("Reboot failed for node %s."),
- node.uuid)
-
- timer = loopingcall.FixedIntervalLoopingCall(_wait_for_reboot,
- state, retries)
- server.reset()
- timer.start(interval=timeout).wait()
- return state[0]
-
-
-def _validate_volume(driver_info, volume_id):
- """Validates if volume is in Storage pools designated for ironic."""
-
- volume = _get_volume(driver_info, volume_id)
-
- # Check if the ironic <scard>/ironic-<pool_id>/<volume_id> naming scheme
- # is present in volume id
- try:
- pool_id = volume.id.split('/')[1].lower()
- except IndexError:
- pool_id = ""
-
- if "ironic-" in pool_id:
- return True
- else:
- raise exception.InvalidParameterValue(_(
- "Invalid volume id specified"))
-
-
-def _get_pools(driver_info, filters=None):
- """Get SeaMicro storage pools matching given filters."""
-
- s_client = _get_client(**driver_info)
- return s_client.pools.list(filters=filters)
-
-
-def _create_volume(driver_info, volume_size):
- """Create volume in the SeaMicro storage pools designated for ironic."""
-
- ironic_pools = _get_pools(driver_info, filters={'id': 'ironic-'})
- if ironic_pools is None:
- raise exception.VendorPassthruException(_(
- "No storage pools found for ironic"))
-
- least_used_pool = sorted(ironic_pools,
- key=lambda x: x.freeSize)[0]
- return _get_client(**driver_info).volumes.create(volume_size,
- least_used_pool)
-
-
-def get_telnet_port(driver_info):
- """Get SeaMicro telnet port to listen."""
- server_id = int(driver_info['server_id'].split("/")[0])
- return PORT_BASE + (10 * server_id)
-
-
-class Power(base.PowerInterface):
- """SeaMicro Power Interface.
-
- This PowerInterface class provides a mechanism for controlling the power
- state of servers in a seamicro chassis.
- """
-
- def get_properties(self):
- return COMMON_PROPERTIES
-
- def validate(self, task):
- """Check that node 'driver_info' is valid.
-
- Check that node 'driver_info' contains the required fields.
-
- :param task: a TaskManager instance containing the node to act on.
- :raises: MissingParameterValue if required seamicro parameters are
- missing.
- """
- _parse_driver_info(task.node)
-
- def get_power_state(self, task):
- """Get the current power state of the task's node.
-
- Poll the host for the current power state of the node.
-
- :param task: a TaskManager instance containing the node to act on.
- :raises: ServiceUnavailable on an error from SeaMicro Client.
- :raises: InvalidParameterValue if a seamicro parameter is invalid.
- :raises: MissingParameterValue when a required parameter is missing
- :returns: power state. One of :class:`ironic.common.states`.
-
- """
- return _get_power_status(task.node)
-
- @task_manager.require_exclusive_lock
- def set_power_state(self, task, pstate):
- """Turn the power on or off.
-
- Set the power state of a node.
-
- :param task: a TaskManager instance containing the node to act on.
- :param pstate: Either POWER_ON or POWER_OFF from :class:
- `ironic.common.states`.
- :raises: InvalidParameterValue if an invalid power state was specified
- or a seamicro parameter is invalid.
- :raises: MissingParameterValue when a required parameter is missing
- :raises: PowerStateFailure if the desired power state couldn't be set.
- """
-
- if pstate == states.POWER_ON:
- state = _power_on(task.node)
- elif pstate == states.POWER_OFF:
- state = _power_off(task.node)
- else:
- raise exception.InvalidParameterValue(_(
- "set_power_state called with invalid power state."))
-
- if state != pstate:
- raise exception.PowerStateFailure(pstate=pstate)
-
- @task_manager.require_exclusive_lock
- def reboot(self, task):
- """Cycles the power to the task's node.
-
- :param task: a TaskManager instance containing the node to act on.
- :raises: InvalidParameterValue if a seamicro parameter is invalid.
- :raises: MissingParameterValue if required seamicro parameters are
- missing.
- :raises: PowerStateFailure if the final state of the node is not
- POWER_ON.
- """
- state = _reboot(task.node)
-
- if state != states.POWER_ON:
- raise exception.PowerStateFailure(pstate=states.POWER_ON)
-
-
-class VendorPassthru(base.VendorInterface):
- """SeaMicro vendor-specific methods."""
-
- def get_properties(self):
- return COMMON_PROPERTIES
-
- def validate(self, task, method, **kwargs):
- _parse_driver_info(task.node)
-
- @base.passthru(['POST'],
- description=_("Set an untagged VLAN ID for NIC 0 of node. "
- "Required argument: 'vlan_id' - ID of "
- "untagged VLAN."))
- def set_node_vlan_id(self, task, **kwargs):
- """Sets an untagged vlan id for NIC 0 of node.
-
- @kwargs vlan_id: id of untagged vlan for NIC 0 of node
- """
- node = task.node
- vlan_id = kwargs.get('vlan_id')
- if not vlan_id:
- raise exception.MissingParameterValue(_("No vlan id provided"))
-
- seamicro_info = _parse_driver_info(node)
- try:
- server = _get_server(seamicro_info)
-
- # remove current vlan for server
- if len(server.nic['0']['untaggedVlan']) > 0:
- server.unset_untagged_vlan(server.nic['0']['untaggedVlan'])
- server = server.refresh(5)
- server.set_untagged_vlan(vlan_id)
- except seamicro_client_exception.ClientException as ex:
- LOG.error(_LE("SeaMicro client exception: %s"), ex.message)
- raise exception.VendorPassthruException(message=ex.message)
-
- properties = node.properties
- properties['seamicro_vlan_id'] = vlan_id
- node.properties = properties
- node.save()
-
- @base.passthru(['POST'],
- description=_("Attach volume to node. Arguments: "
- "1. 'volume_id' - ID of pre-provisioned "
- "volume. This is optional. If not specified, "
- "a volume is created in SeaMicro storage "
- "pool. 2. 'volume_size' - size of new volume "
- "(if volume_id is not specified)."))
- def attach_volume(self, task, **kwargs):
- """Attach a volume to a node.
-
- Attach volume from SeaMicro storage pools for ironic to node.
- If kwargs['volume_id'] not given, Create volume in SeaMicro
- storage pool and attach to node.
-
- @kwargs volume_id: id of pre-provisioned volume that is to be attached
- as root volume of node
- @kwargs volume_size: size of new volume to be created and attached
- as root volume of node
- """
- node = task.node
- seamicro_info = _parse_driver_info(node)
- volume_id = kwargs.get('volume_id')
-
- if volume_id is None:
- volume_size = kwargs.get('volume_size')
- if volume_size is None:
- raise exception.MissingParameterValue(
- _("No volume size provided for creating volume"))
- volume_id = _create_volume(seamicro_info, volume_size)
-
- if _validate_volume(seamicro_info, volume_id):
- try:
- server = _get_server(seamicro_info)
- server.detach_volume()
- server = server.refresh(5)
- server.attach_volume(volume_id)
- except seamicro_client_exception.ClientException as ex:
- LOG.error(_LE("SeaMicro client exception: %s"), ex.message)
- raise exception.VendorPassthruException(message=ex.message)
-
- properties = node.properties
- properties['seamicro_volume_id'] = volume_id
- node.properties = properties
- node.save()
-
-
-class Management(base.ManagementInterface):
-
- def get_properties(self):
- return COMMON_PROPERTIES
-
- def validate(self, task):
- """Check that 'driver_info' contains SeaMicro credentials.
-
- Validates whether the 'driver_info' property of the supplied
- task's node contains the required credentials information.
-
- :param task: a task from TaskManager.
- :raises: MissingParameterValue when a required parameter is missing
-
- """
- _parse_driver_info(task.node)
-
- def get_supported_boot_devices(self, task):
- """Get 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 list(_BOOT_DEVICES_MAP.keys())
-
- @task_manager.require_exclusive_lock
- def set_boot_device(self, task, device, persistent=False):
- """Set the boot device for the task's node.
-
- Set the boot device to use on next reboot of the node.
-
- :param task: a task from TaskManager.
- :param device: the boot device, one of
- :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. Ignored by this driver.
- :raises: InvalidParameterValue if an invalid boot device is
- specified or if a seamicro parameter is invalid.
- :raises: IronicException on an error from seamicro-client.
- :raises: MissingParameterValue when a required parameter is missing
-
- """
- if device not in self.get_supported_boot_devices(task):
- raise exception.InvalidParameterValue(_(
- "Invalid boot device %s specified.") % device)
-
- seamicro_info = _parse_driver_info(task.node)
- try:
- server = _get_server(seamicro_info)
- boot_device = _BOOT_DEVICES_MAP[device]
- server.set_boot_order(boot_device)
- except seamicro_client_exception.ClientException as ex:
- LOG.error(_LE("Seamicro set boot device failed for node "
- "%(node)s with the following error: %(error)s"),
- {'node': task.node.uuid, 'error': ex})
- raise exception.IronicException(ex)
-
- def get_boot_device(self, task):
- """Get the current boot device for the task's node.
-
- Returns the current boot device of the node. Be aware that not
- all drivers support this.
-
- :param task: a task from TaskManager.
- :returns: a dictionary containing:
-
- :boot_device: the boot device, one of
- :mod:`ironic.common.boot_devices` or None if it is unknown.
- :persistent: Whether the boot device will persist to all
- future boots or not, None if it is unknown.
-
- """
- # TODO(lucasagomes): The python-seamicroclient library currently
- # doesn't expose a method to get the boot device, update it once
- # it's implemented.
- return {'boot_device': None, 'persistent': None}
-
- def get_sensors_data(self, task):
- """Get sensors data method.
-
- Not implemented by this driver.
- :param task: a TaskManager instance.
-
- """
- raise NotImplementedError()
-
-
-class ShellinaboxConsole(base.ConsoleInterface):
- """A ConsoleInterface that uses telnet and shellinabox."""
-
- def get_properties(self):
- d = COMMON_PROPERTIES.copy()
- d.update(CONSOLE_PROPERTIES)
- return d
-
- def validate(self, task):
- """Validate the Node console info.
-
- :param task: a task from TaskManager.
- :raises: MissingParameterValue if required seamicro parameters are
- missing
- :raises: InvalidParameterValue if required parameter are invalid.
- """
- driver_info = _parse_driver_info(task.node)
- if not driver_info['port']:
- raise exception.MissingParameterValue(_(
- "Missing 'seamicro_terminal_port' parameter in node's "
- "driver_info"))
-
- def start_console(self, task):
- """Start a remote console for the node.
-
- :param task: a task from TaskManager
- :raises: MissingParameterValue if required seamicro parameters are
- missing
- :raises: ConsoleError if the directory for the PID file cannot be
- created
- :raises: ConsoleSubprocessFailed when invoking the subprocess failed
- :raises: InvalidParameterValue if required parameter are invalid.
- """
-
- driver_info = _parse_driver_info(task.node)
- telnet_port = get_telnet_port(driver_info)
- chassis_ip = urlparse.urlparse(driver_info['api_endpoint']).netloc
-
- seamicro_cmd = ("/:%(uid)s:%(gid)s:HOME:telnet %(chassis)s %(port)s"
- % {'uid': os.getuid(),
- 'gid': os.getgid(),
- 'chassis': chassis_ip,
- 'port': telnet_port})
-
- console_utils.start_shellinabox_console(driver_info['uuid'],
- driver_info['port'],
- seamicro_cmd)
-
- def stop_console(self, task):
- """Stop the remote console session for the node.
-
- :param task: a task from TaskManager
- :raises: ConsoleError if unable to stop the console
- """
-
- console_utils.stop_shellinabox_console(task.node.uuid)
-
- def get_console(self, task):
- """Get the type and connection information about the console.
-
- :raises: MissingParameterValue if required seamicro parameters are
- missing
- :raises: InvalidParameterValue if required parameter are invalid.
- """
-
- driver_info = _parse_driver_info(task.node)
- url = console_utils.get_shellinabox_console_url(driver_info['port'])
- return {'type': 'shellinabox', 'url': url}
diff --git a/ironic/drivers/modules/virtualbox.py b/ironic/drivers/modules/virtualbox.py
deleted file mode 100644
index c3eda6a4c..000000000
--- a/ironic/drivers/modules/virtualbox.py
+++ /dev/null
@@ -1,393 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""
-VirtualBox Driver Modules
-"""
-
-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 _, _LE, _LW
-from ironic.common import states
-from ironic.common import utils
-from ironic.conductor import task_manager
-from ironic.conf import CONF
-from ironic.drivers import base
-
-pyremotevbox = importutils.try_import('pyremotevbox')
-if pyremotevbox:
- from pyremotevbox import exception as virtualbox_exc
- from pyremotevbox import vbox as virtualbox
-
-IRONIC_TO_VIRTUALBOX_DEVICE_MAPPING = {
- boot_devices.PXE: 'Network',
- boot_devices.DISK: 'HardDisk',
- boot_devices.CDROM: 'DVD',
-}
-VIRTUALBOX_TO_IRONIC_DEVICE_MAPPING = {
- v: k for k, v in IRONIC_TO_VIRTUALBOX_DEVICE_MAPPING.items()}
-
-VIRTUALBOX_TO_IRONIC_POWER_MAPPING = {
- 'PoweredOff': states.POWER_OFF,
- 'Running': states.POWER_ON,
- 'Error': states.ERROR
-}
-
-LOG = logging.getLogger(__name__)
-
-REQUIRED_PROPERTIES = {
- 'virtualbox_vmname': _("Name of the VM in VirtualBox. Required."),
- 'virtualbox_host': _("IP address or hostname of the VirtualBox host. "
- "Required.")
-}
-
-OPTIONAL_PROPERTIES = {
- 'virtualbox_username': _("Username for the VirtualBox host. "
- "Default value is ''. Optional."),
- 'virtualbox_password': _("Password for 'virtualbox_username'. "
- "Default value is ''. Optional."),
- 'virtualbox_port': _("Port on which VirtualBox web service is listening. "
- "Optional."),
-}
-
-COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
-COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES)
-
-
-def _strip_virtualbox_from_param_name(param_name):
- if param_name.startswith('virtualbox_'):
- return param_name[11:]
- else:
- return param_name
-
-
-def _parse_driver_info(node):
- """Gets the driver specific node driver info.
-
- This method validates whether the 'driver_info' property of the
- supplied node contains the required information for this driver.
-
- :param node: an Ironic Node object.
- :returns: a dict containing information from driver_info (or where
- applicable, config values).
- :raises: MissingParameterValue, if some required parameter(s) are missing
- in the node's driver_info.
- :raises: InvalidParameterValue, if some parameter(s) have invalid value(s)
- in the node's driver_info.
- """
- info = node.driver_info
- d_info = {}
-
- missing_params = []
- for param in REQUIRED_PROPERTIES:
- try:
- d_info_param_name = _strip_virtualbox_from_param_name(param)
- d_info[d_info_param_name] = info[param]
- except KeyError:
- missing_params.append(param)
-
- if missing_params:
- msg = (_("The following parameters are missing in driver_info: %s") %
- ', '.join(missing_params))
- raise exception.MissingParameterValue(msg)
-
- for param in OPTIONAL_PROPERTIES:
- if param in info:
- d_info_param_name = _strip_virtualbox_from_param_name(param)
- d_info[d_info_param_name] = info[param]
-
- port = d_info.get('port', CONF.virtualbox.port)
- d_info['port'] = utils.validate_network_port(port, 'virtualbox_port')
-
- return d_info
-
-
-def _run_virtualbox_method(node, ironic_method, vm_object_method,
- *call_args, **call_kwargs):
- """Runs a method of pyremotevbox.vbox.VirtualMachine
-
- This runs a method from pyremotevbox.vbox.VirtualMachine.
- The VirtualMachine method to be invoked and the argument(s) to be
- passed to it are to be provided.
-
- :param node: an Ironic Node object.
- :param ironic_method: the Ironic method which called
- '_run_virtualbox_method'. This is used for logging only.
- :param vm_object_method: The method on the VirtualMachine object
- to be called.
- :param call_args: The args to be passed to 'vm_object_method'.
- :param call_kwargs: The kwargs to be passed to the 'vm_object_method'.
- :returns: The value returned by 'vm_object_method'
- :raises: VirtualBoxOperationFailed, if execution of 'vm_object_method'
- failed.
- :raises: InvalidParameterValue,
- - if 'vm_object_method' is not a valid 'VirtualMachine' method.
- - if some parameter(s) have invalid value(s) in the node's driver_info.
- :raises: MissingParameterValue, if some required parameter(s) are missing
- in the node's driver_info.
- :raises: pyremotevbox.exception.VmInWrongPowerState, if operation cannot
- be performed when vm is in the current power state.
- """
- driver_info = _parse_driver_info(node)
- try:
- host = virtualbox.VirtualBoxHost(**driver_info)
- vm_object = host.find_vm(driver_info['vmname'])
- except virtualbox_exc.PyRemoteVBoxException as exc:
- LOG.error(_LE("Failed while creating a VirtualMachine object for "
- "node %(node_id)s. Error: %(error)s."),
- {'node_id': node.uuid, 'error': exc})
- raise exception.VirtualBoxOperationFailed(operation=vm_object_method,
- error=exc)
-
- try:
- func = getattr(vm_object, vm_object_method)
- except AttributeError:
- error_msg = _("Invalid VirtualMachine method '%s' passed "
- "to '_run_virtualbox_method'.")
- raise exception.InvalidParameterValue(error_msg % vm_object_method)
-
- try:
- return func(*call_args, **call_kwargs)
- except virtualbox_exc.PyRemoteVBoxException as exc:
- error_msg = _LE("'%(ironic_method)s' failed for node %(node_id)s with "
- "error: %(error)s.")
- LOG.error(error_msg, {'ironic_method': ironic_method,
- 'node_id': node.uuid,
- 'error': exc})
- raise exception.VirtualBoxOperationFailed(operation=vm_object_method,
- error=exc)
-
-
-class VirtualBoxPower(base.PowerInterface):
- def get_properties(self):
- return COMMON_PROPERTIES
-
- def validate(self, task):
- """Check if node.driver_info contains the required credentials.
-
- :param task: a TaskManager instance.
- :raises: MissingParameterValue, if some required parameter(s) are
- missing in the node's driver_info.
- :raises: InvalidParameterValue, if some parameter(s) have invalid
- value(s) in the node's driver_info.
- """
- _parse_driver_info(task.node)
-
- def _apply_boot_device(self, task):
- """Get the target boot device and apply on the baremetal machine .
-
- :param task: a TaskManager instance.
- """
- driver_internal_info = task.node.driver_internal_info
- device = driver_internal_info.pop('vbox_target_boot_device', None)
- if device is not None:
- task.driver.management.set_boot_device(task, device)
- task.node.driver_internal_info = driver_internal_info
- task.node.save()
-
- def get_power_state(self, task):
- """Gets the current power state.
-
- :param task: a TaskManager instance.
- :returns: one of :mod:`ironic.common.states`
- :raises: MissingParameterValue, if some required parameter(s) are
- missing in the node's driver_info.
- :raises: InvalidParameterValue, if some parameter(s) have invalid
- value(s) in the node's driver_info.
- :raises: VirtualBoxOperationFailed, if error encountered from
- VirtualBox operation.
- """
- power_status = _run_virtualbox_method(task.node, 'get_power_state',
- 'get_power_status')
- try:
- return VIRTUALBOX_TO_IRONIC_POWER_MAPPING[power_status]
- except KeyError:
- msg = _LE("VirtualBox returned unknown state '%(state)s' for "
- "node %(node)s")
- LOG.error(msg, {'state': power_status, 'node': task.node.uuid})
- return states.ERROR
-
- @task_manager.require_exclusive_lock
- def set_power_state(self, task, target_state):
- """Turn the current power state on or off.
-
- :param task: a TaskManager instance.
- :param target_state: The desired power state POWER_ON,POWER_OFF or
- REBOOT from :mod:`ironic.common.states`.
- :raises: MissingParameterValue, if some required parameter(s) are
- missing in the node's driver_info.
- :raises: InvalidParameterValue, if some parameter(s) have invalid
- value(s) in the node's driver_info OR if an invalid power state
- was specified.
- :raises: VirtualBoxOperationFailed, if error encountered from
- VirtualBox operation.
- """
-
- # We set boot device before power on to avoid the case that user
- # shuts down the machine without calling power off method here. For
- # instance, soft power off the machine from OS.
- if target_state == states.POWER_OFF:
- _run_virtualbox_method(task.node, 'set_power_state', 'stop')
- self._apply_boot_device(task)
- elif target_state == states.POWER_ON:
- self._apply_boot_device(task)
- _run_virtualbox_method(task.node, 'set_power_state', 'start')
- elif target_state == states.REBOOT:
- self.reboot(task)
- else:
- msg = _("'set_power_state' called with invalid power "
- "state '%s'") % target_state
- raise exception.InvalidParameterValue(msg)
-
- @task_manager.require_exclusive_lock
- def reboot(self, task):
- """Reboot the node.
-
- :param task: a TaskManager instance.
- :raises: MissingParameterValue, if some required parameter(s) are
- missing in the node's driver_info.
- :raises: InvalidParameterValue, if some parameter(s) have invalid
- value(s) in the node's driver_info.
- :raises: VirtualBoxOperationFailed, if error encountered from
- VirtualBox operation.
- """
- _run_virtualbox_method(task.node, 'reboot', 'stop')
- self._apply_boot_device(task)
- _run_virtualbox_method(task.node, 'reboot', 'start')
-
-
-class VirtualBoxManagement(base.ManagementInterface):
- def get_properties(self):
- return COMMON_PROPERTIES
-
- def validate(self, task):
- """Check that 'driver_info' contains required credentials.
-
- Validates whether the 'driver_info' property of the supplied
- task's node contains the required credentials information.
-
- :param task: a task from TaskManager.
- :raises: MissingParameterValue, if some required parameter(s) are
- missing in the node's driver_info.
- :raises: InvalidParameterValue, if some parameter(s) have invalid
- value(s) in the node's driver_info.
- """
- _parse_driver_info(task.node)
-
- def get_supported_boot_devices(self, task):
- """Get 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 list(IRONIC_TO_VIRTUALBOX_DEVICE_MAPPING.keys())
-
- def _get_boot_device_from_hardware(self, task):
- boot_dev = _run_virtualbox_method(task.node,
- 'get_boot_device', 'get_boot_device')
- ironic_boot_dev = VIRTUALBOX_TO_IRONIC_DEVICE_MAPPING.get(boot_dev)
- persistent = True
- if not ironic_boot_dev:
- persistent = None
- msg = _LW("VirtualBox returned unknown boot "
- "device '%(device)s' for node %(node)s")
- LOG.warning(msg, {'device': boot_dev, 'node': task.node.uuid})
- return (ironic_boot_dev, persistent)
-
- def get_boot_device(self, task):
- """Get the current boot device for a node.
-
- :param task: a task from TaskManager.
- :returns: a dictionary containing:
- 'boot_device': one of the ironic.common.boot_devices or None
- 'persistent': True if boot device is persistent, False otherwise
- :raises: MissingParameterValue, if some required parameter(s) are
- missing in the node's driver_info.
- :raises: InvalidParameterValue, if some parameter(s) have invalid
- value(s) in the node's driver_info.
- :raises: VirtualBoxOperationFailed, if error encountered from
- VirtualBox operation.
- """
- if task.driver.power.get_power_state(task) == states.POWER_OFF:
- ironic_boot_dev, persistent = \
- self._get_boot_device_from_hardware(task)
- else:
- ironic_boot_dev = task.node. \
- driver_internal_info.get('vbox_target_boot_device')
- if ironic_boot_dev is not None:
- msg = _LW("As ironic node %(node)s is"
- " powered on, we will set to boot"
- " from %(device)s before next boot.")
- LOG.warning(msg, {'node': task.node.uuid,
- 'device': ironic_boot_dev})
- persistent = True
- else:
- # Maybe the vbox_target_boot_device is cleaned
- ironic_boot_dev, persistent = \
- self._get_boot_device_from_hardware(task)
- return {'boot_device': ironic_boot_dev, 'persistent': persistent}
-
- @task_manager.require_exclusive_lock
- def set_boot_device(self, task, device, persistent=False):
- """Set the boot device for a node.
-
- :param task: a task from TaskManager.
- :param device: ironic.common.boot_devices
- :param persistent: This argument is ignored as VirtualBox support only
- persistent boot devices.
- :raises: MissingParameterValue, if some required parameter(s) are
- missing in the node's driver_info.
- :raises: InvalidParameterValue, if some parameter(s) have invalid
- value(s) in the node's driver_info.
- :raises: VirtualBoxOperationFailed, if error encountered from
- VirtualBox operation.
- """
- # NOTE(rameshg87): VirtualBox has only persistent boot devices.
- try:
- boot_dev = IRONIC_TO_VIRTUALBOX_DEVICE_MAPPING[device]
- except KeyError:
- raise exception.InvalidParameterValue(
- _("Invalid boot device %s specified.") % device)
-
- if task.driver.power.get_power_state(task) == states.POWER_OFF:
-
- _run_virtualbox_method(task.node, 'set_boot_device',
- 'set_boot_device', boot_dev)
- else:
- LOG.warning(_LW('Node %(node_uuid)s: As VirtualBox do not support '
- 'setting boot device when VM is powered on, we '
- 'will set booting from %(device)s when reboot '
- 'next time.'),
- {'node_uuid': task.node.uuid, 'device': device})
- # We should store target boot device in case the
- # end user shutoff the baremetal machine from NOVA API.
- boot_device_now = self.get_boot_device(task)['boot_device']
- if device != boot_device_now:
- driver_internal_info = task.node.driver_internal_info
- driver_internal_info['vbox_target_boot_device'] = device
- task.node.driver_internal_info = driver_internal_info
- task.node.save()
-
- def get_sensors_data(self, task):
- """Get sensors data.
-
- :param task: a TaskManager instance.
- :raises: FailedToGetSensorData when getting the sensor data fails.
- :raises: FailedToParseSensorData when parsing sensor data fails.
- :returns: returns a consistent format dict of sensor data grouped by
- sensor type, which can be processed by Ceilometer.
- """
- raise NotImplementedError()
diff --git a/ironic/drivers/pxe.py b/ironic/drivers/pxe.py
index 8f890f974..8f93170c0 100644
--- a/ironic/drivers/pxe.py
+++ b/ironic/drivers/pxe.py
@@ -39,15 +39,11 @@ from ironic.drivers.modules.irmc import inspect as irmc_inspect
from ironic.drivers.modules.irmc import management as irmc_management
from ironic.drivers.modules.irmc import power as irmc_power
from ironic.drivers.modules import iscsi_deploy
-from ironic.drivers.modules.msftocs import management as msftocs_management
-from ironic.drivers.modules.msftocs import power as msftocs_power
from ironic.drivers.modules import pxe
-from ironic.drivers.modules import seamicro
from ironic.drivers.modules import snmp
from ironic.drivers.modules import ssh
from ironic.drivers.modules.ucs import management as ucs_mgmt
from ironic.drivers.modules.ucs import power as ucs_power
-from ironic.drivers.modules import virtualbox
# For backward compatibility
@@ -110,32 +106,6 @@ class PXEAndIPMINativeDriver(base.BaseDriver):
self.raid = agent.AgentRAID()
-class PXEAndSeaMicroDriver(base.BaseDriver):
- """PXE + SeaMicro driver.
-
- This driver implements the `core` functionality, combining
- :class:`ironic.drivers.modules.seamicro.Power` for power
- on/off and reboot with
- :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy`
- for image deployment. Implementations are in those respective
- classes; this class is merely the glue between them.
- """
-
- supported = False
-
- def __init__(self):
- if not importutils.try_import('seamicroclient'):
- raise exception.DriverLoadError(
- driver=self.__class__.__name__,
- reason=_("Unable to import seamicroclient library"))
- self.power = seamicro.Power()
- self.boot = pxe.PXEBoot()
- self.deploy = iscsi_deploy.ISCSIDeploy()
- self.management = seamicro.Management()
- self.vendor = seamicro.VendorPassthru()
- self.console = seamicro.ShellinaboxConsole()
-
-
class PXEAndIloDriver(base.BaseDriver):
"""PXE + Ilo Driver using IloClient interface.
@@ -206,52 +176,6 @@ class PXEAndIRMCDriver(base.BaseDriver):
self.inspect = irmc_inspect.IRMCInspect()
-class PXEAndVirtualBoxDriver(base.BaseDriver):
- """PXE + VirtualBox driver.
-
- NOTE: This driver is meant only for testing environments.
-
- This driver implements the `core` functionality, combining
- :class:`ironic.drivers.virtualbox.VirtualBoxPower` for power on/off and
- reboot of VirtualBox virtual machines, with
- :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy` for image
- deployment. Implementations are in those respective classes;
- this class is merely the glue between them.
- """
-
- supported = False
-
- def __init__(self):
- if not importutils.try_import('pyremotevbox'):
- raise exception.DriverLoadError(
- driver=self.__class__.__name__,
- reason=_("Unable to import pyremotevbox library"))
- self.power = virtualbox.VirtualBoxPower()
- self.boot = pxe.PXEBoot()
- self.deploy = iscsi_deploy.ISCSIDeploy()
- self.management = virtualbox.VirtualBoxManagement()
- self.raid = agent.AgentRAID()
-
-
-class PXEAndMSFTOCSDriver(base.BaseDriver):
- """PXE + MSFT OCS driver.
-
- This driver implements the `core` functionality, combining
- :class:`ironic.drivers.modules.msftocs.power.MSFTOCSPower` for power on/off
- and reboot with :class:`ironic.drivers.modules.iscsi_deploy.ISCSIDeploy`
- for image deployment. Implementations are in those respective classes;
- this class is merely the glue between them.
- """
-
- supported = False
-
- def __init__(self):
- self.power = msftocs_power.MSFTOCSPower()
- self.boot = pxe.PXEBoot()
- self.deploy = iscsi_deploy.ISCSIDeploy()
- self.management = msftocs_management.MSFTOCSManagement()
-
-
class PXEAndUcsDriver(base.BaseDriver):
"""PXE + Cisco UCSM driver.
diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py
index 6714f1d02..1d2321c4e 100644
--- a/ironic/tests/unit/conductor/test_manager.py
+++ b/ironic/tests/unit/conductor/test_manager.py
@@ -4776,12 +4776,6 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin,
'deploy_forces_oob_reboot']
self._check_driver_properties("fake_pxe", expected)
- def test_driver_properties_fake_seamicro(self):
- expected = ['seamicro_api_endpoint', 'seamicro_password',
- 'seamicro_server_id', 'seamicro_username',
- 'seamicro_api_version', 'seamicro_terminal_port']
- self._check_driver_properties("fake_seamicro", expected)
-
def test_driver_properties_fake_snmp(self):
expected = ['snmp_driver', 'snmp_address', 'snmp_port', 'snmp_version',
'snmp_community', 'snmp_security', 'snmp_outlet']
@@ -4813,14 +4807,6 @@ class ManagerTestProperties(mgr_utils.ServiceSetUpMixin,
'deploy_forces_oob_reboot']
self._check_driver_properties("pxe_ssh", expected)
- def test_driver_properties_pxe_seamicro(self):
- expected = ['deploy_kernel', 'deploy_ramdisk',
- 'seamicro_api_endpoint', 'seamicro_password',
- 'seamicro_server_id', 'seamicro_username',
- 'seamicro_api_version', 'seamicro_terminal_port',
- 'deploy_forces_oob_reboot']
- self._check_driver_properties("pxe_seamicro", expected)
-
def test_driver_properties_pxe_snmp(self):
expected = ['deploy_kernel', 'deploy_ramdisk',
'snmp_driver', 'snmp_address', 'snmp_port', 'snmp_version',
diff --git a/ironic/tests/unit/db/utils.py b/ironic/tests/unit/db/utils.py
index bddbba6ec..3c85969e9 100644
--- a/ironic/tests/unit/db/utils.py
+++ b/ironic/tests/unit/db/utils.py
@@ -89,15 +89,6 @@ def get_test_pxe_instance_info():
}
-def get_test_seamicro_info():
- return {
- "seamicro_api_endpoint": "http://1.2.3.4",
- "seamicro_username": "admin",
- "seamicro_password": "fake",
- "seamicro_server_id": "0/0",
- }
-
-
def get_test_ilo_info():
return {
"ilo_address": "1.2.3.4",
@@ -127,15 +118,6 @@ def get_test_irmc_info():
}
-def get_test_msftocs_info():
- return {
- "msftocs_base_url": "http://fakehost:8000",
- "msftocs_username": "admin",
- "msftocs_password": "fake",
- "msftocs_blade_id": 1,
- }
-
-
def get_test_agent_instance_info():
return {
'image_source': 'fake-image',
diff --git a/ironic/tests/unit/drivers/modules/msftocs/__init__.py b/ironic/tests/unit/drivers/modules/msftocs/__init__.py
deleted file mode 100644
index e69de29bb..000000000
--- a/ironic/tests/unit/drivers/modules/msftocs/__init__.py
+++ /dev/null
diff --git a/ironic/tests/unit/drivers/modules/msftocs/test_common.py b/ironic/tests/unit/drivers/modules/msftocs/test_common.py
deleted file mode 100644
index 546748944..000000000
--- a/ironic/tests/unit/drivers/modules/msftocs/test_common.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright 2015 Cloudbase Solutions Srl
-# 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.
-
-"""
-Test class for MSFT OCS common functions
-"""
-
-import mock
-
-from ironic.common import exception
-from ironic.conductor import task_manager
-from ironic.drivers.modules.msftocs import common as msftocs_common
-from ironic.tests.unit.conductor import mgr_utils
-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
-
-INFO_DICT = db_utils.get_test_msftocs_info()
-
-
-class MSFTOCSCommonTestCase(db_base.DbTestCase):
- def setUp(self):
- super(MSFTOCSCommonTestCase, self).setUp()
- mgr_utils.mock_the_extension_manager(driver='fake_msftocs')
- self.info = INFO_DICT
- self.node = obj_utils.create_test_node(self.context,
- driver='fake_msftocs',
- driver_info=self.info)
-
- def test_get_client_info(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- driver_info = task.node.driver_info
- (client, blade_id) = msftocs_common.get_client_info(driver_info)
-
- self.assertEqual(driver_info['msftocs_base_url'], client._base_url)
- self.assertEqual(driver_info['msftocs_username'], client._username)
- self.assertEqual(driver_info['msftocs_password'], client._password)
- self.assertEqual(driver_info['msftocs_blade_id'], blade_id)
-
- @mock.patch.object(msftocs_common, '_is_valid_url', autospec=True)
- def test_parse_driver_info(self, mock_is_valid_url):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- msftocs_common.parse_driver_info(task.node)
- mock_is_valid_url.assert_called_once_with(
- task.node.driver_info['msftocs_base_url'])
-
- def test_parse_driver_info_fail_missing_param(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- del task.node.driver_info['msftocs_base_url']
- self.assertRaises(exception.MissingParameterValue,
- msftocs_common.parse_driver_info,
- task.node)
-
- def test_parse_driver_info_fail_bad_url(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- task.node.driver_info['msftocs_base_url'] = "bad-url"
- self.assertRaises(exception.InvalidParameterValue,
- msftocs_common.parse_driver_info,
- task.node)
-
- def test_parse_driver_info_fail_bad_blade_id_type(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- task.node.driver_info['msftocs_blade_id'] = "bad-blade-id"
- self.assertRaises(exception.InvalidParameterValue,
- msftocs_common.parse_driver_info,
- task.node)
-
- def test_parse_driver_info_fail_bad_blade_id_value(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- task.node.driver_info['msftocs_blade_id'] = 0
- self.assertRaises(exception.InvalidParameterValue,
- msftocs_common.parse_driver_info,
- task.node)
-
- def test__is_valid_url(self):
- self.assertIs(True, msftocs_common._is_valid_url("http://fake.com"))
- self.assertIs(
- True, msftocs_common._is_valid_url("http://www.fake.com"))
- self.assertIs(True, msftocs_common._is_valid_url("http://FAKE.com"))
- self.assertIs(True, msftocs_common._is_valid_url("http://fake"))
- self.assertIs(
- True, msftocs_common._is_valid_url("http://fake.com/blah"))
- self.assertIs(True, msftocs_common._is_valid_url("http://localhost"))
- self.assertIs(True, msftocs_common._is_valid_url("https://fake.com"))
- self.assertIs(True, msftocs_common._is_valid_url("http://10.0.0.1"))
- self.assertIs(False, msftocs_common._is_valid_url("bad-url"))
- self.assertIs(False, msftocs_common._is_valid_url("http://.bad-url"))
- self.assertIs(False, msftocs_common._is_valid_url("http://bad-url$"))
- self.assertIs(False, msftocs_common._is_valid_url("http://$bad-url"))
- self.assertIs(False, msftocs_common._is_valid_url("http://bad$url"))
- self.assertIs(False, msftocs_common._is_valid_url(None))
- self.assertIs(False, msftocs_common._is_valid_url(0))
diff --git a/ironic/tests/unit/drivers/modules/msftocs/test_management.py b/ironic/tests/unit/drivers/modules/msftocs/test_management.py
deleted file mode 100644
index aaa54a879..000000000
--- a/ironic/tests/unit/drivers/modules/msftocs/test_management.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# Copyright 2015 Cloudbase Solutions Srl
-# 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.
-
-"""
-Test class for MSFT OCS ManagementInterface
-"""
-
-import mock
-
-from ironic.common import boot_devices
-from ironic.common import exception
-from ironic.conductor import task_manager
-from ironic.drivers.modules.msftocs import common as msftocs_common
-from ironic.drivers.modules.msftocs import msftocsclient
-from ironic.drivers import utils as drivers_utils
-from ironic.tests.unit.conductor import mgr_utils
-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
-
-INFO_DICT = db_utils.get_test_msftocs_info()
-
-
-class MSFTOCSManagementTestCase(db_base.DbTestCase):
- def setUp(self):
- super(MSFTOCSManagementTestCase, self).setUp()
- mgr_utils.mock_the_extension_manager(driver='fake_msftocs')
- self.info = INFO_DICT
- self.node = obj_utils.create_test_node(self.context,
- driver='fake_msftocs',
- driver_info=self.info)
-
- def test_get_properties(self):
- expected = msftocs_common.REQUIRED_PROPERTIES
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- self.assertEqual(expected, task.driver.get_properties())
-
- @mock.patch.object(msftocs_common, 'parse_driver_info', autospec=True)
- def test_validate(self, mock_drvinfo):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- task.driver.power.validate(task)
- mock_drvinfo.assert_called_once_with(task.node)
-
- @mock.patch.object(msftocs_common, 'parse_driver_info', autospec=True)
- def test_validate_fail(self, mock_drvinfo):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- mock_drvinfo.side_effect = exception.InvalidParameterValue('x')
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.power.validate,
- task)
-
- def test_get_supported_boot_devices(self):
- expected = [boot_devices.PXE, boot_devices.DISK, boot_devices.BIOS]
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- self.assertEqual(
- sorted(expected),
- sorted(task.driver.management.
- get_supported_boot_devices(task)))
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def _test_set_boot_device_one_time(self, persistent, uefi,
- mock_gci):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
-
- if uefi:
- drivers_utils.add_node_capability(task, 'boot_mode', 'uefi')
-
- task.driver.management.set_boot_device(
- task, boot_devices.PXE, persistent)
-
- mock_gci.assert_called_once_with(task.node.driver_info)
- mock_c.set_next_boot.assert_called_once_with(
- blade_id, msftocsclient.BOOT_TYPE_FORCE_PXE, persistent, uefi)
-
- def test_set_boot_device_one_time(self):
- self._test_set_boot_device_one_time(False, False)
-
- def test_set_boot_device_persistent(self):
- self._test_set_boot_device_one_time(True, False)
-
- def test_set_boot_device_uefi(self):
- self._test_set_boot_device_one_time(True, True)
-
- def test_set_boot_device_fail(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.management.set_boot_device,
- task, 'fake-device')
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def test_get_boot_device(self, mock_gci):
- expected = {'boot_device': boot_devices.DISK, 'persistent': None}
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
- force_hdd = msftocsclient.BOOT_TYPE_FORCE_DEFAULT_HDD
- mock_c.get_next_boot.return_value = force_hdd
-
- self.assertEqual(expected,
- task.driver.management.get_boot_device(task))
- mock_gci.assert_called_once_with(task.node.driver_info)
- mock_c.get_next_boot.assert_called_once_with(blade_id)
-
- def test_get_sensor_data(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- self.assertRaises(NotImplementedError,
- task.driver.management.get_sensors_data,
- task)
diff --git a/ironic/tests/unit/drivers/modules/msftocs/test_msftocsclient.py b/ironic/tests/unit/drivers/modules/msftocs/test_msftocsclient.py
deleted file mode 100644
index 66097d05e..000000000
--- a/ironic/tests/unit/drivers/modules/msftocs/test_msftocsclient.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# Copyright 2015 Cloudbase Solutions Srl
-# 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.
-
-"""
-Test class for MSFT OCS REST API client
-"""
-
-import mock
-import requests
-from requests import exceptions as requests_exceptions
-
-from ironic.common import exception
-from ironic.drivers.modules.msftocs import msftocsclient
-from ironic.tests import base
-
-
-FAKE_BOOT_RESPONSE = (
- '<BootResponse xmlns="%s" '
- 'xmlns:i="http://www.w3.org/2001/XMLSchema-instance">'
- '<completionCode>Success</completionCode>'
- '<apiVersion>1</apiVersion>'
- '<statusDescription>Success</statusDescription>'
- '<bladeNumber>1</bladeNumber>'
- '<nextBoot>ForcePxe</nextBoot>'
- '</BootResponse>') % msftocsclient.WCSNS
-
-FAKE_BLADE_RESPONSE = (
- '<BladeResponse xmlns="%s" '
- 'xmlns:i="http://www.w3.org/2001/XMLSchema-instance">'
- '<completionCode>Success</completionCode>'
- '<apiVersion>1</apiVersion>'
- '<statusDescription/>'
- '<bladeNumber>1</bladeNumber>'
- '</BladeResponse>') % msftocsclient.WCSNS
-
-FAKE_POWER_STATE_RESPONSE = (
- '<PowerStateResponse xmlns="%s" '
- 'xmlns:i="http://www.w3.org/2001/XMLSchema-instance">'
- '<completionCode>Success</completionCode>'
- '<apiVersion>1</apiVersion>'
- '<statusDescription>Blade Power is On, firmware decompressed'
- '</statusDescription>'
- '<bladeNumber>1</bladeNumber>'
- '<Decompression>0</Decompression>'
- '<powerState>ON</powerState>'
- '</PowerStateResponse>') % msftocsclient.WCSNS
-
-FAKE_BLADE_STATE_RESPONSE = (
- '<BladeStateResponse xmlns="%s" '
- 'xmlns:i="http://www.w3.org/2001/XMLSchema-instance">'
- '<completionCode>Success</completionCode>'
- '<apiVersion>1</apiVersion>'
- '<statusDescription/>'
- '<bladeNumber>1</bladeNumber>'
- '<bladeState>ON</bladeState>'
- '</BladeStateResponse>') % msftocsclient.WCSNS
-
-
-class MSFTOCSClientApiTestCase(base.TestCase):
- def setUp(self):
- super(MSFTOCSClientApiTestCase, self).setUp()
- self._fake_base_url = "http://fakehost:8000"
- self._fake_username = "admin"
- self._fake_password = 'fake'
- self._fake_blade_id = 1
- self._client = msftocsclient.MSFTOCSClientApi(
- self._fake_base_url, self._fake_username, self._fake_password)
-
- @mock.patch.object(requests, 'get', autospec=True)
- def test__exec_cmd(self, mock_get):
- fake_response_text = 'fake_response_text'
- fake_rel_url = 'fake_rel_url'
- mock_get.return_value.text = 'fake_response_text'
-
- self.assertEqual(fake_response_text,
- self._client._exec_cmd(fake_rel_url))
- mock_get.assert_called_once_with(
- self._fake_base_url + "/" + fake_rel_url, auth=mock.ANY)
-
- @mock.patch.object(requests, 'get', autospec=True)
- def test__exec_cmd_http_get_fail(self, mock_get):
- fake_rel_url = 'fake_rel_url'
- mock_get.side_effect = requests_exceptions.ConnectionError('x')
-
- self.assertRaises(exception.MSFTOCSClientApiException,
- self._client._exec_cmd,
- fake_rel_url)
- mock_get.assert_called_once_with(
- self._fake_base_url + "/" + fake_rel_url, auth=mock.ANY)
-
- def test__check_completion_code(self):
- et = self._client._check_completion_code(FAKE_BOOT_RESPONSE)
- self.assertEqual('{%s}BootResponse' % msftocsclient.WCSNS, et.tag)
-
- def test__check_completion_code_fail(self):
- self.assertRaises(exception.MSFTOCSClientApiException,
- self._client._check_completion_code,
- '<fake xmlns="%s"></fake>' % msftocsclient.WCSNS)
-
- def test__check_completion_with_bad_completion_code_fail(self):
- self.assertRaises(exception.MSFTOCSClientApiException,
- self._client._check_completion_code,
- '<fake xmlns="%s">'
- '<completionCode>Fail</completionCode>'
- '</fake>' % msftocsclient.WCSNS)
-
- def test__check_completion_code_xml_parsing_fail(self):
- self.assertRaises(exception.MSFTOCSClientApiException,
- self._client._check_completion_code,
- 'bad_xml')
-
- @mock.patch.object(
- msftocsclient.MSFTOCSClientApi, '_exec_cmd', autospec=True)
- def test_get_blade_state(self, mock_exec_cmd):
- mock_exec_cmd.return_value = FAKE_BLADE_STATE_RESPONSE
- self.assertEqual(
- msftocsclient.POWER_STATUS_ON,
- self._client.get_blade_state(self._fake_blade_id))
- mock_exec_cmd.assert_called_once_with(
- self._client, "GetBladeState?bladeId=%d" % self._fake_blade_id)
-
- @mock.patch.object(
- msftocsclient.MSFTOCSClientApi, '_exec_cmd', autospec=True)
- def test_set_blade_on(self, mock_exec_cmd):
- mock_exec_cmd.return_value = FAKE_BLADE_RESPONSE
- self._client.set_blade_on(self._fake_blade_id)
- mock_exec_cmd.assert_called_once_with(
- self._client, "SetBladeOn?bladeId=%d" % self._fake_blade_id)
-
- @mock.patch.object(
- msftocsclient.MSFTOCSClientApi, '_exec_cmd', autospec=True)
- def test_set_blade_off(self, mock_exec_cmd):
- mock_exec_cmd.return_value = FAKE_BLADE_RESPONSE
- self._client.set_blade_off(self._fake_blade_id)
- mock_exec_cmd.assert_called_once_with(
- self._client, "SetBladeOff?bladeId=%d" % self._fake_blade_id)
-
- @mock.patch.object(
- msftocsclient.MSFTOCSClientApi, '_exec_cmd', autospec=True)
- def test_set_blade_power_cycle(self, mock_exec_cmd):
- mock_exec_cmd.return_value = FAKE_BLADE_RESPONSE
- self._client.set_blade_power_cycle(self._fake_blade_id)
- mock_exec_cmd.assert_called_once_with(
- self._client,
- "SetBladeActivePowerCycle?bladeId=%d&offTime=0" %
- self._fake_blade_id)
-
- @mock.patch.object(
- msftocsclient.MSFTOCSClientApi, '_exec_cmd', autospec=True)
- def test_get_next_boot(self, mock_exec_cmd):
- mock_exec_cmd.return_value = FAKE_BOOT_RESPONSE
- self.assertEqual(
- msftocsclient.BOOT_TYPE_FORCE_PXE,
- self._client.get_next_boot(self._fake_blade_id))
- mock_exec_cmd.assert_called_once_with(
- self._client, "GetNextBoot?bladeId=%d" % self._fake_blade_id)
-
- @mock.patch.object(
- msftocsclient.MSFTOCSClientApi, '_exec_cmd', autospec=True)
- def test_set_next_boot(self, mock_exec_cmd):
- mock_exec_cmd.return_value = FAKE_BOOT_RESPONSE
- self._client.set_next_boot(self._fake_blade_id,
- msftocsclient.BOOT_TYPE_FORCE_PXE)
- mock_exec_cmd.assert_called_once_with(
- self._client,
- "SetNextBoot?bladeId=%(blade_id)d&bootType=%(boot_type)d&"
- "uefi=%(uefi)s&persistent=%(persistent)s" %
- {"blade_id": self._fake_blade_id,
- "boot_type": msftocsclient.BOOT_TYPE_FORCE_PXE,
- "uefi": "true", "persistent": "true"})
diff --git a/ironic/tests/unit/drivers/modules/msftocs/test_power.py b/ironic/tests/unit/drivers/modules/msftocs/test_power.py
deleted file mode 100644
index 38f07a4b9..000000000
--- a/ironic/tests/unit/drivers/modules/msftocs/test_power.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# Copyright 2015 Cloudbase Solutions Srl
-# 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.
-
-"""
-Test class for MSFT OCS PowerInterface
-"""
-
-import mock
-
-from ironic.common import exception
-from ironic.common import states
-from ironic.conductor import task_manager
-from ironic.drivers.modules.msftocs import common as msftocs_common
-from ironic.drivers.modules.msftocs import msftocsclient
-from ironic.tests.unit.conductor import mgr_utils
-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
-
-INFO_DICT = db_utils.get_test_msftocs_info()
-
-
-class MSFTOCSPowerTestCase(db_base.DbTestCase):
- def setUp(self):
- super(MSFTOCSPowerTestCase, self).setUp()
- mgr_utils.mock_the_extension_manager(driver='fake_msftocs')
- self.info = INFO_DICT
- self.node = obj_utils.create_test_node(self.context,
- driver='fake_msftocs',
- driver_info=self.info)
-
- def test_get_properties(self):
- expected = msftocs_common.REQUIRED_PROPERTIES
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- self.assertEqual(expected, task.driver.get_properties())
-
- @mock.patch.object(msftocs_common, 'parse_driver_info', autospec=True)
- def test_validate(self, mock_drvinfo):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- task.driver.power.validate(task)
- mock_drvinfo.assert_called_once_with(task.node)
-
- @mock.patch.object(msftocs_common, 'parse_driver_info', autospec=True)
- def test_validate_fail(self, mock_drvinfo):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- mock_drvinfo.side_effect = exception.InvalidParameterValue('x')
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.power.validate,
- task)
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def test_get_power_state(self, mock_gci):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
- mock_c.get_blade_state.return_value = msftocsclient.POWER_STATUS_ON
-
- self.assertEqual(states.POWER_ON,
- task.driver.power.get_power_state(task))
- mock_gci.assert_called_once_with(task.node.driver_info)
- mock_c.get_blade_state.assert_called_once_with(blade_id)
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def test_set_power_state_on(self, mock_gci):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
-
- task.driver.power.set_power_state(task, states.POWER_ON)
- mock_gci.assert_called_once_with(task.node.driver_info)
- mock_c.set_blade_on.assert_called_once_with(blade_id)
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def test_set_power_state_off(self, mock_gci):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
-
- task.driver.power.set_power_state(task, states.POWER_OFF)
- mock_gci.assert_called_once_with(task.node.driver_info)
- mock_c.set_blade_off.assert_called_once_with(blade_id)
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def test_set_power_state_blade_on_fail(self, mock_gci):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
-
- ex = exception.MSFTOCSClientApiException('x')
- mock_c.set_blade_on.side_effect = ex
-
- pstate = states.POWER_ON
- self.assertRaises(exception.PowerStateFailure,
- task.driver.power.set_power_state,
- task, pstate)
- mock_gci.assert_called_once_with(task.node.driver_info)
- mock_c.set_blade_on.assert_called_once_with(blade_id)
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def test_set_power_state_invalid_parameter_fail(self, mock_gci):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
-
- pstate = states.ERROR
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.power.set_power_state,
- task, pstate)
- mock_gci.assert_called_once_with(task.node.driver_info)
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def test_reboot(self, mock_gci):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
-
- task.driver.power.reboot(task)
- mock_gci.assert_called_once_with(task.node.driver_info)
- mock_c.set_blade_power_cycle.assert_called_once_with(blade_id)
-
- @mock.patch.object(msftocs_common, 'get_client_info', autospec=True)
- def test_reboot_fail(self, mock_gci):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- mock_c = mock.MagicMock(spec=msftocsclient.MSFTOCSClientApi)
- blade_id = task.node.driver_info['msftocs_blade_id']
- mock_gci.return_value = (mock_c, blade_id)
-
- ex = exception.MSFTOCSClientApiException('x')
- mock_c.set_blade_power_cycle.side_effect = ex
-
- self.assertRaises(exception.PowerStateFailure,
- task.driver.power.reboot,
- task)
- mock_gci.assert_called_once_with(task.node.driver_info)
- mock_c.set_blade_power_cycle.assert_called_once_with(blade_id)
diff --git a/ironic/tests/unit/drivers/modules/test_seamicro.py b/ironic/tests/unit/drivers/modules/test_seamicro.py
deleted file mode 100644
index c6651aca1..000000000
--- a/ironic/tests/unit/drivers/modules/test_seamicro.py
+++ /dev/null
@@ -1,689 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Test class for Ironic SeaMicro driver."""
-
-
-import mock
-from oslo_utils import uuidutils
-from seamicroclient import client as seamicro_client
-from seamicroclient import exceptions as seamicro_client_exception
-from six.moves import http_client
-
-from ironic.common import boot_devices
-from ironic.common import driver_factory
-from ironic.common import exception
-from ironic.common import states
-from ironic.conductor import task_manager
-from ironic.drivers.modules import console_utils
-from ironic.drivers.modules import seamicro
-from ironic.tests.unit.conductor import mgr_utils
-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
-
-INFO_DICT = db_utils.get_test_seamicro_info()
-
-
-class Fake_Server(object):
- def __init__(self, active=False, *args, **kwargs):
- self.active = active
- self.nic = {'0': {'untaggedVlan': ''}}
-
- def power_on(self):
- self.active = True
-
- def power_off(self, force=False):
- self.active = False
-
- def reset(self):
- self.active = True
-
- def set_untagged_vlan(self, vlan_id):
- return
-
- def attach_volume(self, volume_id):
- return
-
- def detach_volume(self):
- return
-
- def set_boot_order(self, boot_order):
- return
-
- def refresh(self, wait=0):
- return self
-
-
-class Fake_Volume(object):
- def __init__(self, id=None, *args, **kwargs):
- if id is None:
- self.id = "%s/%s/%s" % ("0", "ironic-p6-6",
- uuidutils.generate_uuid())
- else:
- self.id = id
-
-
-class Fake_Pool(object):
- def __init__(self, freeSize=None, *args, **kwargs):
- self.freeSize = freeSize
-
-
-class SeaMicroValidateParametersTestCase(db_base.DbTestCase):
-
- def test__parse_driver_info_good(self):
- # make sure we get back the expected things
- node = obj_utils.get_test_node(
- self.context,
- driver='fake_seamicro',
- driver_info=INFO_DICT)
- info = seamicro._parse_driver_info(node)
- self.assertEqual('http://1.2.3.4', info['api_endpoint'])
- self.assertEqual('admin', info['username'])
- self.assertEqual('fake', info['password'])
- self.assertEqual('0/0', info['server_id'])
- self.assertEqual('1be26c0b-03f2-4d2e-ae87-c02d7f33c123',
- info['uuid'])
-
- def test__parse_driver_info_missing_api_endpoint(self):
- # make sure error is raised when info is missing
- info = dict(INFO_DICT)
- del info['seamicro_api_endpoint']
- node = obj_utils.get_test_node(self.context, driver_info=info)
- self.assertRaises(exception.MissingParameterValue,
- seamicro._parse_driver_info,
- node)
-
- def test__parse_driver_info_missing_username(self):
- # make sure error is raised when info is missing
- info = dict(INFO_DICT)
- del info['seamicro_username']
- node = obj_utils.get_test_node(self.context, driver_info=info)
- self.assertRaises(exception.MissingParameterValue,
- seamicro._parse_driver_info,
- node)
-
- def test__parse_driver_info_missing_password(self):
- # make sure error is raised when info is missing
- info = dict(INFO_DICT)
- del info['seamicro_password']
- node = obj_utils.get_test_node(self.context, driver_info=info)
- self.assertRaises(exception.MissingParameterValue,
- seamicro._parse_driver_info,
- node)
-
- def test__parse_driver_info_missing_server_id(self):
- # make sure error is raised when info is missing
- info = dict(INFO_DICT)
- del info['seamicro_server_id']
- node = obj_utils.get_test_node(self.context, driver_info=info)
- self.assertRaises(exception.MissingParameterValue,
- seamicro._parse_driver_info,
- node)
-
- def test__parse_driver_info_empty_terminal_port(self):
- info = dict(INFO_DICT)
- info['seamicro_terminal_port'] = ''
- node = obj_utils.get_test_node(self.context, driver_info=info)
- self.assertRaises(exception.InvalidParameterValue,
- seamicro._parse_driver_info,
- node)
-
-
-@mock.patch('eventlet.greenthread.sleep', lambda n: None)
-class SeaMicroPrivateMethodsTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(SeaMicroPrivateMethodsTestCase, self).setUp()
- n = {
- 'driver': 'fake_seamicro',
- 'driver_info': INFO_DICT
- }
- self.node = obj_utils.create_test_node(self.context, **n)
- self.Server = Fake_Server
- self.Volume = Fake_Volume
- self.Pool = Fake_Pool
- self.config(action_timeout=0, group='seamicro')
- self.config(max_retry=2, group='seamicro')
-
- self.info = seamicro._parse_driver_info(self.node)
-
- @mock.patch.object(seamicro_client, "Client", autospec=True)
- def test__get_client(self, mock_client):
- args = {'username': self.info['username'],
- 'password': self.info['password'],
- 'auth_url': self.info['api_endpoint']}
- seamicro._get_client(**self.info)
- mock_client.assert_called_once_with(self.info['api_version'], **args)
-
- @mock.patch.object(seamicro_client, "Client", autospec=True)
- def test__get_client_fail(self, mock_client):
- args = {'username': self.info['username'],
- 'password': self.info['password'],
- 'auth_url': self.info['api_endpoint']}
- mock_client.side_effect = seamicro_client_exception.UnsupportedVersion
- self.assertRaises(exception.InvalidParameterValue,
- seamicro._get_client,
- **self.info)
- mock_client.assert_called_once_with(self.info['api_version'], **args)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__get_power_status_on(self, mock_get_server):
- mock_get_server.return_value = self.Server(active=True)
- pstate = seamicro._get_power_status(self.node)
- self.assertEqual(states.POWER_ON, pstate)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__get_power_status_off(self, mock_get_server):
- mock_get_server.return_value = self.Server(active=False)
- pstate = seamicro._get_power_status(self.node)
- self.assertEqual(states.POWER_OFF, pstate)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__get_power_status_error(self, mock_get_server):
- mock_get_server.return_value = self.Server(active=None)
- pstate = seamicro._get_power_status(self.node)
- self.assertEqual(states.ERROR, pstate)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__power_on_good(self, mock_get_server):
- mock_get_server.return_value = self.Server(active=False)
- pstate = seamicro._power_on(self.node)
- self.assertEqual(states.POWER_ON, pstate)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__power_on_fail(self, mock_get_server):
- def fake_power_on():
- return
-
- server = self.Server(active=False)
- server.power_on = fake_power_on
- mock_get_server.return_value = server
- pstate = seamicro._power_on(self.node)
- self.assertEqual(states.ERROR, pstate)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__power_off_good(self, mock_get_server):
- mock_get_server.return_value = self.Server(active=True)
- pstate = seamicro._power_off(self.node)
- self.assertEqual(states.POWER_OFF, pstate)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__power_off_fail(self, mock_get_server):
- def fake_power_off():
- return
- server = self.Server(active=True)
- server.power_off = fake_power_off
- mock_get_server.return_value = server
- pstate = seamicro._power_off(self.node)
- self.assertEqual(states.ERROR, pstate)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__reboot_good(self, mock_get_server):
- mock_get_server.return_value = self.Server(active=True)
- pstate = seamicro._reboot(self.node)
- self.assertEqual(states.POWER_ON, pstate)
-
- @mock.patch.object(seamicro, "_get_server", autospec=True)
- def test__reboot_fail(self, mock_get_server):
- def fake_reboot():
- return
- server = self.Server(active=False)
- server.reset = fake_reboot
- mock_get_server.return_value = server
- pstate = seamicro._reboot(self.node)
- self.assertEqual(states.ERROR, pstate)
-
- @mock.patch.object(seamicro, "_get_volume", autospec=True)
- def test__validate_fail(self, mock_get_volume):
- volume_id = "0/p6-6/vol1"
- volume = self.Volume()
- volume.id = volume_id
- mock_get_volume.return_value = volume
- self.assertRaises(exception.InvalidParameterValue,
- seamicro._validate_volume, self.info, volume_id)
-
- @mock.patch.object(seamicro, "_get_volume", autospec=True)
- def test__validate_good(self, mock_get_volume):
- volume = self.Volume()
- mock_get_volume.return_value = volume
- valid = seamicro._validate_volume(self.info, volume.id)
- self.assertTrue(valid)
-
- @mock.patch.object(seamicro, "_get_pools", autospec=True)
- def test__create_volume_fail(self, mock_get_pools):
- mock_get_pools.return_value = None
- self.assertRaises(exception.IronicException,
- seamicro._create_volume,
- self.info, 2)
-
- @mock.patch.object(seamicro, "_get_pools", autospec=True)
- @mock.patch.object(seamicro, "_get_client", autospec=True)
- def test__create_volume_good(self, mock_get_client, mock_get_pools):
- pools = [self.Pool(1), self.Pool(6), self.Pool(5)]
- mock_seamicro_volumes = mock.MagicMock(spec_set=['create'])
- mock_get_client.return_value = mock.MagicMock(
- volumes=mock_seamicro_volumes, spec_set=['volumes'])
- mock_get_pools.return_value = pools
- seamicro._create_volume(self.info, 2)
-
-
-class SeaMicroPowerDriverTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(SeaMicroPowerDriverTestCase, self).setUp()
- mgr_utils.mock_the_extension_manager(driver='fake_seamicro')
- self.driver = driver_factory.get_driver('fake_seamicro')
- self.node = obj_utils.create_test_node(self.context,
- driver='fake_seamicro',
- driver_info=INFO_DICT)
- self.get_server_patcher = mock.patch.object(seamicro, '_get_server',
- autospec=True)
-
- self.get_server_mock = None
- self.Server = Fake_Server
- self.Volume = Fake_Volume
- self.info = seamicro._parse_driver_info(self.node)
-
- def test_get_properties(self):
- expected = seamicro.COMMON_PROPERTIES
- with task_manager.acquire(self.context, self.node['uuid'],
- shared=True) as task:
- self.assertEqual(expected, task.driver.power.get_properties())
-
- expected = (list(seamicro.COMMON_PROPERTIES) +
- list(seamicro.CONSOLE_PROPERTIES))
- console_properties = task.driver.console.get_properties().keys()
- self.assertEqual(sorted(expected), sorted(console_properties))
- self.assertEqual(sorted(expected),
- sorted(task.driver.get_properties().keys()))
-
- def test_vendor_routes(self):
- expected = ['set_node_vlan_id', 'attach_volume']
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- vendor_routes = task.driver.vendor.vendor_routes
- self.assertIsInstance(vendor_routes, dict)
- self.assertEqual(sorted(expected), sorted(vendor_routes))
-
- def test_driver_routes(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=True) as task:
- driver_routes = task.driver.vendor.driver_routes
- self.assertIsInstance(driver_routes, dict)
- self.assertEqual({}, driver_routes)
-
- @mock.patch.object(seamicro, '_parse_driver_info', autospec=True)
- def test_power_interface_validate_good(self, parse_drv_info_mock):
- with task_manager.acquire(self.context, self.node['uuid'],
- shared=True) as task:
- task.driver.power.validate(task)
- self.assertEqual(1, parse_drv_info_mock.call_count)
-
- @mock.patch.object(seamicro, '_parse_driver_info', autospec=True)
- def test_power_interface_validate_fails(self, parse_drv_info_mock):
- side_effect = exception.InvalidParameterValue("Bad input")
- parse_drv_info_mock.side_effect = side_effect
- with task_manager.acquire(self.context, self.node['uuid'],
- shared=True) as task:
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.power.validate, task)
- self.assertEqual(1, parse_drv_info_mock.call_count)
-
- @mock.patch.object(seamicro, '_reboot', autospec=True)
- def test_reboot(self, mock_reboot):
- mock_reboot.return_value = states.POWER_ON
-
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- task.driver.power.reboot(task)
-
- mock_reboot.assert_called_once_with(task.node)
-
- def test_set_power_state_bad_state(self):
- self.get_server_mock = self.get_server_patcher.start()
- self.get_server_mock.return_value = self.Server()
-
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- self.assertRaises(exception.IronicException,
- task.driver.power.set_power_state,
- task, "BAD_PSTATE")
- self.get_server_patcher.stop()
-
- @mock.patch.object(seamicro, '_power_on', autospec=True)
- def test_set_power_state_on_good(self, mock_power_on):
- mock_power_on.return_value = states.POWER_ON
-
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- task.driver.power.set_power_state(task, states.POWER_ON)
-
- mock_power_on.assert_called_once_with(task.node)
-
- @mock.patch.object(seamicro, '_power_on', autospec=True)
- def test_set_power_state_on_fail(self, mock_power_on):
- mock_power_on.return_value = states.POWER_OFF
-
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- self.assertRaises(exception.PowerStateFailure,
- task.driver.power.set_power_state,
- task, states.POWER_ON)
-
- mock_power_on.assert_called_once_with(task.node)
-
- @mock.patch.object(seamicro, '_power_off', autospec=True)
- def test_set_power_state_off_good(self, mock_power_off):
- mock_power_off.return_value = states.POWER_OFF
-
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- task.driver.power.set_power_state(task, states.POWER_OFF)
-
- mock_power_off.assert_called_once_with(task.node)
-
- @mock.patch.object(seamicro, '_power_off', autospec=True)
- def test_set_power_state_off_fail(self, mock_power_off):
- mock_power_off.return_value = states.POWER_ON
-
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- self.assertRaises(exception.PowerStateFailure,
- task.driver.power.set_power_state,
- task, states.POWER_OFF)
-
- mock_power_off.assert_called_once_with(task.node)
-
- @mock.patch.object(seamicro, '_parse_driver_info', autospec=True)
- def test_vendor_passthru_validate_good(self, mock_info):
- with task_manager.acquire(self.context, self.node['uuid'],
- shared=True) as task:
- for method in task.driver.vendor.vendor_routes:
- task.driver.vendor.validate(task, **{'method': method})
- self.assertEqual(len(task.driver.vendor.vendor_routes),
- mock_info.call_count)
-
- @mock.patch.object(seamicro, '_parse_driver_info', autospec=True)
- def test_vendor_passthru_validate_parse_driver_info_fail(self, mock_info):
- mock_info.side_effect = exception.InvalidParameterValue("bad")
- with task_manager.acquire(self.context, self.node['uuid'],
- shared=True) as task:
- method = list(task.driver.vendor.vendor_routes)[0]
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.vendor.validate,
- task, **{'method': method})
- mock_info.assert_called_once_with(task.node)
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- def test_set_node_vlan_id_good(self, mock_get_server):
- vlan_id = "12"
- mock_get_server.return_value = self.Server(active="true")
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- kwargs = {'vlan_id': vlan_id}
- task.driver.vendor.set_node_vlan_id(task, **kwargs)
- mock_get_server.assert_called_once_with(self.info)
-
- def test_set_node_vlan_id_no_input(self):
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.vendor.set_node_vlan_id,
- task, **{})
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- def test_set_node_vlan_id_fail(self, mock_get_server):
- def fake_set_untagged_vlan(self, **kwargs):
- raise seamicro_client_exception.ClientException(
- http_client.INTERNAL_SERVER_ERROR)
-
- vlan_id = "12"
- server = self.Server(active="true")
- server.set_untagged_vlan = fake_set_untagged_vlan
- mock_get_server.return_value = server
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- kwargs = {'vlan_id': vlan_id}
- self.assertRaises(exception.IronicException,
- task.driver.vendor.set_node_vlan_id,
- task, **kwargs)
-
- mock_get_server.assert_called_once_with(self.info)
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- @mock.patch.object(seamicro, '_validate_volume', autospec=True)
- def test_attach_volume_with_volume_id_good(self, mock_validate_volume,
- mock_get_server):
- volume_id = '0/ironic-p6-1/vol1'
- mock_validate_volume.return_value = True
- mock_get_server.return_value = self.Server(active="true")
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- kwargs = {'volume_id': volume_id}
- task.driver.vendor.attach_volume(task, **kwargs)
- mock_get_server.assert_called_once_with(self.info)
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- @mock.patch.object(seamicro, '_get_volume', autospec=True)
- def test_attach_volume_with_invalid_volume_id_fail(self,
- mock_get_volume,
- mock_get_server):
- volume_id = '0/p6-1/vol1'
- mock_get_volume.return_value = self.Volume(volume_id)
- mock_get_server.return_value = self.Server(active="true")
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- kwargs = {'volume_id': volume_id}
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.vendor.attach_volume,
- task, **kwargs)
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- @mock.patch.object(seamicro, '_validate_volume', autospec=True)
- def test_attach_volume_fail(self, mock_validate_volume,
- mock_get_server):
- def fake_attach_volume(self, **kwargs):
- raise seamicro_client_exception.ClientException(
- http_client.INTERNAL_SERVER_ERROR)
-
- volume_id = '0/p6-1/vol1'
- mock_validate_volume.return_value = True
- server = self.Server(active="true")
- server.attach_volume = fake_attach_volume
- mock_get_server.return_value = server
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- kwargs = {'volume_id': volume_id}
- self.assertRaises(exception.IronicException,
- task.driver.vendor.attach_volume,
- task, **kwargs)
-
- mock_get_server.assert_called_once_with(self.info)
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- @mock.patch.object(seamicro, '_validate_volume', autospec=True)
- @mock.patch.object(seamicro, '_create_volume', autospec=True)
- def test_attach_volume_with_volume_size_good(self, mock_create_volume,
- mock_validate_volume,
- mock_get_server):
- volume_id = '0/ironic-p6-1/vol1'
- volume_size = 2
- mock_create_volume.return_value = volume_id
- mock_validate_volume.return_value = True
- mock_get_server.return_value = self.Server(active="true")
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- kwargs = {'volume_size': volume_size}
- task.driver.vendor.attach_volume(task, **kwargs)
- mock_get_server.assert_called_once_with(self.info)
- mock_create_volume.assert_called_once_with(self.info, volume_size)
-
- def test_attach_volume_with_no_input_fail(self):
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.vendor.attach_volume, task,
- **{})
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- def test_set_boot_device_good(self, mock_get_server):
- boot_device = "disk"
- mock_get_server.return_value = self.Server(active="true")
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- task.driver.management.set_boot_device(task, boot_device)
- mock_get_server.assert_called_once_with(self.info)
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- def test_set_boot_device_invalid_device_fail(self, mock_get_server):
- boot_device = "invalid_device"
- mock_get_server.return_value = self.Server(active="true")
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.management.set_boot_device,
- task, boot_device)
-
- @mock.patch.object(seamicro, '_get_server', autospec=True)
- def test_set_boot_device_fail(self, mock_get_server):
- def fake_set_boot_order(self, **kwargs):
- raise seamicro_client_exception.ClientException(
- http_client.INTERNAL_SERVER_ERROR)
-
- boot_device = "pxe"
- server = self.Server(active="true")
- server.set_boot_order = fake_set_boot_order
- mock_get_server.return_value = server
- with task_manager.acquire(self.context, self.info['uuid'],
- shared=False) as task:
- self.assertRaises(exception.IronicException,
- task.driver.management.set_boot_device,
- task, boot_device)
-
- mock_get_server.assert_called_once_with(self.info)
-
- def test_management_interface_get_supported_boot_devices(self):
- with task_manager.acquire(self.context, self.node.uuid) as task:
- expected = [boot_devices.PXE, boot_devices.DISK]
- self.assertEqual(sorted(expected), sorted(task.driver.management.
- get_supported_boot_devices(task)))
-
- def test_management_interface_get_boot_device(self):
- with task_manager.acquire(self.context, self.node.uuid) as task:
- expected = {'boot_device': None, 'persistent': None}
- self.assertEqual(expected,
- task.driver.management.get_boot_device(task))
-
- def test_management_interface_validate_good(self):
- with task_manager.acquire(self.context, self.node.uuid) as task:
- task.driver.management.validate(task)
-
- def test_management_interface_validate_fail(self):
- # Missing SEAMICRO driver_info information
- node = obj_utils.create_test_node(self.context,
- uuid=uuidutils.generate_uuid(),
- driver='fake_seamicro')
- with task_manager.acquire(self.context, node.uuid) as task:
- self.assertRaises(exception.MissingParameterValue,
- task.driver.management.validate, task)
-
-
-class SeaMicroDriverTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(SeaMicroDriverTestCase, self).setUp()
- mgr_utils.mock_the_extension_manager(driver='fake_seamicro')
- self.driver = driver_factory.get_driver('fake_seamicro')
- self.node = obj_utils.create_test_node(self.context,
- driver='fake_seamicro',
- driver_info=INFO_DICT)
- self.get_server_patcher = mock.patch.object(seamicro, '_get_server',
- autospec=True)
-
- self.get_server_mock = None
- self.Server = Fake_Server
- self.Volume = Fake_Volume
- self.info = seamicro._parse_driver_info(self.node)
-
- @mock.patch.object(console_utils, 'start_shellinabox_console',
- autospec=True)
- def test_start_console(self, mock_exec):
- mock_exec.return_value = None
- with task_manager.acquire(self.context,
- self.node.uuid) as task:
- self.driver.console.start_console(task)
-
- mock_exec.assert_called_once_with(self.info['uuid'],
- self.info['port'],
- mock.ANY)
-
- @mock.patch.object(console_utils, 'start_shellinabox_console',
- autospec=True)
- def test_start_console_fail(self, mock_exec):
- mock_exec.side_effect = exception.ConsoleSubprocessFailed(
- error='error')
-
- with task_manager.acquire(self.context,
- self.node.uuid) as task:
- self.assertRaises(exception.ConsoleSubprocessFailed,
- self.driver.console.start_console,
- task)
-
- @mock.patch.object(console_utils, 'stop_shellinabox_console',
- autospec=True)
- def test_stop_console(self, mock_exec):
- mock_exec.return_value = None
- with task_manager.acquire(self.context,
- self.node.uuid) as task:
- self.driver.console.stop_console(task)
-
- mock_exec.assert_called_once_with(self.info['uuid'])
-
- @mock.patch.object(console_utils, 'stop_shellinabox_console',
- autospec=True)
- def test_stop_console_fail(self, mock_stop):
- mock_stop.side_effect = exception.ConsoleError()
-
- with task_manager.acquire(self.context,
- self.node.uuid) as task:
- self.assertRaises(exception.ConsoleError,
- self.driver.console.stop_console,
- task)
-
- mock_stop.assert_called_once_with(self.node.uuid)
-
- @mock.patch.object(console_utils, 'start_shellinabox_console',
- autospec=True)
- def test_start_console_fail_nodir(self, mock_exec):
- mock_exec.side_effect = exception.ConsoleError()
-
- with task_manager.acquire(self.context,
- self.node.uuid) as task:
- self.assertRaises(exception.ConsoleError,
- self.driver.console.start_console,
- task)
- mock_exec.assert_called_once_with(self.node.uuid, mock.ANY, mock.ANY)
-
- @mock.patch.object(console_utils, 'get_shellinabox_console_url',
- autospec=True)
- def test_get_console(self, mock_exec):
- url = 'http://localhost:4201'
- mock_exec.return_value = url
- expected = {'type': 'shellinabox', 'url': url}
-
- with task_manager.acquire(self.context,
- self.node.uuid) as task:
- console_info = self.driver.console.get_console(task)
-
- self.assertEqual(expected, console_info)
- mock_exec.assert_called_once_with(self.info['port'])
diff --git a/ironic/tests/unit/drivers/modules/test_virtualbox.py b/ironic/tests/unit/drivers/modules/test_virtualbox.py
deleted file mode 100644
index 2e2d54adf..000000000
--- a/ironic/tests/unit/drivers/modules/test_virtualbox.py
+++ /dev/null
@@ -1,420 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""Test class for VirtualBox Driver Modules."""
-
-import mock
-from pyremotevbox import exception as pyremotevbox_exc
-from pyremotevbox import vbox as pyremotevbox_vbox
-
-from ironic.common import boot_devices
-from ironic.common import exception
-from ironic.common import states
-from ironic.conductor import task_manager
-from ironic.drivers.modules import virtualbox
-from ironic.tests.unit.conductor import mgr_utils
-from ironic.tests.unit.db import base as db_base
-from ironic.tests.unit.objects import utils as obj_utils
-
-INFO_DICT = {
- 'virtualbox_vmname': 'baremetal1',
- 'virtualbox_host': '10.0.2.2',
- 'virtualbox_username': 'username',
- 'virtualbox_password': 'password',
- 'virtualbox_port': 12345,
-}
-
-
-class VirtualBoxMethodsTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(VirtualBoxMethodsTestCase, self).setUp()
- driver_info = INFO_DICT.copy()
- mgr_utils.mock_the_extension_manager(driver="fake_vbox")
- self.node = obj_utils.create_test_node(self.context,
- driver='fake_vbox',
- driver_info=driver_info)
-
- def test__parse_driver_info(self):
- info = virtualbox._parse_driver_info(self.node)
- self.assertEqual('baremetal1', info['vmname'])
- self.assertEqual('10.0.2.2', info['host'])
- self.assertEqual('username', info['username'])
- self.assertEqual('password', info['password'])
- self.assertEqual(12345, info['port'])
-
- def test__parse_driver_info_missing_vmname(self):
- del self.node.driver_info['virtualbox_vmname']
- self.assertRaises(exception.MissingParameterValue,
- virtualbox._parse_driver_info, self.node)
-
- def test__parse_driver_info_missing_host(self):
- del self.node.driver_info['virtualbox_host']
- self.assertRaises(exception.MissingParameterValue,
- virtualbox._parse_driver_info, self.node)
-
- def test__parse_driver_info_invalid_port(self):
- self.node.driver_info['virtualbox_port'] = 'invalid-port'
- self.assertRaises(exception.InvalidParameterValue,
- virtualbox._parse_driver_info, self.node)
-
- def test__parse_driver_info_missing_port(self):
- del self.node.driver_info['virtualbox_port']
- info = virtualbox._parse_driver_info(self.node)
- self.assertEqual(18083, info['port'])
-
- @mock.patch.object(pyremotevbox_vbox, 'VirtualBoxHost', autospec=True)
- def test__run_virtualbox_method(self, host_mock):
- host_object_mock = mock.MagicMock(spec_set=['find_vm'])
- func_mock = mock.MagicMock(spec_set=[])
- vm_object_mock = mock.MagicMock(spec_set=['foo'], foo=func_mock)
- host_mock.return_value = host_object_mock
- host_object_mock.find_vm.return_value = vm_object_mock
- func_mock.return_value = 'return-value'
-
- return_value = virtualbox._run_virtualbox_method(
- self.node, 'some-ironic-method', 'foo', 'args', kwarg='kwarg')
-
- host_mock.assert_called_once_with(vmname='baremetal1',
- host='10.0.2.2',
- username='username',
- password='password',
- port=12345)
- host_object_mock.find_vm.assert_called_once_with('baremetal1')
- func_mock.assert_called_once_with('args', kwarg='kwarg')
- self.assertEqual('return-value', return_value)
-
- @mock.patch.object(pyremotevbox_vbox, 'VirtualBoxHost', autospec=True)
- def test__run_virtualbox_method_get_host_fails(self, host_mock):
- host_mock.side_effect = pyremotevbox_exc.PyRemoteVBoxException
-
- self.assertRaises(exception.VirtualBoxOperationFailed,
- virtualbox._run_virtualbox_method,
- self.node, 'some-ironic-method', 'foo',
- 'args', kwarg='kwarg')
-
- @mock.patch.object(pyremotevbox_vbox, 'VirtualBoxHost', autospec=True)
- def test__run_virtualbox_method_find_vm_fails(self, host_mock):
- host_object_mock = mock.MagicMock(spec_set=['find_vm'])
- host_mock.return_value = host_object_mock
- exc = pyremotevbox_exc.PyRemoteVBoxException
- host_object_mock.find_vm.side_effect = exc
-
- self.assertRaises(exception.VirtualBoxOperationFailed,
- virtualbox._run_virtualbox_method,
- self.node, 'some-ironic-method', 'foo', 'args',
- kwarg='kwarg')
- host_mock.assert_called_once_with(vmname='baremetal1',
- host='10.0.2.2',
- username='username',
- password='password',
- port=12345)
- host_object_mock.find_vm.assert_called_once_with('baremetal1')
-
- @mock.patch.object(pyremotevbox_vbox, 'VirtualBoxHost', autospec=True)
- def test__run_virtualbox_method_func_fails(self, host_mock):
- host_object_mock = mock.MagicMock(spec_set=['find_vm'])
- host_mock.return_value = host_object_mock
- func_mock = mock.MagicMock()
- vm_object_mock = mock.MagicMock(spec_set=['foo'], foo=func_mock)
- host_object_mock.find_vm.return_value = vm_object_mock
- func_mock.side_effect = pyremotevbox_exc.PyRemoteVBoxException
-
- self.assertRaises(exception.VirtualBoxOperationFailed,
- virtualbox._run_virtualbox_method,
- self.node, 'some-ironic-method', 'foo',
- 'args', kwarg='kwarg')
- host_mock.assert_called_once_with(vmname='baremetal1',
- host='10.0.2.2',
- username='username',
- password='password',
- port=12345)
- host_object_mock.find_vm.assert_called_once_with('baremetal1')
- func_mock.assert_called_once_with('args', kwarg='kwarg')
-
- @mock.patch.object(pyremotevbox_vbox, 'VirtualBoxHost', autospec=True)
- def test__run_virtualbox_method_invalid_method(self, host_mock):
- host_object_mock = mock.MagicMock(spec_set=['find_vm'])
- host_mock.return_value = host_object_mock
- vm_object_mock = mock.MagicMock(spec_set=[])
- host_object_mock.find_vm.return_value = vm_object_mock
- del vm_object_mock.foo
-
- self.assertRaises(exception.InvalidParameterValue,
- virtualbox._run_virtualbox_method,
- self.node, 'some-ironic-method', 'foo',
- 'args', kwarg='kwarg')
- host_mock.assert_called_once_with(vmname='baremetal1',
- host='10.0.2.2',
- username='username',
- password='password',
- port=12345)
- host_object_mock.find_vm.assert_called_once_with('baremetal1')
-
- @mock.patch.object(pyremotevbox_vbox, 'VirtualBoxHost', autospec=True)
- def test__run_virtualbox_method_vm_wrong_power_state(self, host_mock):
- host_object_mock = mock.MagicMock(spec_set=['find_vm'])
- host_mock.return_value = host_object_mock
- func_mock = mock.MagicMock(spec_set=[])
- vm_object_mock = mock.MagicMock(spec_set=['foo'], foo=func_mock)
- host_object_mock.find_vm.return_value = vm_object_mock
- func_mock.side_effect = pyremotevbox_exc.VmInWrongPowerState
-
- # _run_virtualbox_method() doesn't catch VmInWrongPowerState and
- # lets caller handle it.
- self.assertRaises(pyremotevbox_exc.VmInWrongPowerState,
- virtualbox._run_virtualbox_method,
- self.node, 'some-ironic-method', 'foo',
- 'args', kwarg='kwarg')
- host_mock.assert_called_once_with(vmname='baremetal1',
- host='10.0.2.2',
- username='username',
- password='password',
- port=12345)
- host_object_mock.find_vm.assert_called_once_with('baremetal1')
- func_mock.assert_called_once_with('args', kwarg='kwarg')
-
-
-class VirtualBoxPowerTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(VirtualBoxPowerTestCase, self).setUp()
- driver_info = INFO_DICT.copy()
- mgr_utils.mock_the_extension_manager(driver="fake_vbox")
- self.node = obj_utils.create_test_node(self.context,
- driver='fake_vbox',
- driver_info=driver_info)
-
- def test_get_properties(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- properties = task.driver.power.get_properties()
-
- self.assertIn('virtualbox_vmname', properties)
- self.assertIn('virtualbox_host', properties)
-
- @mock.patch.object(virtualbox, '_parse_driver_info', autospec=True)
- def test_validate(self, parse_info_mock):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.driver.power.validate(task)
- parse_info_mock.assert_called_once_with(task.node)
-
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_get_power_state(self, run_method_mock):
- run_method_mock.return_value = 'PoweredOff'
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- power_state = task.driver.power.get_power_state(task)
- run_method_mock.assert_called_once_with(task.node,
- 'get_power_state',
- 'get_power_status')
- self.assertEqual(states.POWER_OFF, power_state)
-
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_get_power_state_invalid_state(self, run_method_mock):
- run_method_mock.return_value = 'invalid-state'
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- power_state = task.driver.power.get_power_state(task)
- run_method_mock.assert_called_once_with(task.node,
- 'get_power_state',
- 'get_power_status')
- self.assertEqual(states.ERROR, power_state)
-
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_set_power_state_off(self, run_method_mock):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.driver.power.set_power_state(task, states.POWER_OFF)
- run_method_mock.assert_called_once_with(task.node,
- 'set_power_state',
- 'stop')
-
- @mock.patch.object(virtualbox.VirtualBoxManagement, 'set_boot_device')
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_set_power_state_on(self, run_method_mock, set_boot_device_mock):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.driver_internal_info['vbox_target_boot_device'] = 'pxe'
- task.driver.power.set_power_state(task, states.POWER_ON)
- run_method_mock.assert_called_once_with(task.node,
- 'set_power_state',
- 'start')
- set_boot_device_mock.assert_called_once_with(task, 'pxe')
-
- @mock.patch.object(virtualbox.VirtualBoxManagement, 'set_boot_device')
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_set_power_state_reboot(self, run_method_mock,
- mock_set_boot_device):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.driver_internal_info['vbox_target_boot_device'] = 'pxe'
- task.driver.power.set_power_state(task, states.REBOOT)
- run_method_mock.assert_any_call(task.node,
- 'reboot',
- 'stop')
- mock_set_boot_device.assert_called_once_with(task, 'pxe')
- run_method_mock.assert_any_call(task.node,
- 'reboot',
- 'start')
-
- def test_set_power_state_invalid_state(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.power.set_power_state,
- task, 'invalid-state')
-
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_reboot(self, run_method_mock):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.driver.power.reboot(task)
- run_method_mock.assert_any_call(task.node,
- 'reboot',
- 'stop')
- run_method_mock.assert_any_call(task.node,
- 'reboot',
- 'start')
-
-
-class VirtualBoxManagementTestCase(db_base.DbTestCase):
-
- def setUp(self):
- super(VirtualBoxManagementTestCase, self).setUp()
- driver_info = INFO_DICT.copy()
- mgr_utils.mock_the_extension_manager(driver="fake_vbox")
- self.node = obj_utils.create_test_node(self.context,
- driver='fake_vbox',
- driver_info=driver_info)
-
- def test_get_properties(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- properties = task.driver.management.get_properties()
-
- self.assertIn('virtualbox_vmname', properties)
- self.assertIn('virtualbox_host', properties)
-
- @mock.patch.object(virtualbox, '_parse_driver_info', autospec=True)
- def test_validate(self, parse_info_mock):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.driver.management.validate(task)
- parse_info_mock.assert_called_once_with(task.node)
-
- def test_get_supported_boot_devices(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- devices = task.driver.management.get_supported_boot_devices(task)
- self.assertIn(boot_devices.PXE, devices)
- self.assertIn(boot_devices.DISK, devices)
- self.assertIn(boot_devices.CDROM, devices)
-
- @mock.patch.object(virtualbox.VirtualBoxPower,
- 'get_power_state', autospec=True)
- @mock.patch.object(virtualbox, '_run_virtualbox_method',
- autospec=True)
- def test_get_boot_device_VM_Poweroff_ok(self, run_method_mock,
- get_power_state_mock):
- run_method_mock.return_value = 'Network'
- get_power_state_mock.return_value = states.POWER_OFF
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- ret_val = task.driver.management.get_boot_device(task)
- run_method_mock.assert_called_once_with(task.node,
- 'get_boot_device',
- 'get_boot_device')
- self.assertEqual(boot_devices.PXE, ret_val['boot_device'])
- self.assertTrue(ret_val['persistent'])
-
- @mock.patch.object(virtualbox.VirtualBoxPower,
- 'get_power_state', autospec=True)
- def test_get_boot_device_VM_Poweron_ok(self, get_power_state_mock):
- get_power_state_mock.return_value = states.POWER_ON
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.driver_internal_info['vbox_target_boot_device'] = 'pxe'
- ret_val = task.driver.management.get_boot_device(task)
- self.assertEqual(boot_devices.PXE, ret_val['boot_device'])
- self.assertTrue(ret_val['persistent'])
-
- @mock.patch.object(virtualbox.VirtualBoxPower,
- 'get_power_state', autospec=True)
- @mock.patch.object(virtualbox, '_run_virtualbox_method',
- autospec=True)
- def test_get_boot_device_target_device_none_ok(self,
- run_method_mock,
- get_power_state_mock):
- run_method_mock.return_value = 'Network'
- get_power_state_mock.return_value = states.POWER_ON
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.node.driver_internal_info['vbox_target_boot_device'] = None
- ret_val = task.driver.management.get_boot_device(task)
- run_method_mock.assert_called_once_with(task.node,
- 'get_boot_device',
- 'get_boot_device')
- self.assertEqual(boot_devices.PXE, ret_val['boot_device'])
- self.assertTrue(ret_val['persistent'])
-
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_get_boot_device_invalid(self, run_method_mock):
- run_method_mock.return_value = 'invalid-boot-device'
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- ret_val = task.driver.management.get_boot_device(task)
- self.assertIsNone(ret_val['boot_device'])
- self.assertIsNone(ret_val['persistent'])
-
- @mock.patch.object(virtualbox.VirtualBoxPower,
- 'get_power_state', autospec=True)
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_set_boot_device_VM_Poweroff_ok(self, run_method_mock,
- get_power_state_mock):
- get_power_state_mock.return_value = states.POWER_OFF
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.driver.management.set_boot_device(task, boot_devices.PXE)
- run_method_mock.assert_called_with(task.node,
- 'set_boot_device',
- 'set_boot_device',
- 'Network')
-
- @mock.patch.object(virtualbox.VirtualBoxPower,
- 'get_power_state', autospec=True)
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_set_boot_device_VM_Poweron_ok(self, run_method_mock,
- get_power_state_mock):
- get_power_state_mock.return_value = states.POWER_ON
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- task.driver.management.set_boot_device(task, boot_devices.PXE)
- self.assertEqual('pxe',
- task.node.driver_internal_info
- ['vbox_target_boot_device'])
-
- @mock.patch.object(virtualbox, '_run_virtualbox_method', autospec=True)
- def test_set_boot_device_invalid(self, run_method_mock):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- self.assertRaises(exception.InvalidParameterValue,
- task.driver.management.set_boot_device,
- task, 'invalid-boot-device')
-
- def test_get_sensors_data(self):
- with task_manager.acquire(self.context, self.node.uuid,
- shared=False) as task:
- self.assertRaises(NotImplementedError,
- task.driver.management.get_sensors_data,
- task)
diff --git a/ironic/tests/unit/drivers/test_pxe.py b/ironic/tests/unit/drivers/test_pxe.py
index c6799c961..4464a440f 100644
--- a/ironic/tests/unit/drivers/test_pxe.py
+++ b/ironic/tests/unit/drivers/test_pxe.py
@@ -33,15 +33,11 @@ from ironic.drivers.modules import ipmitool
from ironic.drivers.modules.irmc import management as irmc_management
from ironic.drivers.modules.irmc import power as irmc_power
from ironic.drivers.modules import iscsi_deploy
-from ironic.drivers.modules.msftocs import management as msftocs_management
-from ironic.drivers.modules.msftocs import power as msftocs_power
from ironic.drivers.modules import pxe as pxe_module
-from ironic.drivers.modules import seamicro
from ironic.drivers.modules import snmp
from ironic.drivers.modules import ssh
from ironic.drivers.modules.ucs import management as ucs_management
from ironic.drivers.modules.ucs import power as ucs_power
-from ironic.drivers.modules import virtualbox
from ironic.drivers import pxe
@@ -85,28 +81,6 @@ class PXEDriversTestCase(testtools.TestCase):
@mock.patch.object(pxe.importutils, 'try_import', spec_set=True,
autospec=True)
- def test_pxe_seamicro_driver(self, try_import_mock):
- try_import_mock.return_value = True
-
- driver = pxe.PXEAndSeaMicroDriver()
-
- self.assertIsInstance(driver.power, seamicro.Power)
- self.assertIsInstance(driver.boot, pxe_module.PXEBoot)
- self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy)
- self.assertIsInstance(driver.management, seamicro.Management)
- self.assertIsInstance(driver.vendor, seamicro.VendorPassthru)
- self.assertIsInstance(driver.console, seamicro.ShellinaboxConsole)
-
- @mock.patch.object(pxe.importutils, 'try_import', spec_set=True,
- autospec=True)
- def test_pxe_seamicro_driver_import_error(self, try_import_mock):
- try_import_mock.return_value = False
-
- self.assertRaises(exception.DriverLoadError,
- pxe.PXEAndSeaMicroDriver)
-
- @mock.patch.object(pxe.importutils, 'try_import', spec_set=True,
- autospec=True)
def test_pxe_ilo_driver(self, try_import_mock):
try_import_mock.return_value = True
@@ -175,41 +149,6 @@ class PXEDriversTestCase(testtools.TestCase):
@mock.patch.object(pxe.importutils, 'try_import', spec_set=True,
autospec=True)
- def test_pxe_vbox_driver(self, try_import_mock):
- try_import_mock.return_value = True
-
- driver = pxe.PXEAndVirtualBoxDriver()
-
- self.assertIsInstance(driver.power, virtualbox.VirtualBoxPower)
- self.assertIsInstance(driver.boot, pxe_module.PXEBoot)
- self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy)
- self.assertIsInstance(driver.management,
- virtualbox.VirtualBoxManagement)
- self.assertIsInstance(driver.raid, agent.AgentRAID)
-
- @mock.patch.object(pxe.importutils, 'try_import', spec_set=True,
- autospec=True)
- def test_pxe_vbox_driver_import_error(self, try_import_mock):
- try_import_mock.return_value = False
-
- self.assertRaises(exception.DriverLoadError,
- pxe.PXEAndVirtualBoxDriver)
-
- @mock.patch.object(pxe.importutils, 'try_import', spec_set=True,
- autospec=True)
- def test_pxe_msftocs_driver(self, try_import_mock):
- try_import_mock.return_value = True
-
- driver = pxe.PXEAndMSFTOCSDriver()
-
- self.assertIsInstance(driver.power, msftocs_power.MSFTOCSPower)
- self.assertIsInstance(driver.boot, pxe_module.PXEBoot)
- self.assertIsInstance(driver.deploy, iscsi_deploy.ISCSIDeploy)
- self.assertIsInstance(driver.management,
- msftocs_management.MSFTOCSManagement)
-
- @mock.patch.object(pxe.importutils, 'try_import', spec_set=True,
- autospec=True)
def test_pxe_ucs_driver(self, try_import_mock):
try_import_mock.return_value = True
diff --git a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
index f82edba08..1fea41475 100644
--- a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
+++ b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
@@ -73,19 +73,6 @@ PYGHMI_IPMICMD_SPEC = (
'Command',
)
-# pyremotevbox
-PYREMOTEVBOX_SPEC = (
- 'exception',
- 'vbox',
-)
-PYREMOTEVBOX_EXC_SPEC = (
- 'PyRemoteVBoxException',
- 'VmInWrongPowerState',
-)
-PYREMOTEVBOX_VBOX_SPEC = (
- 'VirtualBoxHost',
-)
-
# pywsman
PYWSMAN_SPEC = (
'Client',
@@ -150,17 +137,3 @@ ONEVIEWCLIENT_STATES_SPEC = (
'ONEVIEW_RESETTING',
'ONEVIEW_ERROR',
)
-
-# seamicro
-SEAMICRO_SPEC = (
- 'client',
- 'exceptions',
-)
-# seamicro.client module
-SEAMICRO_CLIENT_MOD_SPEC = (
- 'Client',
-)
-SEAMICRO_EXC_SPEC = (
- 'ClientException',
- 'UnsupportedVersion',
-)
diff --git a/ironic/tests/unit/drivers/third_party_driver_mocks.py b/ironic/tests/unit/drivers/third_party_driver_mocks.py
index 22aa8e76c..5c1a373e6 100644
--- a/ironic/tests/unit/drivers/third_party_driver_mocks.py
+++ b/ironic/tests/unit/drivers/third_party_driver_mocks.py
@@ -22,7 +22,6 @@ respective external libraries' actually being present.
Any external library required by a third-party driver should be mocked here.
Current list of mocked libraries:
-- seamicroclient
- ipminative
- proliantutils
- pysnmp
@@ -43,24 +42,6 @@ from ironic.tests.unit.drivers import third_party_driver_mock_specs \
as mock_specs
-# attempt to load the external 'seamicroclient' library, which is
-# required by the optional drivers.modules.seamicro module
-seamicroclient = importutils.try_import("seamicroclient")
-if not seamicroclient:
- smc = mock.MagicMock(spec_set=mock_specs.SEAMICRO_SPEC)
- smc.client = mock.MagicMock(spec_set=mock_specs.SEAMICRO_CLIENT_MOD_SPEC)
- smc.exceptions = mock.MagicMock(spec_set=mock_specs.SEAMICRO_EXC_SPEC)
- smc.exceptions.ClientException = Exception
- smc.exceptions.UnsupportedVersion = Exception
- sys.modules['seamicroclient'] = smc
- sys.modules['seamicroclient.client'] = smc.client
- sys.modules['seamicroclient.exceptions'] = smc.exceptions
-
-# if anything has loaded the seamicro driver yet, reload it now that
-# the external library has been mocked
-if 'ironic.drivers.modules.seamicro' in sys.modules:
- six.moves.reload_module(sys.modules['ironic.drivers.modules.seamicro'])
-
# IPMITool driver checks the system for presence of 'ipmitool' binary during
# __init__. We bypass that check in order to run the unit tests, which do not
# depend on 'ipmitool' being on the system.
@@ -217,21 +198,6 @@ irmc_boot.check_share_fs_mounted_patcher = mock.patch(
irmc_boot.check_share_fs_mounted_patcher.return_value = None
-pyremotevbox = importutils.try_import('pyremotevbox')
-if not pyremotevbox:
- pyremotevbox = mock.MagicMock(spec_set=mock_specs.PYREMOTEVBOX_SPEC)
- pyremotevbox.exception = mock.MagicMock(
- spec_set=mock_specs.PYREMOTEVBOX_EXC_SPEC)
- pyremotevbox.exception.PyRemoteVBoxException = Exception
- pyremotevbox.exception.VmInWrongPowerState = Exception
- pyremotevbox.vbox = mock.MagicMock(
- spec_set=mock_specs.PYREMOTEVBOX_VBOX_SPEC)
- sys.modules['pyremotevbox'] = pyremotevbox
- if 'ironic.drivers.modules.virtualbox' in sys.modules:
- six.moves.reload_module(
- sys.modules['ironic.drivers.modules.virtualbox'])
-
-
ironic_inspector_client = importutils.try_import('ironic_inspector_client')
if not ironic_inspector_client:
ironic_inspector_client = mock.MagicMock(
diff --git a/releasenotes/notes/remove-most-unsupported-049f3401c2554a3c.yaml b/releasenotes/notes/remove-most-unsupported-049f3401c2554a3c.yaml
new file mode 100644
index 000000000..744d42298
--- /dev/null
+++ b/releasenotes/notes/remove-most-unsupported-049f3401c2554a3c.yaml
@@ -0,0 +1,32 @@
+---
+upgrade:
+ - |
+ A number of drivers that were declared as unsupported in Newton release
+ have been removed from ironic tree. This includes drivers with
+ power and/or management driver interfaces based on:
+
+ - MSFT OCS
+ - SeaMicro client
+ - Virtualbox over pyremotevbox client
+
+ As a result, the following ironic drivers will no longer be available:
+
+ - agent_vbox
+ - fake_msftocs
+ - fake_seamicro
+ - fake_vbox
+ - pxe_msftocs
+ - pxe_seamicro
+ - pxe_vbox
+
+ After upgrading, if one or more of these drivers are in the
+ 'enabled_drivers' configuration option,
+ the ironic-conductor service will fail to start.
+ Any existing ironic nodes with these drivers assigned will become
+ inoperational via ironic after ironic upgrade,
+ as it will be not possible to change any node state/properties
+ except changing the node driver.
+ Operators having one of the drivers listed above enabled are required to
+ either disable those drivers and assign another existing driver
+ to affected nodes as appropriate,
+ or install these drivers from elsewhere separately.
diff --git a/setup.cfg b/setup.cfg
index b872b2bf7..eba73c353 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -49,7 +49,6 @@ ironic.drivers =
agent_pxe_oneview = ironic.drivers.oneview:AgentPXEOneViewDriver
agent_pyghmi = ironic.drivers.agent:AgentAndIPMINativeDriver
agent_ssh = ironic.drivers.agent:AgentAndSSHDriver
- agent_vbox = ironic.drivers.agent:AgentAndVirtualBoxDriver
agent_ucs = ironic.drivers.agent:AgentAndUcsDriver
fake = ironic.drivers.fake:FakeDriver
fake_soft_power = ironic.drivers.fake:FakeSoftPowerDriver
@@ -60,13 +59,10 @@ ironic.drivers =
fake_ipminative = ironic.drivers.fake:FakeIPMINativeDriver
fake_ssh = ironic.drivers.fake:FakeSSHDriver
fake_pxe = ironic.drivers.fake:FakePXEDriver
- fake_seamicro = ironic.drivers.fake:FakeSeaMicroDriver
fake_ilo = ironic.drivers.fake:FakeIloDriver
fake_drac = ironic.drivers.fake:FakeDracDriver
fake_snmp = ironic.drivers.fake:FakeSNMPDriver
fake_irmc = ironic.drivers.fake:FakeIRMCDriver
- fake_vbox = ironic.drivers.fake:FakeVirtualBoxDriver
- fake_msftocs = ironic.drivers.fake:FakeMSFTOCSDriver
fake_ucs = ironic.drivers.fake:FakeUcsDriver
fake_cimc = ironic.drivers.fake:FakeCIMCDriver
fake_oneview = ironic.drivers.fake:FakeOneViewDriver
@@ -77,14 +73,11 @@ ironic.drivers =
pxe_ipmitool_socat = ironic.drivers.ipmi:PXEAndIPMIToolAndSocatDriver
pxe_ipminative = ironic.drivers.pxe:PXEAndIPMINativeDriver
pxe_ssh = ironic.drivers.pxe:PXEAndSSHDriver
- pxe_vbox = ironic.drivers.pxe:PXEAndVirtualBoxDriver
- pxe_seamicro = ironic.drivers.pxe:PXEAndSeaMicroDriver
pxe_ilo = ironic.drivers.pxe:PXEAndIloDriver
pxe_drac = ironic.drivers.drac:PXEDracDriver
pxe_drac_inspector = ironic.drivers.drac:PXEDracInspectorDriver
pxe_snmp = ironic.drivers.pxe:PXEAndSNMPDriver
pxe_irmc = ironic.drivers.pxe:PXEAndIRMCDriver
- pxe_msftocs = ironic.drivers.pxe:PXEAndMSFTOCSDriver
pxe_ucs = ironic.drivers.pxe:PXEAndUcsDriver
pxe_iscsi_cimc = ironic.drivers.pxe:PXEAndCIMCDriver
pxe_agent_cimc = ironic.drivers.agent:AgentAndCIMCDriver