Add nullable flag to NIC's mtu attribute
Partial-Bug: #1643599
Change-Id: I8cd2b972c4be053ebbcb0cc788c1ee0384120374
(cherry picked from commit b82e6e5aff
)
This commit is contained in:
parent
711a4aa7d7
commit
5fd05b30e8
@ -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'}
|
||||
},
|
||||
}
|
||||
|
@ -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': {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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}}}
|
||||
|
||||
|
@ -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': {
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user