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
This commit is contained in:
Kiran Pawar 2021-11-12 11:01:32 +00:00
parent f7c7c38d5e
commit 39ebe3307a
7 changed files with 178 additions and 14 deletions

View File

@ -27,7 +27,7 @@ from manilaclient import utils
LOG = logging.getLogger(__name__)
MAX_VERSION = '2.66'
MAX_VERSION = '2.67'
MIN_VERSION = '2.0'
DEPRECATED_VERSION = '1.0'
_VERSIONED_METHOD_MAP = {}

View File

@ -11,10 +11,12 @@
# under the License.
import logging
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils as osc_utils
from manilaclient import api_versions
from manilaclient.common._i18n import _
from manilaclient.common import cliutils
from manilaclient.osc import utils
@ -45,6 +47,15 @@ class CreateShareReplica(command.ShowOne):
default=False,
help=_('Wait for replica creation')
)
parser.add_argument(
"--scheduler-hint",
metavar="<key=value>",
default={},
action=parseractions.KeyValueAction,
help=_("Scheduler hint for the share replica as key=value pairs, "
"Supported key is only_host. Available for microversion "
">= 2.67."),
)
return parser
def take_action(self, parsed_args):
@ -52,10 +63,28 @@ class CreateShareReplica(command.ShowOne):
share = osc_utils.find_resource(share_client.shares,
parsed_args.share)
share_replica = share_client.share_replicas.create(
share,
availability_zone=parsed_args.availability_zone
)
scheduler_hints = {}
if parsed_args.scheduler_hint:
if share_client.api_version < api_versions.APIVersion("2.67"):
raise exceptions.CommandError(_(
"arg '--scheduler_hint' is available only starting with "
"API microversion '2.67'."))
hints = utils.extract_key_value_options(parsed_args.scheduler_hint)
if 'only_host' not in hints.keys() or len(hints) > 1:
raise exceptions.CommandError(
"The only valid key supported with the --scheduler-hint "
"argument is 'only_host'.")
scheduler_hints['only_host'] = hints.get('only_host')
body = {
'share': share,
'availability_zone': parsed_args.availability_zone,
}
if scheduler_hints:
body['scheduler_hints'] = scheduler_hints
share_replica = share_client.share_replicas.create(**body)
if parsed_args.wait:
if not osc_utils.wait_for_status(
status_f=share_client.share_replicas.get,

View File

@ -15,6 +15,8 @@ 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
@ -34,6 +36,8 @@ class TestShareReplica(manila_fakes.TestShare):
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
@ -84,7 +88,7 @@ class TestShareReplicaCreate(TestShareReplica):
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
self.share,
share=self.share,
availability_zone=None
)
@ -106,13 +110,75 @@ class TestShareReplicaCreate(TestShareReplica):
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
self.share,
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,
@ -128,7 +194,7 @@ class TestShareReplicaCreate(TestShareReplica):
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
self.share,
share=self.share,
availability_zone=None
)
@ -153,7 +219,7 @@ class TestShareReplicaCreate(TestShareReplica):
columns, data = self.cmd.take_action(parsed_args)
self.replicas_mock.create.assert_called_with(
self.share,
share=self.share,
availability_zone=None
)

View File

@ -33,7 +33,7 @@ class ShareReplicasTest(utils.TestCase):
def setUp(self):
super(ShareReplicasTest, self).setUp()
microversion = api_versions.APIVersion("2.11")
microversion = api_versions.APIVersion("2.67")
self.manager = share_replicas.ShareReplicaManager(
fakes.FakeClient(api_version=microversion))

View File

@ -116,17 +116,26 @@ class ShareReplicaManager(base.ManagerWithFind):
return self._create_share_replica(
share, availability_zone=availability_zone)
@api_versions.wraps(constants.REPLICA_GRADUATION_VERSION) # noqa
@api_versions.wraps(constants.REPLICA_GRADUATION_VERSION, '2.66') # noqa
def create(self, share, availability_zone=None): # noqa F811
return self._create_share_replica(
share, availability_zone=availability_zone)
def _create_share_replica(self, share, availability_zone=None):
@api_versions.wraps("2.67") # noqa
def create(self, share, availability_zone=None, scheduler_hints=None): # noqa F811
return self._create_share_replica(
share, availability_zone=availability_zone,
scheduler_hints=scheduler_hints)
def _create_share_replica(self, share, availability_zone=None,
scheduler_hints=None):
"""Create a replica for a share.
:param share: The share to create the replica of. Can be the share
object or its UUID.
:param availability_zone: The 'availability_zone' object or its UUID.
:param scheduler_hints: The scheduler_hints as key=value pair. Only
supported key is 'only_host'.
"""
share_id = common_base.getid(share)
@ -135,6 +144,8 @@ class ShareReplicaManager(base.ManagerWithFind):
if availability_zone:
body['availability_zone'] = common_base.getid(availability_zone)
if scheduler_hints:
body['scheduler_hints'] = scheduler_hints
return self._create(RESOURCES_PATH,
{RESOURCE_NAME: body},
RESOURCE_NAME)

View File

@ -6009,6 +6009,7 @@ def do_share_replica_list(cs, args):
cliutils.print_list(replicas, list_of_keys)
@api_versions.wraps("2.11", "2.66")
@cliutils.arg(
'share',
metavar='<share>',
@ -6021,12 +6022,61 @@ def do_share_replica_list(cs, args):
action='single_alias',
metavar='<availability-zone>',
help='Optional Availability zone in which replica should be created.')
@api_versions.wraps("2.11")
def do_share_replica_create(cs, args):
"""Create a share replica."""
share = _find_share(cs, args.share)
replica = cs.share_replicas.create(share, args.availability_zone)
body = {
'share': share,
'availability_zone': args.availability_zone,
}
replica = cs.share_replicas.create(**body)
_print_share_replica(cs, replica)
@api_versions.wraps("2.67")
@cliutils.arg(
'share',
metavar='<share>',
help='Name or ID of the share to replicate.')
@cliutils.arg(
'--availability-zone',
'--availability_zone',
'--az',
default=None,
action='single_alias',
metavar='<availability-zone>',
help='Optional Availability zone in which replica should be created.')
@cliutils.arg(
'--scheduler-hints',
'--scheduler_hints',
'--sh',
metavar='<key=value>',
nargs='*',
help='Scheduler hints for the share replica as key=value pairs, '
'Supported key is only_host. Available for microversion >= 2.67. ',
default=None)
def do_share_replica_create(cs, args): # noqa
"""Create a share replica."""
share = _find_share(cs, args.share)
scheduler_hints = {}
if args.scheduler_hints:
hints = _extract_key_value_options(args, 'scheduler_hints')
if 'only_host' not in hints.keys() or len(hints) > 1:
raise exceptions.CommandError(
"The only valid key supported with the --scheduler-hints "
"argument is 'only_host'.")
scheduler_hints['only_host'] = hints.get('only_host')
body = {
'share': share,
'availability_zone': args.availability_zone,
}
if scheduler_hints:
body['scheduler_hints'] = scheduler_hints
replica = cs.share_replicas.create(**body)
_print_share_replica(cs, replica)

View File

@ -0,0 +1,8 @@
---
features:
- Added --scheduler_hints to the share-replica create command of manila
shellclient. In case of OSC, --scheduler-hint is used. Scheduler hints in
the share-replica create allow scheduler to select appropriate host using
filters. For example, user needs to specify "only_host=host@backend#pool"
when creating a manila share-replica in case of onlyhostFilter. Supported
for microversion >= 2.67.