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:
parent
f7c7c38d5e
commit
39ebe3307a
@ -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 = {}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user