Look for all accessible flavors by default, not just public ones

The Nova server will restrict unprivileged user accounts to just
public images, while allowing administrator accounts access to
all. The Nova client shouldn't force the flavor name lookup to
be restricted to just public images, since that breaks the ability
to the flavor name when booting an instance

Fixes bug #1327212

Change-Id: I949aec52660242249b8cba51d77bfdc1acaf31d2
This commit is contained in:
Daniel P. Berrange 2014-06-06 14:23:17 +01:00
parent a4e033292d
commit d17253b29a
6 changed files with 84 additions and 12 deletions

View File

@ -750,6 +750,9 @@ class FakeHTTPClient(base_client.HTTPClient):
def get_flavors_512_MB_Server(self, **kw):
raise exceptions.NotFound('404')
def get_flavors_128_MB_Server(self, **kw):
raise exceptions.NotFound('404')
def get_flavors_aa1(self, **kw):
# Alphanumeric flavor id are allowed.
return (

View File

@ -661,6 +661,27 @@ class ShellTest(utils.TestCase):
self.assertRaises(exceptions.InstanceInErrorState, self.run_command,
'boot --flavor 1 --image 1 some-bad-server --poll')
def test_boot_named_flavor(self):
self.run_command(["boot", "--image", "1",
"--flavor", "512 MB Server",
"--max-count", "3", "server"])
self.assert_called('GET', '/images/1', pos=0)
self.assert_called('GET', '/flavors/512 MB Server', pos=1)
self.assert_called('GET', '/flavors?is_public=None', pos=2)
self.assert_called('GET', '/flavors?is_public=None', pos=3)
self.assert_called('GET', '/flavors/2', pos=4)
self.assert_called(
'POST', '/servers',
{
'server': {
'flavorRef': '2',
'name': 'server',
'imageRef': '1',
'min_count': 1,
'max_count': 3,
}
}, pos=5)
def test_flavor_list(self):
self.run_command('flavor-list')
self.assert_called_anytime('GET', '/flavors/detail')
@ -682,6 +703,22 @@ class ShellTest(utils.TestCase):
self.run_command('flavor-show aa1')
self.assert_called_anytime('GET', '/flavors/aa1')
def test_flavor_show_by_name(self):
self.run_command(['flavor-show', '128 MB Server'])
self.assert_called('GET', '/flavors/128 MB Server', pos=0)
self.assert_called('GET', '/flavors?is_public=None', pos=1)
self.assert_called('GET', '/flavors?is_public=None', pos=2)
self.assert_called('GET', '/flavors/aa1', pos=3)
self.assert_called('GET', '/flavors/aa1/os-extra_specs', pos=4)
def test_flavor_show_by_name_priv(self):
self.run_command(['flavor-show', '512 MB Server'])
self.assert_called('GET', '/flavors/512 MB Server', pos=0)
self.assert_called('GET', '/flavors?is_public=None', pos=1)
self.assert_called('GET', '/flavors?is_public=None', pos=2)
self.assert_called('GET', '/flavors/2', pos=3)
self.assert_called('GET', '/flavors/2/os-extra_specs', pos=4)
def test_flavor_key_set(self):
self.run_command('flavor-key 1 set k1=v1')
self.assert_called('POST', '/flavors/1/os-extra_specs',

View File

@ -120,6 +120,10 @@ class FakeHTTPClient(fakes_v1_1.FakeHTTPClient):
#
get_flavors_2_flavor_access = (
fakes_v1_1.FakeHTTPClient.get_flavors_2_os_flavor_access)
get_flavors_2_flavor_extra_specs = (
fakes_v1_1.FakeHTTPClient.get_flavors_2_os_extra_specs)
get_flavors_aa1_flavor_extra_specs = (
fakes_v1_1.FakeHTTPClient.get_flavors_aa1_os_extra_specs)
#
# Images

View File

@ -558,3 +558,39 @@ class ShellTest(utils.TestCase):
def test_boot_with_poll_to_check_VM_state_error(self):
self.assertRaises(exceptions.InstanceInErrorState, self.run_command,
'boot --flavor 1 --image 1 some-bad-server --poll')
def test_boot_named_flavor(self):
self.run_command(["boot", "--image", "1",
"--flavor", "512 MB Server",
"--max-count", "3", "server"])
self.assert_called('GET', '/flavors/512 MB Server', pos=0)
self.assert_called('GET', '/flavors?is_public=None', pos=1)
self.assert_called('GET', '/flavors?is_public=None', pos=2)
self.assert_called('GET', '/flavors/2', pos=3)
self.assert_called(
'POST', '/servers',
{
'server': {
'flavor_ref': '2',
'name': 'server',
'image_ref': '1',
'os-multiple-create:min_count': 1,
'os-multiple-create:max_count': 3,
}
}, pos=4)
def test_flavor_show_by_name(self):
self.run_command(['flavor-show', '128 MB Server'])
self.assert_called('GET', '/flavors/128 MB Server', pos=0)
self.assert_called('GET', '/flavors?is_public=None', pos=1)
self.assert_called('GET', '/flavors?is_public=None', pos=2)
self.assert_called('GET', '/flavors/aa1', pos=3)
self.assert_called('GET', '/flavors/aa1/flavor-extra-specs', pos=4)
def test_flavor_show_by_name_priv(self):
self.run_command(['flavor-show', '512 MB Server'])
self.assert_called('GET', '/flavors/512 MB Server', pos=0)
self.assert_called('GET', '/flavors?is_public=None', pos=1)
self.assert_called('GET', '/flavors?is_public=None', pos=2)
self.assert_called('GET', '/flavors/2', pos=3)
self.assert_called('GET', '/flavors/2/flavor-extra-specs', pos=4)

View File

@ -733,7 +733,7 @@ def do_flavor_access_list(cs, args):
help=_('Tenant ID to add flavor access for.'))
def do_flavor_access_add(cs, args):
"""Add flavor access for the given tenant."""
flavor = _find_flavor_for_admin(cs, args.flavor)
flavor = _find_flavor(cs, args.flavor)
access_list = cs.flavor_access.add_tenant_access(flavor, args.tenant)
columns = ['Flavor_ID', 'Tenant_ID']
utils.print_list(access_list, columns)
@ -746,7 +746,7 @@ def do_flavor_access_add(cs, args):
help=_('Tenant ID to remove flavor access for.'))
def do_flavor_access_remove(cs, args):
"""Remove flavor access for the given tenant."""
flavor = _find_flavor_for_admin(cs, args.flavor)
flavor = _find_flavor(cs, args.flavor)
access_list = cs.flavor_access.remove_tenant_access(flavor, args.tenant)
columns = ['Flavor_ID', 'Tenant_ID']
utils.print_list(access_list, columns)
@ -1578,18 +1578,10 @@ def _find_image(cs, image):
return utils.find_resource(cs.images, image)
def _find_flavor_for_admin(cs, flavor):
"""Get a flavor for administrator by name, ID, or RAM size."""
try:
return utils.find_resource(cs.flavors, flavor, is_public=None)
except exceptions.NotFound:
return cs.flavors.find(ram=flavor)
def _find_flavor(cs, flavor):
"""Get a flavor by name, ID, or RAM size."""
try:
return utils.find_resource(cs.flavors, flavor)
return utils.find_resource(cs.flavors, flavor, is_public=None)
except exceptions.NotFound:
return cs.flavors.find(ram=flavor)

View File

@ -1395,7 +1395,7 @@ def _find_image(cs, image):
def _find_flavor(cs, flavor):
"""Get a flavor by name, ID, or RAM size."""
try:
return utils.find_resource(cs.flavors, flavor)
return utils.find_resource(cs.flavors, flavor, is_public=None)
except exceptions.NotFound:
return cs.flavors.find(ram=flavor)