Skip to content

Commit 2c9d263

Browse files
author
Dean Troyer
committed
Fix server create for boot-from-volume
* server create required --image even when booting the server from a volume. Change options to require either --image or --volume to specify the server boot disk. Using --volume currently uses device 'vda' for the block mapping and ignores any other block mappings given in --block-device-mapping. * server create and server show are both affected by bug 1378842 where an excepion was thrown when no image ID was present in the returned server object, which is the case for a server booted from a volume. * Fix the remaining assertEqual() order problems in test_server.py Closes-Bug: 1378842 Closes-Bug: 1383338 Change-Id: I5daebf4e50a765d4920088dfead95b6295af6a4d
1 parent 8ba7445 commit 2c9d263

2 files changed

Lines changed: 52 additions & 21 deletions

File tree

‎openstackclient/compute/v2/server.py‎

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,10 @@ def _prep_server_detail(compute_client, server):
6767

6868
# Convert the image blob to a name
6969
image_info = info.get('image', {})
70-
image_id = image_info.get('id', '')
71-
image = utils.find_resource(compute_client.images, image_id)
72-
info['image'] = "%s (%s)" % (image.name, image_id)
70+
if image_info:
71+
image_id = image_info.get('id', '')
72+
image = utils.find_resource(compute_client.images, image_id)
73+
info['image'] = "%s (%s)" % (image.name, image_id)
7374

7475
# Convert the flavor blob to a name
7576
flavor_info = info.get('flavor', {})
@@ -192,11 +193,17 @@ def get_parser(self, prog_name):
192193
'server_name',
193194
metavar='<server-name>',
194195
help=_('New server name'))
195-
parser.add_argument(
196+
disk_group = parser.add_mutually_exclusive_group(
197+
required=True,
198+
)
199+
disk_group.add_argument(
196200
'--image',
197201
metavar='<image>',
198-
required=True,
199202
help=_('Create server from this image'))
203+
disk_group.add_argument(
204+
'--volume',
205+
metavar='<volume>',
206+
help=_('Create server from this volume'))
200207
parser.add_argument(
201208
'--flavor',
202209
metavar='<flavor>',
@@ -282,10 +289,23 @@ def get_parser(self, prog_name):
282289
def take_action(self, parsed_args):
283290
self.log.debug('take_action(%s)', parsed_args)
284291
compute_client = self.app.client_manager.compute
292+
volume_client = self.app.client_manager.volume
285293

286294
# Lookup parsed_args.image
287-
image = utils.find_resource(compute_client.images,
288-
parsed_args.image)
295+
image = None
296+
if parsed_args.image:
297+
image = utils.find_resource(
298+
compute_client.images,
299+
parsed_args.image,
300+
)
301+
302+
# Lookup parsed_args.volume
303+
volume = None
304+
if parsed_args.volume:
305+
volume = utils.find_resource(
306+
volume_client.volumes,
307+
parsed_args.volume,
308+
).id
289309

290310
# Lookup parsed_args.flavor
291311
flavor = utils.find_resource(compute_client.flavors,
@@ -319,8 +339,21 @@ def take_action(self, parsed_args):
319339
msg = "Can't open '%s': %s"
320340
raise exceptions.CommandError(msg % (parsed_args.user_data, e))
321341

322-
block_device_mapping = dict(v.split('=', 1)
323-
for v in parsed_args.block_device_mapping)
342+
block_device_mapping = {}
343+
if volume:
344+
# When booting from volume, for now assume no other mappings
345+
# This device value is likely KVM-specific
346+
block_device_mapping = {'vda': volume}
347+
else:
348+
for dev_map in parsed_args.block_device_mapping:
349+
dev_key, dev_vol = dev_map.split('=', 1)
350+
block_volume = None
351+
if dev_vol:
352+
block_volume = utils.find_resource(
353+
volume_client.volumes,
354+
dev_vol,
355+
).id
356+
block_device_mapping.update({dev_key: block_volume})
324357

325358
nics = []
326359
for nic_str in parsed_args.nic:

‎openstackclient/tests/compute/v2/test_server.py‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,16 @@ def test_server_create_minimal(self):
134134
**kwargs
135135
)
136136

137-
collist = ('addresses', 'flavor', 'id', 'image', 'name', 'properties')
138-
self.assertEqual(columns, collist)
137+
collist = ('addresses', 'flavor', 'id', 'name', 'properties')
138+
self.assertEqual(collist, columns)
139139
datalist = (
140140
'',
141141
'Large ()',
142142
compute_fakes.server_id,
143-
'graven ()',
144143
compute_fakes.server_name,
145144
'',
146145
)
147-
self.assertEqual(data, datalist)
146+
self.assertEqual(datalist, data)
148147

149148
@mock.patch('openstackclient.compute.v2.server.io.open')
150149
def test_server_create_userdata(self, mock_open):
@@ -200,17 +199,16 @@ def test_server_create_userdata(self, mock_open):
200199
**kwargs
201200
)
202201

203-
collist = ('addresses', 'flavor', 'id', 'image', 'name', 'properties')
204-
self.assertEqual(columns, collist)
202+
collist = ('addresses', 'flavor', 'id', 'name', 'properties')
203+
self.assertEqual(collist, columns)
205204
datalist = (
206205
'',
207206
'Large ()',
208207
compute_fakes.server_id,
209-
'graven ()',
210208
compute_fakes.server_name,
211209
'',
212210
)
213-
self.assertEqual(data, datalist)
211+
self.assertEqual(datalist, data)
214212

215213

216214
class TestServerDelete(TestServer):
@@ -288,14 +286,14 @@ def test_server_image_create_no_options(self):
288286
)
289287

290288
collist = ('id', 'is_public', 'name', 'owner')
291-
self.assertEqual(columns, collist)
289+
self.assertEqual(collist, columns)
292290
datalist = (
293291
image_fakes.image_id,
294292
False,
295293
image_fakes.image_name,
296294
image_fakes.image_owner,
297295
)
298-
self.assertEqual(data, datalist)
296+
self.assertEqual(datalist, data)
299297

300298
def test_server_image_create_name(self):
301299
arglist = [
@@ -318,14 +316,14 @@ def test_server_image_create_name(self):
318316
)
319317

320318
collist = ('id', 'is_public', 'name', 'owner')
321-
self.assertEqual(columns, collist)
319+
self.assertEqual(collist, columns)
322320
datalist = (
323321
image_fakes.image_id,
324322
False,
325323
image_fakes.image_name,
326324
image_fakes.image_owner,
327325
)
328-
self.assertEqual(data, datalist)
326+
self.assertEqual(datalist, data)
329327

330328

331329
class TestServerResize(TestServer):

0 commit comments

Comments
 (0)