Dean Troyer 2c9d263611 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
2014-10-24 17:55:44 -05:00

458 lines
14 KiB
Python

# Copyright 2013 Nebula Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
import copy
import mock
from openstackclient.compute.v2 import server
from openstackclient.tests.compute.v2 import fakes as compute_fakes
from openstackclient.tests import fakes
from openstackclient.tests.image.v2 import fakes as image_fakes
from openstackclient.tests import utils
class TestServer(compute_fakes.TestComputev2):
def setUp(self):
super(TestServer, self).setUp()
# Get a shortcut to the ServerManager Mock
self.servers_mock = self.app.client_manager.compute.servers
self.servers_mock.reset_mock()
# Get a shortcut to the ImageManager Mock
self.cimages_mock = self.app.client_manager.compute.images
self.cimages_mock.reset_mock()
# Get a shortcut to the FlavorManager Mock
self.flavors_mock = self.app.client_manager.compute.flavors
self.flavors_mock.reset_mock()
# Get a shortcut to the ImageManager Mock
self.images_mock = self.app.client_manager.image.images
self.images_mock.reset_mock()
class TestServerCreate(TestServer):
def setUp(self):
super(TestServerCreate, self).setUp()
self.servers_mock.create.return_value = fakes.FakeResource(
None,
copy.deepcopy(compute_fakes.SERVER),
loaded=True,
)
new_server = fakes.FakeResource(
None,
copy.deepcopy(compute_fakes.SERVER),
loaded=True,
)
new_server.__dict__['networks'] = {}
self.servers_mock.get.return_value = new_server
self.image = fakes.FakeResource(
None,
copy.deepcopy(image_fakes.IMAGE),
loaded=True,
)
self.cimages_mock.get.return_value = self.image
self.flavor = fakes.FakeResource(
None,
copy.deepcopy(compute_fakes.FLAVOR),
loaded=True,
)
self.flavors_mock.get.return_value = self.flavor
# Get the command object to test
self.cmd = server.CreateServer(self.app, None)
def test_server_create_no_options(self):
arglist = [
compute_fakes.server_id,
]
verifylist = [
('server_name', compute_fakes.server_id),
]
try:
# Missing required args should bail here
self.check_parser(self.cmd, arglist, verifylist)
except utils.ParserException:
pass
def test_server_create_minimal(self):
arglist = [
'--image', 'image1',
'--flavor', 'flavor1',
compute_fakes.server_id,
]
verifylist = [
('image', 'image1'),
('flavor', 'flavor1'),
('config_drive', False),
('server_name', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
columns, data = self.cmd.take_action(parsed_args)
# Set expected values
kwargs = dict(
meta=None,
files={},
reservation_id=None,
min_count=1,
max_count=1,
security_groups=[],
userdata=None,
key_name=None,
availability_zone=None,
block_device_mapping={},
nics=[],
scheduler_hints={},
config_drive=None,
)
# ServerManager.create(name, image, flavor, **kwargs)
self.servers_mock.create.assert_called_with(
compute_fakes.server_id,
self.image,
self.flavor,
**kwargs
)
collist = ('addresses', 'flavor', 'id', 'name', 'properties')
self.assertEqual(collist, columns)
datalist = (
'',
'Large ()',
compute_fakes.server_id,
compute_fakes.server_name,
'',
)
self.assertEqual(datalist, data)
@mock.patch('openstackclient.compute.v2.server.io.open')
def test_server_create_userdata(self, mock_open):
mock_file = mock.MagicMock(name='File')
mock_open.return_value = mock_file
mock_open.read.return_value = '#!/bin/sh'
arglist = [
'--image', 'image1',
'--flavor', 'flavor1',
'--user-data', 'userdata.sh',
compute_fakes.server_id,
]
verifylist = [
('image', 'image1'),
('flavor', 'flavor1'),
('user_data', 'userdata.sh'),
('config_drive', False),
('server_name', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
columns, data = self.cmd.take_action(parsed_args)
# Ensure the userdata file is opened
mock_open.assert_called_with('userdata.sh')
# Ensure the userdata file is closed
mock_file.close.assert_called()
# Set expected values
kwargs = dict(
meta=None,
files={},
reservation_id=None,
min_count=1,
max_count=1,
security_groups=[],
userdata=mock_file,
key_name=None,
availability_zone=None,
block_device_mapping={},
nics=[],
scheduler_hints={},
config_drive=None,
)
# ServerManager.create(name, image, flavor, **kwargs)
self.servers_mock.create.assert_called_with(
compute_fakes.server_id,
self.image,
self.flavor,
**kwargs
)
collist = ('addresses', 'flavor', 'id', 'name', 'properties')
self.assertEqual(collist, columns)
datalist = (
'',
'Large ()',
compute_fakes.server_id,
compute_fakes.server_name,
'',
)
self.assertEqual(datalist, data)
class TestServerDelete(TestServer):
def setUp(self):
super(TestServerDelete, self).setUp()
# This is the return value for utils.find_resource()
self.servers_mock.get.return_value = fakes.FakeResource(
None,
copy.deepcopy(compute_fakes.SERVER),
loaded=True,
)
self.servers_mock.delete.return_value = None
# Get the command object to test
self.cmd = server.DeleteServer(self.app, None)
def test_server_delete_no_options(self):
arglist = [
compute_fakes.server_id,
]
verifylist = [
('server', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
self.cmd.take_action(parsed_args)
self.servers_mock.delete.assert_called_with(
compute_fakes.server_id,
)
class TestServerImageCreate(TestServer):
def setUp(self):
super(TestServerImageCreate, self).setUp()
# This is the return value for utils.find_resource()
self.servers_mock.get.return_value = fakes.FakeResource(
None,
copy.deepcopy(compute_fakes.SERVER),
loaded=True,
)
self.servers_mock.create_image.return_value = image_fakes.image_id
self.images_mock.get.return_value = fakes.FakeResource(
None,
copy.deepcopy(image_fakes.IMAGE),
loaded=True,
)
# Get the command object to test
self.cmd = server.CreateServerImage(self.app, None)
def test_server_image_create_no_options(self):
arglist = [
compute_fakes.server_id,
]
verifylist = [
('server', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
columns, data = self.cmd.take_action(parsed_args)
# ServerManager.create_image(server, image_name, metadata=)
self.servers_mock.create_image.assert_called_with(
self.servers_mock.get.return_value,
compute_fakes.server_name,
)
collist = ('id', 'is_public', 'name', 'owner')
self.assertEqual(collist, columns)
datalist = (
image_fakes.image_id,
False,
image_fakes.image_name,
image_fakes.image_owner,
)
self.assertEqual(datalist, data)
def test_server_image_create_name(self):
arglist = [
'--name', 'img-nam',
compute_fakes.server_id,
]
verifylist = [
('name', 'img-nam'),
('server', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
columns, data = self.cmd.take_action(parsed_args)
# ServerManager.create_image(server, image_name, metadata=)
self.servers_mock.create_image.assert_called_with(
self.servers_mock.get.return_value,
'img-nam',
)
collist = ('id', 'is_public', 'name', 'owner')
self.assertEqual(collist, columns)
datalist = (
image_fakes.image_id,
False,
image_fakes.image_name,
image_fakes.image_owner,
)
self.assertEqual(datalist, data)
class TestServerResize(TestServer):
def setUp(self):
super(TestServerResize, self).setUp()
# This is the return value for utils.find_resource()
self.servers_get_return_value = fakes.FakeResource(
None,
copy.deepcopy(compute_fakes.SERVER),
loaded=True,
)
self.servers_mock.get.return_value = self.servers_get_return_value
self.servers_mock.resize.return_value = None
self.servers_mock.confirm_resize.return_value = None
self.servers_mock.revert_resize.return_value = None
# This is the return value for utils.find_resource()
self.flavors_get_return_value = fakes.FakeResource(
None,
copy.deepcopy(compute_fakes.FLAVOR),
loaded=True,
)
self.flavors_mock.get.return_value = self.flavors_get_return_value
# Get the command object to test
self.cmd = server.ResizeServer(self.app, None)
def test_server_resize_no_options(self):
arglist = [
compute_fakes.server_id,
]
verifylist = [
('verify', False),
('revert', False),
('server', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(
compute_fakes.server_id,
)
self.assertNotCalled(self.servers_mock.resize)
self.assertNotCalled(self.servers_mock.confirm_resize)
self.assertNotCalled(self.servers_mock.revert_resize)
def test_server_resize(self):
arglist = [
'--flavor', compute_fakes.flavor_id,
compute_fakes.server_id,
]
verifylist = [
('flavor', compute_fakes.flavor_id),
('verify', False),
('revert', False),
('server', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(
compute_fakes.server_id,
)
self.flavors_mock.get.assert_called_with(
compute_fakes.flavor_id,
)
self.servers_mock.resize.assert_called_with(
self.servers_get_return_value,
self.flavors_get_return_value,
)
self.assertNotCalled(self.servers_mock.confirm_resize)
self.assertNotCalled(self.servers_mock.revert_resize)
def test_server_resize_confirm(self):
arglist = [
'--verify',
compute_fakes.server_id,
]
verifylist = [
('verify', True),
('revert', False),
('server', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(
compute_fakes.server_id,
)
self.assertNotCalled(self.servers_mock.resize)
self.servers_mock.confirm_resize.assert_called_with(
self.servers_get_return_value,
)
self.assertNotCalled(self.servers_mock.revert_resize)
def test_server_resize_revert(self):
arglist = [
'--revert',
compute_fakes.server_id,
]
verifylist = [
('verify', False),
('revert', True),
('server', compute_fakes.server_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(
compute_fakes.server_id,
)
self.assertNotCalled(self.servers_mock.resize)
self.assertNotCalled(self.servers_mock.confirm_resize)
self.servers_mock.revert_resize.assert_called_with(
self.servers_get_return_value,
)