Add nullable flag to NIC's mtu attribute

Partial-Bug: #1643599

Change-Id: I8cd2b972c4be053ebbcb0cc788c1ee0384120374
(cherry picked from commit b82e6e5aff)
This commit is contained in:
Julia Aranovich 2016-12-20 13:35:40 +03:00
parent 711a4aa7d7
commit 5fd05b30e8
9 changed files with 143 additions and 30 deletions

View File

@ -321,7 +321,10 @@ ATTRIBUTE_TYPE_SCHEMAS = {
'password': {'value': {'type': 'string'}},
'radio': ALLOWED_VALUES_SCHEMA,
'select': ALLOWED_VALUES_SCHEMA,
'text': {'value': {'type': 'string'}},
'text': {
'value': NULLABLE_STRING,
'nullable': {'type': 'boolean'}
},
'textarea': {'value': {'type': 'string'}},
'text_list': MULTIPLE_TEXT_FIELDS_SCHEMA,
'textarea_list': MULTIPLE_TEXT_FIELDS_SCHEMA,
@ -334,5 +337,8 @@ ATTRIBUTE_TYPE_SCHEMAS = {
}
}
},
'number': {'value': NON_NEGATIVE_INTEGER},
'number': {
'value': NULLABLE_NON_NEGATIVE_INTEGER,
'nullable': {'type': 'boolean'}
},
}

View File

