Merge "Add --image-property parameter in 'server create'"
This commit is contained in:
commit
5ed81c5a77
openstackclient
releasenotes/notes
@ -435,6 +435,12 @@ class CreateServer(command.ShowOne):
|
|||||||
metavar='<image>',
|
metavar='<image>',
|
||||||
help=_('Create server boot disk from this image (name or ID)'),
|
help=_('Create server boot disk from this image (name or ID)'),
|
||||||
)
|
)
|
||||||
|
disk_group.add_argument(
|
||||||
|
'--image-property',
|
||||||
|
metavar='<key=value>',
|
||||||
|
action=parseractions.KeyValueAction,
|
||||||
|
help=_("Image property to be matched"),
|
||||||
|
)
|
||||||
disk_group.add_argument(
|
disk_group.add_argument(
|
||||||
'--volume',
|
'--volume',
|
||||||
metavar='<volume>',
|
metavar='<volume>',
|
||||||
@ -609,6 +615,45 @@ class CreateServer(command.ShowOne):
|
|||||||
parsed_args.image,
|
parsed_args.image,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not image and parsed_args.image_property:
|
||||||
|
def emit_duplicated_warning(img, image_property):
|
||||||
|
img_uuid_list = [str(image.id) for image in img]
|
||||||
|
LOG.warning(_('Multiple matching images: %(img_uuid_list)s\n'
|
||||||
|
'Using image: %(chosen_one)s') %
|
||||||
|
{'img_uuid_list': img_uuid_list,
|
||||||
|
'chosen_one': img_uuid_list[0]})
|
||||||
|
|
||||||
|
def _match_image(image_api, wanted_properties):
|
||||||
|
image_list = image_api.image_list()
|
||||||
|
images_matched = []
|
||||||
|
for img in image_list:
|
||||||
|
img_dict = {}
|
||||||
|
# exclude any unhashable entries
|
||||||
|
for key, value in img.items():
|
||||||
|
try:
|
||||||
|
set([key, value])
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
img_dict[key] = value
|
||||||
|
if all(k in img_dict and img_dict[k] == v
|
||||||
|
for k, v in wanted_properties.items()):
|
||||||
|
images_matched.append(img)
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
return images_matched
|
||||||
|
|
||||||
|
images = _match_image(image_client.api, parsed_args.image_property)
|
||||||
|
if len(images) > 1:
|
||||||
|
emit_duplicated_warning(images,
|
||||||
|
parsed_args.image_property)
|
||||||
|
if images:
|
||||||
|
image = images[0]
|
||||||
|
else:
|
||||||
|
raise exceptions.CommandError(_("No images match the "
|
||||||
|
"property expected by "
|
||||||
|
"--image-property"))
|
||||||
|
|
||||||
# Lookup parsed_args.volume
|
# Lookup parsed_args.volume
|
||||||
volume = None
|
volume = None
|
||||||
if parsed_args.volume:
|
if parsed_args.volume:
|
||||||
|
@ -1528,6 +1528,164 @@ class TestServerCreate(TestServer):
|
|||||||
self.cmd.take_action,
|
self.cmd.take_action,
|
||||||
parsed_args)
|
parsed_args)
|
||||||
|
|
||||||
|
def test_server_create_image_property(self):
|
||||||
|
arglist = [
|
||||||
|
'--image-property', 'hypervisor_type=qemu',
|
||||||
|
'--flavor', 'flavor1',
|
||||||
|
'--nic', 'none',
|
||||||
|
self.new_server.name,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('image_property', {'hypervisor_type': 'qemu'}),
|
||||||
|
('flavor', 'flavor1'),
|
||||||
|
('nic', ['none']),
|
||||||
|
('config_drive', False),
|
||||||
|
('server_name', self.new_server.name),
|
||||||
|
]
|
||||||
|
_image = image_fakes.FakeImage.create_one_image()
|
||||||
|
# create a image_info as the side_effect of the fake image_list()
|
||||||
|
image_info = {
|
||||||
|
'id': _image.id,
|
||||||
|
'name': _image.name,
|
||||||
|
'owner': _image.owner,
|
||||||
|
'hypervisor_type': 'qemu',
|
||||||
|
}
|
||||||
|
self.api_mock = mock.Mock()
|
||||||
|
self.api_mock.image_list.side_effect = [
|
||||||
|
[image_info], [],
|
||||||
|
]
|
||||||
|
self.app.client_manager.image.api = self.api_mock
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Set expected values
|
||||||
|
kwargs = dict(
|
||||||
|
files={},
|
||||||
|
reservation_id=None,
|
||||||
|
min_count=1,
|
||||||
|
max_count=1,
|
||||||
|
security_groups=[],
|
||||||
|
userdata=None,
|
||||||
|
key_name=None,
|
||||||
|
availability_zone=None,
|
||||||
|
block_device_mapping_v2=[],
|
||||||
|
nics='none',
|
||||||
|
meta=None,
|
||||||
|
scheduler_hints={},
|
||||||
|
config_drive=None,
|
||||||
|
)
|
||||||
|
# ServerManager.create(name, image, flavor, **kwargs)
|
||||||
|
self.servers_mock.create.assert_called_with(
|
||||||
|
self.new_server.name,
|
||||||
|
image_info,
|
||||||
|
self.flavor,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.datalist(), data)
|
||||||
|
|
||||||
|
def test_server_create_image_property_multi(self):
|
||||||
|
arglist = [
|
||||||
|
'--image-property', 'hypervisor_type=qemu',
|
||||||
|
'--image-property', 'hw_disk_bus=ide',
|
||||||
|
'--flavor', 'flavor1',
|
||||||
|
'--nic', 'none',
|
||||||
|
self.new_server.name,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('image_property', {'hypervisor_type': 'qemu',
|
||||||
|
'hw_disk_bus': 'ide'}),
|
||||||
|
('flavor', 'flavor1'),
|
||||||
|
('nic', ['none']),
|
||||||
|
('config_drive', False),
|
||||||
|
('server_name', self.new_server.name),
|
||||||
|
]
|
||||||
|
_image = image_fakes.FakeImage.create_one_image()
|
||||||
|
# create a image_info as the side_effect of the fake image_list()
|
||||||
|
image_info = {
|
||||||
|
'id': _image.id,
|
||||||
|
'name': _image.name,
|
||||||
|
'owner': _image.owner,
|
||||||
|
'hypervisor_type': 'qemu',
|
||||||
|
'hw_disk_bus': 'ide',
|
||||||
|
}
|
||||||
|
self.api_mock = mock.Mock()
|
||||||
|
self.api_mock.image_list.side_effect = [
|
||||||
|
[image_info], [],
|
||||||
|
]
|
||||||
|
self.app.client_manager.image.api = self.api_mock
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
# Set expected values
|
||||||
|
kwargs = dict(
|
||||||
|
files={},
|
||||||
|
reservation_id=None,
|
||||||
|
min_count=1,
|
||||||
|
max_count=1,
|
||||||
|
security_groups=[],
|
||||||
|
userdata=None,
|
||||||
|
key_name=None,
|
||||||
|
availability_zone=None,
|
||||||
|
block_device_mapping_v2=[],
|
||||||
|
nics='none',
|
||||||
|
meta=None,
|
||||||
|
scheduler_hints={},
|
||||||
|
config_drive=None,
|
||||||
|
)
|
||||||
|
# ServerManager.create(name, image, flavor, **kwargs)
|
||||||
|
self.servers_mock.create.assert_called_with(
|
||||||
|
self.new_server.name,
|
||||||
|
image_info,
|
||||||
|
self.flavor,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(self.columns, columns)
|
||||||
|
self.assertEqual(self.datalist(), data)
|
||||||
|
|
||||||
|
def test_server_create_image_property_missed(self):
|
||||||
|
arglist = [
|
||||||
|
'--image-property', 'hypervisor_type=qemu',
|
||||||
|
'--image-property', 'hw_disk_bus=virtio',
|
||||||
|
'--flavor', 'flavor1',
|
||||||
|
'--nic', 'none',
|
||||||
|
self.new_server.name,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('image_property', {'hypervisor_type': 'qemu',
|
||||||
|
'hw_disk_bus': 'virtio'}),
|
||||||
|
('flavor', 'flavor1'),
|
||||||
|
('nic', ['none']),
|
||||||
|
('config_drive', False),
|
||||||
|
('server_name', self.new_server.name),
|
||||||
|
]
|
||||||
|
_image = image_fakes.FakeImage.create_one_image()
|
||||||
|
# create a image_info as the side_effect of the fake image_list()
|
||||||
|
image_info = {
|
||||||
|
'id': _image.id,
|
||||||
|
'name': _image.name,
|
||||||
|
'owner': _image.owner,
|
||||||
|
'hypervisor_type': 'qemu',
|
||||||
|
'hw_disk_bus': 'ide',
|
||||||
|
}
|
||||||
|
self.api_mock = mock.Mock()
|
||||||
|
self.api_mock.image_list.side_effect = [
|
||||||
|
[image_info], [],
|
||||||
|
]
|
||||||
|
self.app.client_manager.image.api = self.api_mock
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.CommandError,
|
||||||
|
self.cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
class TestServerDelete(TestServer):
|
class TestServerDelete(TestServer):
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Add a parameter ``--image-property`` to ``server create`` command.
|
||||||
|
This parameter will filter a image which properties that are matching.
|
Loading…
x
Reference in New Issue
Block a user