diff options
| author | whoami-rajat <rajatdhasmana@gmail.com> | 2023-02-01 15:04:43 +0530 |
|---|---|---|
| committer | whoami-rajat <rajatdhasmana@gmail.com> | 2023-02-17 10:02:22 +0000 |
| commit | 2be359677908b81d9985917fd78f9c6897759fb9 (patch) | |
| tree | 0f85d1e21234a6101988993bbcafd754eace0622 /openstackclient/tests/unit | |
| parent | a9e3049e9ce8a6e2d46152ef85ad6679b8cb8f1d (diff) | |
| download | python-openstackclient-2be359677908b81d9985917fd78f9c6897759fb9.tar.gz | |
Add block storage cleanup command
This patch adds the ``block storage cleanup`` command that
allow operators to cleanup resources (volumes and snapshots) with
failed operations by requesting services in other hosts in the
same cluster to cleanup resources of a failed service.
Change-Id: I1375223f525021db5201fa0a9f9a647d17dd01f7
Diffstat (limited to 'openstackclient/tests/unit')
| -rw-r--r-- | openstackclient/tests/unit/volume/v3/fakes.py | 32 | ||||
| -rw-r--r-- | openstackclient/tests/unit/volume/v3/test_block_storage_cleanup.py | 178 |
2 files changed, 210 insertions, 0 deletions
diff --git a/openstackclient/tests/unit/volume/v3/fakes.py b/openstackclient/tests/unit/volume/v3/fakes.py index 4e8e6597..7bde154e 100644 --- a/openstackclient/tests/unit/volume/v3/fakes.py +++ b/openstackclient/tests/unit/volume/v3/fakes.py @@ -49,6 +49,8 @@ class FakeVolumeClient: self.volume_types.resource_class = fakes.FakeResource(None, {}) self.services = mock.Mock() self.services.resource_class = fakes.FakeResource(None, {}) + self.workers = mock.Mock() + self.workers.resource_class = fakes.FakeResource(None, {}) class TestVolume(utils.TestCommand): @@ -455,3 +457,33 @@ def create_service_log_level_entry(attrs=None): service_log_level = fakes.FakeResource( None, service_log_level_info, loaded=True) return service_log_level + + +def create_cleanup_records(): + """Create fake service cleanup records. + + :return: A list of FakeResource objects + """ + cleaning_records = [] + unavailable_records = [] + cleaning_work_info = { + 'id': 1, + 'host': 'devstack@fakedriver-1', + 'binary': 'cinder-volume', + 'cluster_name': 'fake_cluster', + } + unavailable_work_info = { + 'id': 2, + 'host': 'devstack@fakedriver-2', + 'binary': 'cinder-scheduler', + 'cluster_name': 'new_cluster', + } + cleaning_records.append(cleaning_work_info) + unavailable_records.append(unavailable_work_info) + + cleaning = [fakes.FakeResource( + None, obj, loaded=True) for obj in cleaning_records] + unavailable = [fakes.FakeResource( + None, obj, loaded=True) for obj in unavailable_records] + + return cleaning, unavailable diff --git a/openstackclient/tests/unit/volume/v3/test_block_storage_cleanup.py b/openstackclient/tests/unit/volume/v3/test_block_storage_cleanup.py new file mode 100644 index 00000000..b48ce2f9 --- /dev/null +++ b/openstackclient/tests/unit/volume/v3/test_block_storage_cleanup.py @@ -0,0 +1,178 @@ +# 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 uuid + +from cinderclient import api_versions +from osc_lib import exceptions + +from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes +from openstackclient.volume.v3 import block_storage_cleanup + + +class TestBlockStorage(volume_fakes.TestVolume): + + def setUp(self): + super().setUp() + + # Get a shortcut to the BlockStorageWorkerManager Mock + self.worker_mock = self.app.client_manager.volume.workers + self.worker_mock.reset_mock() + + +class TestBlockStorageCleanup(TestBlockStorage): + + cleaning, unavailable = volume_fakes.create_cleanup_records() + + def setUp(self): + super().setUp() + + self.worker_mock.clean.return_value = (self.cleaning, self.unavailable) + + # Get the command object to test + self.cmd = \ + block_storage_cleanup.BlockStorageCleanup(self.app, None) + + def test_cleanup(self): + self.app.client_manager.volume.api_version = \ + api_versions.APIVersion('3.24') + + arglist = [ + ] + verifylist = [ + ('cluster', None), + ('host', None), + ('binary', None), + ('is_up', None), + ('disabled', None), + ('resource_id', None), + ('resource_type', None), + ('service_id', None), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + expected_columns = ('ID', 'Cluster Name', 'Host', 'Binary', 'Status') + cleaning_data = tuple( + ( + obj.id, + obj.cluster_name, + obj.host, + obj.binary, + 'Cleaning' + ) for obj in self.cleaning + ) + unavailable_data = tuple( + ( + obj.id, + obj.cluster_name, + obj.host, + obj.binary, + 'Unavailable' + ) for obj in self.unavailable + ) + expected_data = cleaning_data + unavailable_data + columns, data = self.cmd.take_action(parsed_args) + + self.assertEqual(expected_columns, columns) + self.assertEqual(expected_data, tuple(data)) + + # checking if proper call was made to cleanup resources + # Since we ignore all parameters with None value, we don't + # have any arguments passed to the API + self.worker_mock.clean.assert_called_once_with() + + def test_block_storage_cleanup_pre_324(self): + arglist = [ + ] + verifylist = [ + ('cluster', None), + ('host', None), + ('binary', None), + ('is_up', None), + ('disabled', None), + ('resource_id', None), + ('resource_type', None), + ('service_id', None), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + exc = self.assertRaises(exceptions.CommandError, self.cmd.take_action, + parsed_args) + self.assertIn( + '--os-volume-api-version 3.24 or greater is required', str(exc)) + + def test_cleanup_with_args(self): + self.app.client_manager.volume.api_version = \ + api_versions.APIVersion('3.24') + + fake_cluster = 'fake-cluster' + fake_host = 'fake-host' + fake_binary = 'fake-service' + fake_resource_id = str(uuid.uuid4()) + fake_resource_type = 'Volume' + fake_service_id = 1 + arglist = [ + '--cluster', fake_cluster, + '--host', fake_host, + '--binary', fake_binary, + '--down', + '--enabled', + '--resource-id', fake_resource_id, + '--resource-type', fake_resource_type, + '--service-id', str(fake_service_id), + ] + verifylist = [ + ('cluster', fake_cluster), + ('host', fake_host), + ('binary', fake_binary), + ('is_up', False), + ('disabled', False), + ('resource_id', fake_resource_id), + ('resource_type', fake_resource_type), + ('service_id', fake_service_id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + expected_columns = ('ID', 'Cluster Name', 'Host', 'Binary', 'Status') + cleaning_data = tuple( + ( + obj.id, + obj.cluster_name, + obj.host, + obj.binary, + 'Cleaning' + ) for obj in self.cleaning + ) + unavailable_data = tuple( + ( + obj.id, + obj.cluster_name, + obj.host, + obj.binary, + 'Unavailable' + ) for obj in self.unavailable + ) + expected_data = cleaning_data + unavailable_data + columns, data = self.cmd.take_action(parsed_args) + + self.assertEqual(expected_columns, columns) + self.assertEqual(expected_data, tuple(data)) + + # checking if proper call was made to cleanup resources + self.worker_mock.clean.assert_called_once_with( + cluster_name=fake_cluster, + host=fake_host, + binary=fake_binary, + is_up=False, + disabled=False, + resource_id=fake_resource_id, + resource_type=fake_resource_type, + service_id=fake_service_id) |
