From 9d3a72f7dd9b2dbb0e4aeafc43adee419aabd242 Mon Sep 17 00:00:00 2001 From: Shobhi Jain Date: Tue, 10 Apr 2018 15:17:35 +0100 Subject: Replace cinder detach volume with shade client. Function detach volume now uses shade client. JIRA: YARDSTICK-891 Change-Id: Ie437ccf1172cb82dc869963f0d62e31a5ab23ebb Signed-off-by: Shobhi Jain (cherry picked from commit f6cca46f6b1aa6134a0e634a3a9e524cdbbfa729) --- yardstick/benchmark/scenarios/lib/detach_volume.py | 33 ++++++++------ yardstick/common/exceptions.py | 4 ++ yardstick/common/openstack_utils.py | 22 +++++++-- .../benchmark/scenarios/lib/test_detach_volume.py | 53 +++++++++++++++++----- .../tests/unit/common/test_openstack_utils.py | 27 +++++++++++ 5 files changed, 109 insertions(+), 30 deletions(-) diff --git a/yardstick/benchmark/scenarios/lib/detach_volume.py b/yardstick/benchmark/scenarios/lib/detach_volume.py index 0b02a3a81..76c0167bd 100644 --- a/yardstick/benchmark/scenarios/lib/detach_volume.py +++ b/yardstick/benchmark/scenarios/lib/detach_volume.py @@ -6,14 +6,12 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - -from __future__ import print_function -from __future__ import absolute_import - import logging +from yardstick.common import openstack_utils +from yardstick.common import exceptions from yardstick.benchmark.scenarios import base -import yardstick.common.openstack_utils as op_utils + LOG = logging.getLogger(__name__) @@ -26,10 +24,14 @@ class DetachVolume(base.Scenario): def __init__(self, scenario_cfg, context_cfg): self.scenario_cfg = scenario_cfg self.context_cfg = context_cfg - self.options = self.scenario_cfg['options'] + self.options = self.scenario_cfg["options"] - self.server_id = self.options.get("server_id", "TestServer") - self.volume_id = self.options.get("volume_id", None) + self.server = self.options["server_name_or_id"] + self.volume = self.options["volume_name_or_id"] + self.wait = self.options.get("wait", True) + self.timeout = self.options.get("timeout") + + self.shade_client = openstack_utils.get_shade_client() self.setup_done = False @@ -44,11 +46,14 @@ class DetachVolume(base.Scenario): if not self.setup_done: self.setup() - status = op_utils.detach_volume(self.server_id, self.volume_id) + status = openstack_utils.detach_volume( + self.shade_client, self.server, self.volume, + wait=self.wait, timeout=self.timeout) - if status: - result.update({"detach_volume": 1}) - LOG.info("Detach volume from server successful!") - else: + if not status: result.update({"detach_volume": 0}) - LOG.info("Detach volume from server failed!") + LOG.error("Detach volume from server failed!") + raise exceptions.ScenarioDetachVolumeError + + result.update({"detach_volume": 1}) + LOG.info("Detach volume from server successful!") diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py index 1ddd88432..39a3d2004 100644 --- a/yardstick/common/exceptions.py +++ b/yardstick/common/exceptions.py @@ -254,6 +254,10 @@ class ScenarioDeleteVolumeError(YardstickException): message = 'Cinder Delete Volume Scenario failed' +class ScenarioDetachVolumeError(YardstickException): + message = 'Cinder Detach Volume Scenario failed' + + class ApiServerError(YardstickException): message = 'An unkown exception happened to Api Server!' diff --git a/yardstick/common/openstack_utils.py b/yardstick/common/openstack_utils.py index a9d833fff..a2b75e0e0 100644 --- a/yardstick/common/openstack_utils.py +++ b/yardstick/common/openstack_utils.py @@ -824,11 +824,23 @@ def delete_volume(shade_client, name_or_id=None, wait=True, timeout=None): return False -def detach_volume(server_id, volume_id): # pragma: no cover +def detach_volume(shade_client, server_name_or_id, volume_name_or_id, + wait=True, timeout=None): + """Detach a volume from a server. + + :param server_name_or_id: The server name or id to detach from. + :param volume_name_or_id: The volume name or id to detach. + :param wait: If true, waits for volume to be detached. + :param timeout: Seconds to wait for volume detachment. None is forever. + + :return: True on success. + """ try: - get_nova_client().volumes.delete_server_volume(server_id, volume_id) + volume = shade_client.get_volume(volume_name_or_id) + server = get_server(shade_client, name_or_id=server_name_or_id) + shade_client.detach_volume(server, volume, wait=wait, timeout=timeout) return True - except Exception: # pylint: disable=broad-except - log.exception("Error [detach_server_volume(nova_client, '%s', '%s')]", - server_id, volume_id) + except (exc.OpenStackCloudException, exc.OpenStackCloudTimeout) as o_exc: + log.error("Error [detach_volume(shade_client)]. " + "Exception message: %s", o_exc.orig_message) return False diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py index 9794d2129..2bc57f495 100644 --- a/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py +++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py @@ -6,21 +6,52 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +from oslo_utils import uuidutils import unittest import mock -from yardstick.benchmark.scenarios.lib.detach_volume import DetachVolume +from yardstick.common import openstack_utils +from yardstick.common import exceptions +from yardstick.benchmark.scenarios.lib import detach_volume class DetachVolumeTestCase(unittest.TestCase): - @mock.patch('yardstick.common.openstack_utils.detach_volume') - def test_detach_volume(self, mock_detach_volume): - options = { - 'server_id': '321-321-321', - 'volume_id': '123-123-123' - } - args = {"options": options} - obj = DetachVolume(args, {}) - obj.run({}) - mock_detach_volume.assert_called_once() + def setUp(self): + self._mock_detach_volume = mock.patch.object( + openstack_utils, 'detach_volume') + self.mock_detach_volume = ( + self._mock_detach_volume.start()) + self._mock_get_shade_client = mock.patch.object( + openstack_utils, 'get_shade_client') + self.mock_get_shade_client = self._mock_get_shade_client.start() + self._mock_log = mock.patch.object(detach_volume, 'LOG') + self.mock_log = self._mock_log.start() + _uuid = uuidutils.generate_uuid() + self.args = {'options': {'server_name_or_id': _uuid, + 'volume_name_or_id': _uuid}} + self.result = {} + + self.detachvol_obj = detach_volume.DetachVolume(self.args, mock.ANY) + + self.addCleanup(self._stop_mock) + + def _stop_mock(self): + self._mock_detach_volume.stop() + self._mock_get_shade_client.stop() + self._mock_log.stop() + + def test_run(self): + self.mock_detach_volume.return_value = True + self.assertIsNone(self.detachvol_obj.run(self.result)) + self.assertEqual({'detach_volume': 1}, self.result) + self.mock_log.info.assert_called_once_with( + 'Detach volume from server successful!') + + def test_run_fail(self): + self.mock_detach_volume.return_value = False + with self.assertRaises(exceptions.ScenarioDetachVolumeError): + self.detachvol_obj.run(self.result) + self.assertEqual({'detach_volume': 0}, self.result) + self.mock_log.error.assert_called_once_with( + 'Detach volume from server failed!') diff --git a/yardstick/tests/unit/common/test_openstack_utils.py b/yardstick/tests/unit/common/test_openstack_utils.py index 6497f664e..d1d91e2d5 100644 --- a/yardstick/tests/unit/common/test_openstack_utils.py +++ b/yardstick/tests/unit/common/test_openstack_utils.py @@ -604,3 +604,30 @@ class DeleteVolumeTestCase(unittest.TestCase): 'volume_name_or_id') mock_logger.error.assert_called_once() self.assertFalse(output) + + +class DetachVolumeTestCase(unittest.TestCase): + + @mock.patch.object(openstack_utils, 'get_server') + def test_detach_volume(self, mock_get_server): + self.mock_shade_client = mock.Mock() + mock_get_server.return_value = {'server_dict'} + self.mock_shade_client.get_volume.return_value = {'volume_dict'} + output = openstack_utils.detach_volume(self.mock_shade_client, + 'server_name_or_id', + 'volume_name_or_id') + self.assertTrue(output) + + @mock.patch.object(openstack_utils, 'get_server') + @mock.patch.object(openstack_utils, 'log') + def test_detach_volume_exception(self, mock_logger, mock_get_server): + self.mock_shade_client = mock.Mock() + mock_get_server.return_value = {'server_dict'} + self.mock_shade_client.get_volume.return_value = {'volume_dict'} + self.mock_shade_client.detach_volume.side_effect = ( + exc.OpenStackCloudException('error message')) + output = openstack_utils.detach_volume(self.mock_shade_client, + 'server_name_or_id', + 'volume_name_or_id') + mock_logger.error.assert_called_once() + self.assertFalse(output) -- cgit 1.2.3-korg