Check tenant_id's format in "nova quota-update"

Fix bug 1088835
"nova quota-update" command is executed without checking the format of
the tenant_id argument. The tenant_id should be in the format of UUID.
The tenant_id of quotas should be in accord with the form of keystone's
tenant_id. So this patch checks the format of the tenant_id when "nova
quota-update" command is executed.

Change-Id: I47c4f2ff9adbab5da4697270dcf024ac88e24529
This commit is contained in:
Haiwei Xu 2012-12-26 11:24:55 +00:00
parent 5b8099cd0e
commit 168636e744
5 changed files with 110 additions and 8 deletions

View File

@ -289,3 +289,16 @@ def slugify(value):
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
value = unicode(_slugify_strip_re.sub('', value).strip().lower()) value = unicode(_slugify_strip_re.sub('', value).strip().lower())
return _slugify_hyphenate_re.sub('-', value) return _slugify_hyphenate_re.sub('-', value)
def is_uuid_like(val):
"""
The UUID which doesn't contain hyphens or 'A-F' is allowed.
"""
try:
if uuid.UUID(val) and val.isalnum() and val.islower():
return True
else:
return False
except (TypeError, ValueError, AttributeError):
return False

View File

@ -2532,6 +2532,10 @@ def _quota_show(quotas):
def _quota_update(manager, identifier, args): def _quota_update(manager, identifier, args):
updates = {} updates = {}
if not utils.is_uuid_like(identifier):
raise exceptions.CommandError(
"error: Invalid tenant-id %s supplied for update"
% identifier)
for resource in _quota_resources: for resource in _quota_resources:
val = getattr(args, resource, None) val = getattr(args, resource, None)
if val is not None: if val is not None:

View File

@ -863,6 +863,57 @@ class FakeHTTPClient(base_client.HTTPClient):
'security_groups': 1, 'security_groups': 1,
'security_group_rules': 1}}) 'security_group_rules': 1}})
def get_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, **kw):
return (200, {}, {'quota_set': {
'tenant_id': '97f4c221bff44578b0300df4ef119353',
'metadata_items': [],
'injected_file_content_bytes': 1,
'injected_file_path_bytes': 1,
'volumes': 1,
'gigabytes': 1,
'ram': 1,
'floating_ips': 1,
'instances': 1,
'injected_files': 1,
'cores': 1,
'keypairs': 1,
'security_groups': 1,
'security_group_rules': 1}})
def put_os_quota_sets_97f4c221_bff4_4578_b030_0df4ef119353(self, **kw):
return (200, {}, {'quota_set': {
'tenant_id': '97f4c221-bff4-4578-b030-0df4ef119353',
'metadata_items': [],
'injected_file_content_bytes': 1,
'injected_file_path_bytes': 1,
'volumes': 1,
'gigabytes': 1,
'ram': 1,
'floating_ips': 1,
'instances': 1,
'injected_files': 1,
'cores': 1,
'keypairs': 1,
'security_groups': 1,
'security_group_rules': 1}})
def get_os_quota_sets_97f4c221_bff4_4578_b030_0df4ef119353(self, **kw):
return (200, {}, {'quota_set': {
'tenant_id': '97f4c221-bff4-4578-b030-0df4ef119353',
'metadata_items': [],
'injected_file_content_bytes': 1,
'injected_file_path_bytes': 1,
'volumes': 1,
'gigabytes': 1,
'ram': 1,
'floating_ips': 1,
'instances': 1,
'injected_files': 1,
'cores': 1,
'keypairs': 1,
'security_groups': 1,
'security_group_rules': 1}})
def get_os_quota_sets_test_defaults(self): def get_os_quota_sets_test_defaults(self):
return (200, {}, {'quota_set': { return (200, {}, {'quota_set': {
'tenant_id': 'test', 'tenant_id': 'test',
@ -880,12 +931,12 @@ class FakeHTTPClient(base_client.HTTPClient):
'security_groups': 1, 'security_groups': 1,
'security_group_rules': 1}}) 'security_group_rules': 1}})
def put_os_quota_sets_test(self, body, **kw): def put_os_quota_sets_97f4c221bff44578b0300df4ef119353(self, body, **kw):
assert body.keys() == ['quota_set'] assert body.keys() == ['quota_set']
fakes.assert_has_keys(body['quota_set'], fakes.assert_has_keys(body['quota_set'],
required=['tenant_id']) required=['tenant_id'])
return (200, {}, {'quota_set': { return (200, {}, {'quota_set': {
'tenant_id': 'test', 'tenant_id': '97f4c221bff44578b0300df4ef119353',
'metadata_items': [], 'metadata_items': [],
'injected_file_content_bytes': 1, 'injected_file_content_bytes': 1,
'injected_file_path_bytes': 1, 'injected_file_path_bytes': 1,
@ -941,6 +992,27 @@ class FakeHTTPClient(base_client.HTTPClient):
'security_groups': 1, 'security_groups': 1,
'security_group_rules': 1}}) 'security_group_rules': 1}})
def put_os_quota_class_sets_97f4c221bff44578b0300df4ef119353(self,
body, **kw):
assert body.keys() == ['quota_class_set']
fakes.assert_has_keys(body['quota_class_set'],
required=['class_name'])
return (200, {}, {'quota_class_set': {
'class_name': '97f4c221bff44578b0300df4ef119353',
'metadata_items': [],
'injected_file_content_bytes': 1,
'injected_file_path_bytes': 1,
'volumes': 2,
'gigabytes': 1,
'ram': 1,
'floating_ips': 1,
'instances': 1,
'injected_files': 1,
'cores': 1,
'keypairs': 1,
'security_groups': 1,
'security_group_rules': 1}})
# #
# Security Groups # Security Groups
# #