@ -182,7 +182,7 @@ DEFAULT_RELEASE_NIC_ATTRIBUTES = {
},
'mtu': {
'value': {'type': 'number', 'value': None, 'weight': 10,
'label': 'MTU'},
'label': 'Use Custom MTU', 'nullable': True},
'metadata': {'weight': 20, 'label': 'MTU'}
},
'sriov': {
@ -223,7 +223,7 @@ DEFAULT_RELEASE_BOND_ATTRIBUTES = {
},
'mtu': {
'value': {'type': 'number', 'weight': 10, 'value': None,
'label': 'MTU'},
'label': 'Use Custom MTU', 'nullable': True},
'metadata': {'weight': 30, 'label': 'MTU'}
},
'lacp': {

View File

@ -651,9 +651,10 @@ class TestHandlers(BaseIntegrationTest):
'weight': 20
},
'value': {
'label': 'MTU',
'label': 'Use Custom MTU',
'weight': 10,
'type': 'number',
'nullable': True,
'value': 1500,
'min': 42,
'max': 65536
@ -684,9 +685,10 @@ class TestHandlers(BaseIntegrationTest):
'weight': 20
},
'value': {
'label': 'MTU',
'label': 'Use Custom MTU',
'weight': 10,
'type': 'number',
'nullable': True,
'value': 1500,
'min': 42,
'max': 65536
@ -1219,8 +1221,9 @@ class TestNICAttributesHandlers(BaseIntegrationTest):
'mtu': {
'value': {
'value': None,
'label': 'MTU',
'label': 'Use Custom MTU',
'type': 'number',
'nullable': True,
'weight': 10,
'min': 42,
'max': 65536

View File

@ -897,8 +897,9 @@ class TestBondAttributesDefaultsHandler(BaseIntegrationTest):
'value': {
'weight': 10,
'type': 'number',
'nullable': True,
'value': None,
'label': 'MTU',
'label': 'Use Custom MTU',
'min': 42,
'max': 65536
}

View File

@ -2124,9 +2124,10 @@
label: "MTU"
weight: 20
value:
label: "MTU"
label: "Use Custom MTU"
weight: 10
type: "number"
nullable: True
value: null
min: 42
max: 65536
@ -2209,9 +2210,10 @@
label: "MTU"
weight: 30
value:
label: "MTU"
label: "Use Custom MTU"
weight: 10
type: "number"
nullable: True
value: null
min: 42
max: 65536

View File

@ -335,6 +335,40 @@ class TestBasicAttributesValidator(base_test.BaseTestCase):
base.BasicAttributesValidator.validate_attributes,
attrs)
attrs = {
'storage': {
'osd_pool_size': {
'description': 'desc',
'label': 'OSD Pool Size',
'type': 'text',
'nullable': True,
'value': '2',
'weight': 80
}
}
}
self.assertNotRaises(
errors.InvalidData,
base.BasicAttributesValidator.validate_attributes,
attrs)
attrs = {
'storage': {
'osd_pool_size': {
'description': 'desc',
'label': 'OSD Pool Size',
'type': 'text',
'nullable': True,
'value': None,
'weight': 80
}
}
}
self.assertNotRaises(
errors.InvalidData,
base.BasicAttributesValidator.validate_attributes,
attrs)
def test_textarea_value(self):
attrs = {
'storage': {
@ -492,6 +526,42 @@ class TestBasicAttributesValidator(base_test.BaseTestCase):
base.BasicAttributesValidator.validate_attributes,
attrs)
attrs = {
'cpu_pinning': {
'nova': {
'description': 'desc',
'label': 'Label',
'type': 'number',
'nullable': True,
'value': 1,
'min': 0,
'weight': 10
}
}
}
self.assertNotRaises(
errors.InvalidData,
base.BasicAttributesValidator.validate_attributes,
attrs)
attrs = {
'cpu_pinning': {
'nova': {
'description': 'desc',
'label': 'Label',
'type': 'number',
'nullable': True,
'value': None,
'min': 0,
'weight': 10
}
}
}
self.assertNotRaises(
errors.InvalidData,
base.BasicAttributesValidator.validate_attributes,
attrs)
def test_restriction_strict(self):
context = {'context': {'existing': {'value': 13}}}

View File

@ -117,7 +117,7 @@ DEFAULT_NIC_ATTRIBUTES = {
},
'mtu': {
'value': {'type': 'number', 'value': None, 'weight': 10,
'label': 'MTU'},
'label': 'Use Custom MTU', 'nullable': True},
'metadata': {'weight': 20, 'label': 'MTU'}
},
'sriov': {
@ -158,7 +158,7 @@ DEFAULT_BOND_ATTRIBUTES = {
},
'mtu': {
'value': {'type': 'number', 'weight': 10, 'value': None,
'label': 'MTU'},
'label': 'Use Custom MTU', 'nullable': True},
'metadata': {'weight': 30, 'label': 'MTU'}
},
'lacp': {

View File

@ -273,6 +273,27 @@ class TestAttributesRestriction(base.BaseTestCase):
regex:
source: '\S'
error: "Empty password"
nullable_text:
label: "Nullable text"
value: null
nullable: True
type: "text"
regex:
source: '\S'
error: "Empty value"
not_nullable_text:
label: "Not nullable text"
value: null
type: "text"
nullable_number:
label: "Nullable number"
value: null
nullable: True
type: "number"
not_nullable_number:
label: "Not nullable number"
value: null
type: "number"
"""
self.attributes_data = yaml.load(attributes_metadata)
@ -290,7 +311,9 @@ class TestAttributesRestriction(base.BaseTestCase):
errs, ['Invalid username', ['Invalid tenant name'],
"Value ['test'] should have at least 2 items",
"Value ['test1', 'test2', 'test3'] "
"should not have more than 2 items"])
"should not have more than 2 items",
"Null value is forbidden for 'Not nullable text'",
"Null value is forbidden for 'Not nullable number'"])
def test_check_with_valid_values(self):
access = self.attributes_data['editable']['access']
@ -298,6 +321,8 @@ class TestAttributesRestriction(base.BaseTestCase):
access['tenant']['value'] = ['test']
access['another_tenant']['value'] = ['test1', 'test2']
access['another_tenant_2']['value'] = ['test1', 'test2']
access['not_nullable_text']['value'] = 'test'
access['not_nullable_number']['value'] = 123
objects.Cluster.update_attributes(
self.cluster, self.attributes_data)

View File

@ -337,6 +337,11 @@ class AttributesRestriction(RestrictionBase):
models, restrictions, action='disable')['result']:
return
if attr_type in ['text', 'number']:
if not data.get('nullable', False) and value is None:
yield ("Null value is forbidden for '{}'"
.format(label))
if attr_type in ['text_list', 'textarea_list']:
err = cls.check_fields_length(data)
if err is not None:
@ -356,25 +361,26 @@ class AttributesRestriction(RestrictionBase):
@staticmethod
def validate_regex(data):
attr_regex = data.get('regex', {})
if attr_regex:
attr_value = data.get('value')
pattern = re.compile(attr_regex.get('source'))
error = attr_regex.get('error')
attr_value = data.get('value')
if attr_value is not None:
attr_regex = data.get('regex', {})
if attr_regex:
pattern = re.compile(attr_regex.get('source'))
error = attr_regex.get('error')
def test_regex(value, pattern=pattern, error=error):
if not pattern.search(value):
return error
def test_regex(value, pattern=pattern, error=error):
if not pattern.search(value):
return error
if isinstance(attr_value, six.string_types):
return test_regex(attr_value)
elif isinstance(attr_value, list):
errors = map(test_regex, attr_value)
if compact(errors):
return errors
else:
return ('Value {0} is of invalid type, cannot check '
'regexp'.format(attr_value))
if isinstance(attr_value, six.string_types):
return test_regex(attr_value)
elif isinstance(attr_value, list):
errors = map(test_regex, attr_value)
if compact(errors):
return errors
else:
return ('Value {0} is of invalid type, cannot check '
'regexp'.format(attr_value))
@staticmethod
def check_fields_length(data):