Files
python-manilaclient/manilaclient/tests/unit/osc/v2/test_share_replicas.py
Kiran Pawar 39ebe3307a Add --scheduler_hints to share replica create command
This commit adds --scheduler_hints option to share replica create
command of manila shellclient. For OSC, --scheduler-hint is used.
Users can specify scheduler hints e.g. "only_host=host@backend#pool"
to share replica create command which will then force share replica
creation on the specified host.

Depends-on: I2e6d8709fc02df16622bdc910127fa489835db38

Closes-Bug: #1950313
Change-Id: Iba3ed8107fc7ee8a056c8dee04406e2feb8ca055
2022-02-15 03:19:05 +00:00

670 lines
20 KiB
Python

# 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 unittest import mock
from osc_lib import exceptions
from osc_lib import utils as oscutils
from manilaclient import api_versions
from manilaclient.api_versions import MAX_VERSION
from manilaclient.common import cliutils
from manilaclient.osc import utils
from manilaclient.osc.v2 import share_replicas as osc_share_replicas
from manilaclient.tests.unit.osc import osc_utils
from manilaclient.tests.unit.osc.v2 import fakes as manila_fakes
class TestShareReplica(manila_fakes.TestShare):
def setUp(self):
super(TestShareReplica, self).setUp()
self.shares_mock = self.app.client_manager.share.shares
self.shares_mock.reset_mock()
self.replicas_mock = self.app.client_manager.share.share_replicas
self.replicas_mock.reset_mock()
self.app.client_manager.share.api_version = api_versions.APIVersion(
MAX_VERSION)
self.replica_el_mock = (
self.app.client_manager
.share.share_replica_export_locations)
self.replica_el_mock.reset_mock()
class TestShareReplicaCreate(TestShareReplica):
def setUp(self):
super(TestShareReplicaCreate, self).setUp()
self.share = manila_fakes.FakeShare.create_one_share()
self.shares_mock.get.return_value = self.share
self.share_replica = (
manila_fakes.FakeShareReplica.create_one_replica(
attrs={
'availability_zone': 'manila-zone-1',
'status': 'available'}
))
self.replicas_mock.create.return_value = self.share_replica
self.replicas_mock.get.return_value = self.share_replica
self.cmd = osc_share_replicas.CreateShareReplica(self.app, None)
self.data = tuple(self.share_replica._info.values())
self.columns = tuple(self.share_replica._info.keys())
def test_share_replica_create_missing_args(self):
arglist = []
verifylist = []
self.assertRaises(
osc_utils.ParserException,
self.check_parser, self.cmd, arglist, verifylist)
def test_share_replica_create(self):
arglist = [
self.share.id
]
verifylist = [
('share', self.share.id)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
share=self.share,
availability_zone=None
)
self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, data)
def test_share_replica_create_az(self):
arglist = [
self.share.id,
'--availability-zone', self.share.availability_zone
]
verifylist = [
('share', self.share.id),
('availability_zone', self.share.availability_zone)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
share=self.share,
availability_zone=self.share.availability_zone
)
self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, data)
def test_share_replica_create_scheduler_hint_valid(self):
arglist = [
self.share.id,
'--availability-zone', self.share.availability_zone,
'--scheduler-hint', ('only_host=host1@backend1#pool1'),
]
verifylist = [
('share', self.share.id),
('availability_zone', self.share.availability_zone),
('scheduler_hint', {'only_host': 'host1@backend1#pool1'})
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
share=self.share,
availability_zone=self.share.availability_zone,
scheduler_hints={'only_host': 'host1@backend1#pool1'}
)
self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, data)
def test_share_replica_create_scheduler_hint_invalid_hint(self):
arglist = [
self.share.id,
'--availability-zone', self.share.availability_zone,
'--scheduler-hint', 'fake_hint=host1@backend1#pool1'
]
verifylist = [
('share', self.share.id),
('availability_zone', self.share.availability_zone),
('scheduler_hint', {'fake_hint': 'host1@backend1#pool1'})
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action,
parsed_args)
def test_share_replica_create_scheduler_hint_invalid_version(self):
self.app.client_manager.share.api_version = api_versions.APIVersion(
"2.66")
arglist = [
self.share.id,
'--availability-zone', self.share.availability_zone,
'--scheduler-hint', 'only_host=host1@backend1#pool1'
]
verifylist = [
('share', self.share.id),
('availability_zone', self.share.availability_zone),
('scheduler_hint', {'only_host': 'host1@backend1#pool1'})
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(exceptions.CommandError,
self.cmd.take_action,
parsed_args)
def test_share_replica_create_wait(self):
arglist = [
self.share.id,
'--wait'
]
verifylist = [
('share', self.share.id),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
share=self.share,
availability_zone=None
)
self.replicas_mock.get.assert_called_with(self.share_replica.id)
self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, data)
@mock.patch('manilaclient.osc.v2.share_replicas.LOG')
def test_share_replica_create_wait_exception(self, mock_logger):
arglist = [
self.share.id,
'--wait'
]
verifylist = [
('share', self.share.id),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('osc_lib.utils.wait_for_status', return_value=False):
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
share=self.share,
availability_zone=None
)
mock_logger.error.assert_called_with(
"ERROR: Share replica is in error state.")
self.replicas_mock.get.assert_called_with(self.share_replica.id)
self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, data)
class TestShareReplicaDelete(TestShareReplica):
def setUp(self):
super(TestShareReplicaDelete, self).setUp()
self.share_replica = (
manila_fakes.FakeShareReplica.create_one_replica())
self.replicas_mock.get.return_value = self.share_replica
self.cmd = osc_share_replicas.DeleteShareReplica(self.app, None)
def test_share_replica_delete_missing_args(self):
arglist = []
verifylist = []
self.assertRaises(osc_utils.ParserException,
self.check_parser, self.cmd, arglist, verifylist)
def test_share_replica_delete(self):
arglist = [
self.share_replica.id
]
verifylist = [
('replica', [self.share_replica.id])
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.replicas_mock.delete.assert_called_with(
self.share_replica,
force=False)
self.assertIsNone(result)
def test_share_replica_delete_force(self):
arglist = [
self.share_replica.id,
'--force'
]
verifylist = [
('replica', [self.share_replica.id]),
('force', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.replicas_mock.delete.assert_called_with(
self.share_replica,
force=True)
self.assertIsNone(result)
def test_share_replica_delete_multiple(self):
share_replicas = (
manila_fakes.FakeShareReplica.create_share_replicas(
count=2))
arglist = [
share_replicas[0].id,
share_replicas[1].id
]
verifylist = [
('replica', [share_replicas[0].id, share_replicas[1].id])
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.assertEqual(self.replicas_mock.delete.call_count,
len(share_replicas))
self.assertIsNone(result)
def test_share_snapshot_delete_exception(self):
arglist = [
self.share_replica.id
]
verifylist = [
('replica', [self.share_replica.id])
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.replicas_mock.delete.side_effect = exceptions.CommandError()
self.assertRaises(exceptions.CommandError,
self.cmd.take_action,
parsed_args)
def test_share_replica_delete_wait(self):
arglist = [
self.share_replica.id,
'--wait'
]
verifylist = [
('replica', [self.share_replica.id]),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('osc_lib.utils.wait_for_delete', return_value=True):
result = self.cmd.take_action(parsed_args)
self.replicas_mock.delete.assert_called_with(
self.share_replica,
force=False)
self.replicas_mock.get.assert_called_with(self.share_replica.id)
self.assertIsNone(result)
def test_share_replica_delete_wait_exception(self):
arglist = [
self.share_replica.id,
'--wait'
]
verifylist = [
('replica', [self.share_replica.id]),
('wait', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
with mock.patch('osc_lib.utils.wait_for_delete', return_value=False):
self.assertRaises(
exceptions.CommandError,
self.cmd.take_action,
parsed_args
)
class TestShareReplicaList(TestShareReplica):
columns = [
'id',
'status',
'replica_state',
'share_id',
'host',
'availability_zone',
'updated_at',
]
column_headers = utils.format_column_headers(columns)
def setUp(self):
super(TestShareReplicaList, self).setUp()
self.share = manila_fakes.FakeShare.create_one_share()
self.shares_mock.get.return_value = self.share
self.replicas_list = (
manila_fakes.FakeShareReplica.create_share_replicas(
count=2))
self.replicas_mock.list.return_value = self.replicas_list
self.values = (oscutils.get_dict_properties(
i._info, self.columns) for i in self.replicas_list)
self.cmd = osc_share_replicas.ListShareReplica(self.app, None)
def test_share_replica_list(self):
arglist = []
verifylist = []
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.list.assert_called_with(share=None)
self.assertEqual(self.column_headers, columns)
self.assertEqual(list(self.values), list(data))
def test_share_replica_list_for_share(self):
arglist = [
'--share', self.share.id
]
verifylist = [
('share', self.share.id)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.list.assert_called_with(share=self.share)
self.assertEqual(self.column_headers, columns)
self.assertEqual(list(self.values), list(data))
class TestShareReplicaShow(TestShareReplica):
def setUp(self):
super(TestShareReplicaShow, self).setUp()
self.share_replica = (
manila_fakes.FakeShareReplica.create_one_replica()
)
self.replicas_mock.get.return_value = self.share_replica
self.replica_el_list = (
manila_fakes.FakeShareExportLocation.
create_share_export_locations(count=2)
)
self.replica_el_mock.list.return_value = (
self.replica_el_list)
self.cmd = osc_share_replicas.ShowShareReplica(self.app, None)
self.share_replica._info['export_locations'] = (
cliutils.convert_dict_list_to_string(
self.replica_el_list))
self.data = tuple(self.share_replica._info.values())
self.columns = tuple(self.share_replica._info.keys())
def test_share_replica_show_missing_args(self):
arglist = []
verifylist = []
self.assertRaises(
osc_utils.ParserException,
self.check_parser, self.cmd, arglist, verifylist)
def test_share_replica_show(self):
arglist = [
self.share_replica.id
]
verifylist = [
('replica', self.share_replica.id)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.get.assert_called_with(
self.share_replica.id
)
self.assertCountEqual(self.columns, columns)
self.assertCountEqual(self.data, data)
class TestShareReplicaSet(TestShareReplica):
def setUp(self):
super(TestShareReplicaSet, self).setUp()
self.share_replica = (
manila_fakes.FakeShareReplica.create_one_replica()
)
self.replicas_mock.get.return_value = self.share_replica
self.cmd = osc_share_replicas.SetShareReplica(self.app, None)
def test_share_replica_set_replica_state(self):
new_replica_state = 'in_sync'
arglist = [
self.share_replica.id,
'--replica-state', new_replica_state
]
verifylist = [
('replica', self.share_replica.id),
('replica_state', new_replica_state)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.replicas_mock.reset_replica_state.assert_called_with(
self.share_replica,
new_replica_state)
self.assertIsNone(result)
def test_share_replica_set_replica_state_exception(self):
new_replica_state = 'in_sync'
arglist = [
self.share_replica.id,
'--replica-state', new_replica_state
]
verifylist = [
('replica', self.share_replica.id),
('replica_state', new_replica_state)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.replicas_mock.reset_replica_state.side_effect = Exception()
self.assertRaises(
exceptions.CommandError,
self.cmd.take_action,
parsed_args)
def test_share_replica_set_status(self):
new_status = 'available'
arglist = [
self.share_replica.id,
'--status', new_status
]
verifylist = [
('replica', self.share_replica.id),
('status', new_status)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.replicas_mock.reset_state.assert_called_with(
self.share_replica,
new_status)
self.assertIsNone(result)
def test_share_replica_set_status_exception(self):
new_status = 'available'
arglist = [
self.share_replica.id,
'--status', new_status
]
verifylist = [
('replica', self.share_replica.id),
('status', new_status)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.replicas_mock.reset_state.side_effect = Exception()
self.assertRaises(
exceptions.CommandError,
self.cmd.take_action,
parsed_args)
def test_share_replica_set_nothing_defined(self):
arglist = [
self.share_replica.id,
]
verifylist = [
('replica', self.share_replica.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError,
self.cmd.take_action,
parsed_args)
class TestShareReplicaPromote(TestShareReplica):
def setUp(self):
super(TestShareReplicaPromote, self).setUp()
self.share_replica = (
manila_fakes.FakeShareReplica.create_one_replica()
)
self.replicas_mock.get.return_value = self.share_replica
self.cmd = osc_share_replicas.PromoteShareReplica(
self.app, None)
def test_share_replica_promote(self):
arglist = [
self.share_replica.id,
]
verifylist = [
('replica', self.share_replica.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.replicas_mock.promote.assert_called_with(
self.share_replica)
self.assertIsNone(result)
def test_share_replica_promote_exception(self):
arglist = [
self.share_replica.id,
]
verifylist = [
('replica', self.share_replica.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.replicas_mock.promote.side_effect = Exception()
self.assertRaises(
exceptions.CommandError,
self.cmd.take_action,
parsed_args)
class TestShareReplicaResync(TestShareReplica):
def setUp(self):
super(TestShareReplicaResync, self).setUp()
self.share_replica = (
manila_fakes.FakeShareReplica.create_one_replica()
)
self.replicas_mock.get.return_value = self.share_replica
self.cmd = osc_share_replicas.ResyncShareReplica(
self.app, None)
def test_share_replica_resync(self):
arglist = [
self.share_replica.id,
]
verifylist = [
('replica', self.share_replica.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
result = self.cmd.take_action(parsed_args)
self.replicas_mock.resync.assert_called_with(
self.share_replica)
self.assertIsNone(result)
def test_share_replica_resync_exception(self):
arglist = [
self.share_replica.id,
]
verifylist = [
('replica', self.share_replica.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.replicas_mock.resync.side_effect = Exception()
self.assertRaises(
exceptions.CommandError,
self.cmd.take_action,
parsed_args)