View File

@ -16,6 +16,7 @@
from tests import utils from tests import utils
from tests.v1_1 import fakes from tests.v1_1 import fakes
from novaclient import exceptions
cs = fakes.FakeClient() cs = fakes.FakeClient()
@ -33,9 +34,10 @@ class QuotaSetsTest(utils.TestCase):
cs.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id) cs.assert_called('GET', '/os-quota-sets/%s/defaults' % tenant_id)
def test_update_quota(self): def test_update_quota(self):
q = cs.quotas.get('test') q = cs.quotas.get('97f4c221bff44578b0300df4ef119353')
q.update(volumes=2) q.update(volumes=2)
cs.assert_called('PUT', '/os-quota-sets/test') cs.assert_called('PUT',
'/os-quota-sets/97f4c221bff44578b0300df4ef119353')
def test_refresh_quota(self): def test_refresh_quota(self):
q = cs.quotas.get('test') q = cs.quotas.get('test')

View File

@ -702,16 +702,27 @@ class ShellTest(utils.TestCase):
self.assert_called('GET', '/os-quota-sets/test/defaults') self.assert_called('GET', '/os-quota-sets/test/defaults')
def test_quota_update(self): def test_quota_update(self):
self.run_command('quota-update test --instances=5') self.run_command(
self.assert_called('PUT', '/os-quota-sets/test') 'quota-update 97f4c221bff44578b0300df4ef119353 \
--instances=5')
self.assert_called('PUT',
'/os-quota-sets/97f4c221bff44578b0300df4ef119353')
def test_quota_update_error(self):
self.assertRaises(exceptions.CommandError,
self.run_command,
'quota-update 7f4c221-bff4-4578-b030-0df4ef119353 \
--instances=5')
def test_quota_class_show(self): def test_quota_class_show(self):
self.run_command('quota-class-show test') self.run_command('quota-class-show test')
self.assert_called('GET', '/os-quota-class-sets/test') self.assert_called('GET', '/os-quota-class-sets/test')
def test_quota_class_update(self): def test_quota_class_update(self):
self.run_command('quota-class-update test --instances=5') self.run_command('quota-class-update 97f4c221bff44578b0300df4ef119353 \
self.assert_called('PUT', '/os-quota-class-sets/test') --instances=5')
self.assert_called('PUT',
'/os-quota-class-sets/97f4c221bff44578b0300df4ef119353')
def test_network_list(self): def test_network_list(self):
self.run_command('network-list') self.run_command('network-list')