Skip to content

Commit 60a0e37

Browse files
committed
volume: Support same_host, different_host hint as list
When creating a volume, the scheduler hints can be supplied as strings. The "same_host" and "different_host" hints can also be supplied as a list if affinity/anti-affinity to multiple volumes is requested [0] The previously-used `KeyValueAction` only supplies strings as values - the last one if multiple --hint contain the same key. An alternative already used in `CreateServer` would be `KeyValueAppendAction`, but only a subset of the scheduler hints accept lists, so we cannot use that in general. Therefore, we create `KeyValueHintAction`. It contains both a `KeyValueAction` and a `KeyValueAppendAction` object and calls the appropriate action based on the beginning of the given values as defined in `APPEND_KEYS`. [0] https://github.com/sapcc/cinder/blob/d96b705774e8ca85c75d3d0292722da8fe8cb14f/cinder/api/schemas/scheduler_hints.py#L31-L65 Change-Id: Ida7f4662dc9fea24510758541fd4f2622b73bf31
1 parent 98b9496 commit 60a0e37

2 files changed

Lines changed: 96 additions & 3 deletions

File tree

openstackclient/tests/unit/volume/v2/test_volume.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,74 @@ def test_volume_create_with_multi_source(self):
686686
verifylist,
687687
)
688688

689+
def test_volume_create_hints(self):
690+
"""--hint needs to behave differently based on the given hint
691+
692+
different_host and same_host need to append to a list if given multiple
693+
times. All other parameter are strings.
694+
"""
695+
arglist = [
696+
'--size',
697+
str(self.new_volume.size),
698+
'--hint',
699+
'k=v',
700+
'--hint',
701+
'k=v2',
702+
'--hint',
703+
'same_host=v3',
704+
'--hint',
705+
'same_host=v4',
706+
'--hint',
707+
'different_host=v5',
708+
'--hint',
709+
'local_to_instance=v6',
710+
'--hint',
711+
'different_host=v7',
712+
self.new_volume.name,
713+
]
714+
verifylist = [
715+
('size', self.new_volume.size),
716+
(
717+
'hint',
718+
{
719+
'k': 'v2',
720+
'same_host': ['v3', 'v4'],
721+
'local_to_instance': 'v6',
722+
'different_host': ['v5', 'v7'],
723+
},
724+
),
725+
('name', self.new_volume.name),
726+
]
727+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
728+
729+
# In base command class ShowOne in cliff, abstract method take_action()
730+
# returns a two-part tuple with a tuple of column names and a tuple of
731+
# data to be shown.
732+
columns, data = self.cmd.take_action(parsed_args)
733+
734+
self.volumes_mock.create.assert_called_with(
735+
size=self.new_volume.size,
736+
snapshot_id=None,
737+
name=self.new_volume.name,
738+
description=None,
739+
volume_type=None,
740+
availability_zone=None,
741+
metadata=None,
742+
imageRef=None,
743+
source_volid=None,
744+
consistencygroup_id=None,
745+
scheduler_hints={
746+
'k': 'v2',
747+
'same_host': ['v3', 'v4'],
748+
'local_to_instance': 'v6',
749+
'different_host': ['v5', 'v7'],
750+
},
751+
backup_id=None,
752+
)
753+
754+
self.assertEqual(self.columns, columns)
755+
self.assertCountEqual(self.datalist, data)
756+
689757

690758
class TestVolumeDelete(TestVolume):
691759
def setUp(self):

openstackclient/volume/v2/volume.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,29 @@
3333
LOG = logging.getLogger(__name__)
3434

3535

36+
class KeyValueHintAction(argparse.Action):
37+
"""Uses KeyValueAction or KeyValueAppendAction based on the given key"""
38+
39+
APPEND_KEYS = ('same_host', 'different_host')
40+
41+
def __init__(self, *args, **kwargs):
42+
self._key_value_action = parseractions.KeyValueAction(*args, **kwargs)
43+
self._key_value_append_action = parseractions.KeyValueAppendAction(
44+
*args, **kwargs
45+
)
46+
super().__init__(*args, **kwargs)
47+
48+
def __call__(self, parser, namespace, values, option_string=None):
49+
if values.startswith(self.APPEND_KEYS):
50+
self._key_value_append_action(
51+
parser, namespace, values, option_string=option_string
52+
)
53+
else:
54+
self._key_value_action(
55+
parser, namespace, values, option_string=option_string
56+
)
57+
58+
3659
class AttachmentsColumn(cliff_columns.FormattableColumn):
3760
"""Formattable column for attachments column.
3861
@@ -162,10 +185,12 @@ def get_parser(self, prog_name):
162185
parser.add_argument(
163186
"--hint",
164187
metavar="<key=value>",
165-
action=parseractions.KeyValueAction,
188+
action=KeyValueHintAction,
166189
help=_(
167-
"Arbitrary scheduler hint key-value pairs to help boot "
168-
"an instance (repeat option to set multiple hints)"
190+
"Arbitrary scheduler hint key-value pairs to help creating "
191+
"a volume. Repeat the option to set multiple hints. "
192+
"'same_host' and 'different_host' get values appended when "
193+
"repeated, all other keys take the last given value"
169194
),
170195
)
171196
bootable_group = parser.add_mutually_exclusive_group()

0 commit comments

Comments
 (0)