Ensures that OneView nodes are free for use by Ironic

Following the requirement. The validation is used within
"OneViewPower.validate". As a result it enforces that a machine
is owned by OneView, thus it cannot be powered on or off by the
Ironic driver. Raising an exception when the node is owned by
Oneview.

Change-Id: Ibf500577b7a3b5976fd49fd217c1be3d3e9c0f46
Closes-Bug: 1627034
Co-Authored-By: Stenio Araujo <steniaraujo@lsd.ufcg.edu.br>
This commit is contained in:
Charlle Daniel 2016-11-21 17:46:23 -03:00
parent 3871a015f6
commit 2505cb58f7
4 changed files with 51 additions and 7 deletions

View File

@ -52,18 +52,28 @@ class OneViewPower(base.PowerInterface):
enclosure_group_uri. Also, checks if the server profile of the node is
applied, if NICs are valid for the server profile of the node, and if
the server hardware attributes (ram, memory, vcpus count) are
consistent with OneView.
consistent with OneView. It validates if the node is being used by
Oneview.
:param task: a task from TaskManager.
:raises: MissingParameterValue if a required parameter is missing.
:raises: InvalidParameterValue if parameters set are inconsistent with
resources in OneView
:raises: InvalidParameterValue if the node in use by OneView.
:raises: OneViewError if not possible to get OneView's information
for the given node, if not possible to retrieve Server
Hardware from OneView.
"""
common.verify_node_info(task.node)
try:
common.validate_oneview_resources_compatibility(
self.oneview_client, task)
if deploy_utils.is_node_in_use_by_oneview(self.oneview_client,
task.node):
raise exception.InvalidParameterValue(
_("Node %s is in use by OneView.") % task.node.uuid)
except exception.OneViewError as oneview_exc:
raise exception.InvalidParameterValue(oneview_exc)
@ -72,7 +82,6 @@ class OneViewPower(base.PowerInterface):
"""Gets the current power state.
:param task: a TaskManager instance.
:param node: The Node.
:returns: one of :mod:`ironic.common.states` POWER_OFF,
POWER_ON or ERROR.
:raises: OneViewError if fails to retrieve power state of OneView
@ -99,7 +108,6 @@ class OneViewPower(base.PowerInterface):
"""Turn the current power state on or off.
:param task: a TaskManager instance.
:param node: The Node.
:param power_state: The desired power state POWER_ON, POWER_OFF or
REBOOT from :mod:`ironic.common.states`.
:raises: InvalidParameterValue if an invalid power state was specified.
@ -135,7 +143,6 @@ class OneViewPower(base.PowerInterface):
"""Reboot the node
:param task: a TaskManager instance.
:param node: The Node.
:raises: PowerStateFailure if the final state of the node is not
POWER_ON.
"""

View File

@ -255,7 +255,7 @@ class OneViewDeployUtilsTestCase(db_base.DbTestCase):
task.node)
)
# Tests for is_node_in_use_by_oneview
# Tests for is_node_in_use_by_ironic
def test_is_node_in_use_by_ironic(self, mock_get_ov_client):
"""Node has a Server Profile applied by ironic.

View File

@ -24,12 +24,12 @@ from ironic.common import exception
from ironic.common import states
from ironic.conductor import task_manager
from ironic.drivers.modules.oneview import common
from ironic.drivers.modules.oneview import deploy_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
oneview_exceptions = importutils.try_import('oneview_client.exceptions')
POWER_ON = 'On'
@ -58,7 +58,11 @@ class OneViewPowerDriverTestCase(db_base.DbTestCase):
@mock.patch.object(common, 'validate_oneview_resources_compatibility',
spect_set=True, autospec=True)
def test_power_interface_validate(self, mock_validate, mock_get_ov_client):
@mock.patch.object(deploy_utils, 'is_node_in_use_by_oneview',
spect_set=True, autospec=True)
def test_power_interface_validate(self, mock_is_node_in_use_by_oneview,
mock_validate, mock_get_ov_client):
mock_is_node_in_use_by_oneview.return_value = False
with task_manager.acquire(self.context, self.node.uuid) as task:
task.driver.power.validate(task)
self.assertTrue(mock_validate.called)
@ -82,6 +86,35 @@ class OneViewPowerDriverTestCase(db_base.DbTestCase):
task.driver.power.validate,
task)
@mock.patch.object(common, 'validate_oneview_resources_compatibility',
spect_set=True, autospec=True)
@mock.patch.object(deploy_utils, 'is_node_in_use_by_oneview',
spect_set=True, autospec=True)
def test_power_validate_fail_node_used_by_oneview(
self, mock_is_node_in_use_by_oneview, mock_validate,
mock_get_ov_client):
mock_validate.return_value = True
mock_is_node_in_use_by_oneview.return_value = True
with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.InvalidParameterValue,
task.driver.power.validate,
task)
@mock.patch.object(common, 'validate_oneview_resources_compatibility',
spect_set=True, autospec=True)
@mock.patch.object(deploy_utils, 'is_node_in_use_by_oneview',
spect_set=True, autospec=True)
def test_validate_fail_node_in_use_by_oneview(
self, mock_is_node_in_use_by_oneview, mock_validate,
mock_get_ov_client):
mock_validate.return_value = True
mock_is_node_in_use_by_oneview.side_effect = (
exception.OneViewError('message'))
with task_manager.acquire(self.context, self.node.uuid) as task:
self.assertRaises(exception.InvalidParameterValue,
task.driver.power.validate,
task)
def test_power_interface_get_properties(self, mock_get_ov_client):
expected = common.COMMON_PROPERTIES
self.assertItemsEqual(expected, self.driver.power.get_properties())

View File

@ -0,0 +1,4 @@
---
fixes:
- Fixes an issue with ironic being able to change
the power state of nodes currently in use by OneView.