Reject the cell name include '!', '.' and '@' for Nova API

Nova cells use '!', '.' and '@' for routing the instance in cells.
So those special characters can't include in the cell name.

This patch adds '@' validation for v2 API, and adds '!', '.' and '@'
for v2.1 API.

Change-Id: I5cb704a44c2abfb0bfb5b42d4aa8fefe35cc1523
Partial-Bug: #1491511
This commit is contained in:
He Jie Xu 2015-09-04 11:55:02 +08:00 committed by John Garbutt
parent bc0cc457ba
commit e5982de3e9
4 changed files with 56 additions and 33 deletions

View File

@ -187,12 +187,14 @@ class Controller(object):
return {}
def _validate_cell_name(self, cell_name):
"""Validate cell name is not empty and doesn't contain '!' or '.'."""
"""Validate cell name is not empty and doesn't contain '!',
'.' or '@'.
"""
if not cell_name:
msg = _("Cell name cannot be empty")
raise exc.HTTPBadRequest(explanation=msg)
if '!' in cell_name or '.' in cell_name:
msg = _("Cell name cannot contain '!' or '.'")
if '!' in cell_name or '.' in cell_name or '@' in cell_name:
msg = _("Cell name cannot contain '!', '.' or '@'")
raise exc.HTTPBadRequest(explanation=msg)
def _validate_cell_type(self, cell_type):

View File

@ -21,7 +21,7 @@ create = {
'cell': {
'type': 'object',
'properties': {
'name': parameter_types.name,
'name': parameter_types.cell_name,
'type': {
'type': 'string',
'enum': ['parent', 'child'],
@ -61,7 +61,7 @@ update = {
'cell': {
'type': 'object',
'properties': {
'name': parameter_types.name,
'name': parameter_types.cell_name,
'type': {
'type': 'string',
'enum': ['parent', 'child'],

View File

@ -40,6 +40,7 @@ def _get_all_chars():
for i in range(0xFFFF):
yield six.unichr(i)
# build a regex that matches all printable characters. This allows
# spaces in the middle of the name. Also note that the regexp below
# deliberately allows the empty string. This is so only the constraint
@ -47,13 +48,25 @@ def _get_all_chars():
# empty string is tested. Otherwise it is not deterministic which
# constraint fails and this causes issues for some unittests when
# PYTHONHASHSEED is set randomly.
_printable = ''.join(c for c in _get_all_chars() if _is_printable(c))
def _get_printable(exclude=None):
if exclude is None:
exclude = []
return ''.join(c for c in _get_all_chars()
if _is_printable(c) and c not in exclude)
_printable_ws = ''.join(c for c in _get_all_chars()
if unicodedata.category(c) == "Zs")
valid_name_regex = '^(?![%s])[%s]*(?<![%s])$' % (
re.escape(_printable_ws), re.escape(_printable), re.escape(_printable_ws))
re.escape(_printable_ws), re.escape(_get_printable()),
re.escape(_printable_ws))
# cell's name disallow '!', '.' and '@'.
valid_cell_name_regex = '^(?![%s])[%s]*(?<![%s])$' % (
re.escape(_printable_ws),
re.escape(_get_printable(exclude=['!', '.', '@'])),
re.escape(_printable_ws))
boolean = {
'type': ['boolean', 'string'],
@ -109,6 +122,12 @@ name = {
}
cell_name = {
'type': 'string', 'minLength': 1, 'maxLength': 255,
'pattern': valid_cell_name_regex,
}
tcp_udp_port = {
'type': ['integer', 'string'], 'pattern': '^[0-9]*$',
'minimum': 0, 'maximum': 65535,

View File

@ -286,9 +286,32 @@ class CellsTestV21(BaseCellsTest):
req = self._get_request("cells")
req.environ['nova.context'] = self.context
res_dict = self.controller.create(req, body=body)
cell = res_dict['cell']
self.assertEqual(cell['name'], 'moo.cow')
self.assertRaises(self.bad_request, self.controller.create,
req, body=body)
def test_cell_create_name_with_exclamation_point_raises(self):
body = {'cell': {'name': 'moo!cow',
'username': 'fred',
'password': 'secret',
'rpc_host': 'r3.example.org',
'type': 'parent'}}
req = self._get_request("cells")
req.environ['nova.context'] = self.context
self.assertRaises(self.bad_request, self.controller.create,
req, body=body)
def test_cell_create_name_with_at_raises(self):
body = {'cell': {'name': 'moo@cow',
'username': 'fred',
'password': 'secret',
'rpc_host': 'r3.example.org',
'type': 'parent'}}
req = self._get_request("cells")
req.environ['nova.context'] = self.context
self.assertRaises(self.bad_request, self.controller.create,
req, body=body)
def test_cell_create_name_with_invalid_type_raises(self):
body = {'cell': {'name': 'moocow',
@ -681,32 +704,11 @@ class CellsTestV2(CellsTestV21):
cell_extension = 'compute_extension:cells'
bad_request = exc.HTTPBadRequest
def test_cell_create_name_with_invalid_character_raises(self):
body = {'cell': {'name': 'moo!cow',
'username': 'fred',
'password': 'secret',
'rpc_host': 'r3.example.org',
'type': 'parent'}}
req = self._get_request("cells")
req.environ['nova.context'] = self.context
self.assertRaises(self.bad_request,
self.controller.create, req, body=body)
def _get_cell_controller(self, ext_mgr):
return cells_ext_v2.Controller(ext_mgr)
def test_cell_create_name_with_dot_raises(self):
body = {'cell': {'name': 'moo.cow',
'username': 'fred',
'password': 'secret',
'rpc_host': 'r3.example.org',
'type': 'parent'}}
req = self._get_request("cells")
req.environ['nova.context'] = self.context
self.assertRaises(exc.HTTPBadRequest,
self.controller.create, req, body=body)
def test_cell_create_name_with_invalid_character_raises(self):
pass
def test_cell_create_rpc_port_with_null(self):
body = {'cell': {'name': 'fake',