Validate number of instance metadata entries
The Server resource arbitrarily limits instance metadata to five entries, when the actual provider's maxServerMeta limit could be much higher. Make the Server resource check the provider's maxServerMeta absolute limit and enforce that limit in validate(). Change-Id: Ic00fc6f3a41ae783e43bd7f2df8663263d9cbf90 Closes-Bug: #1260427
This commit is contained in:
parent
86edcb0ba8
commit
c772307829
@ -293,3 +293,9 @@ def server_to_ipaddress(client, server):
|
||||
for n in server.networks:
|
||||
if len(server.networks[n]) > 0:
|
||||
return server.networks[n][0]
|
||||
|
||||
|
||||
def absolute_limits(nova_client):
|
||||
"""Return the absolute limits as a dictionary."""
|
||||
limits = nova_client.limits.get()
|
||||
return dict([(limit.name, limit.value) for limit in list(limits.absolute)])
|
||||
|
@ -147,9 +147,8 @@ class Server(resource.Resource):
|
||||
'Type': 'Map',
|
||||
'UpdateAllowed': True,
|
||||
'Description': _('Arbitrary key/value metadata to store for this '
|
||||
'server. A maximum of five entries is allowed, '
|
||||
'and both keys and values must be 255 characters '
|
||||
'or less.')},
|
||||
'server. Both keys and values must be 255 '
|
||||
'characters or less.')},
|
||||
'user_data_format': {
|
||||
'Type': 'String',
|
||||
'Default': 'HEAT_CFNTOOLS',
|
||||
@ -494,6 +493,18 @@ class Server(resource.Resource):
|
||||
'') % dict(network=network['network'],
|
||||
server=self.name))
|
||||
|
||||
# verify that the number of metadata entries is not greater
|
||||
# than the maximum number allowed in the provider's absolute
|
||||
# limits
|
||||
metadata = self.properties.get('metadata')
|
||||
if metadata is not None:
|
||||
limits = nova_utils.absolute_limits(self.nova())
|
||||
if len(metadata) > limits['maxServerMeta']:
|
||||
msg = _('Instance metadata must not contain greater than %s '
|
||||
'entries. This is the maximum number allowed by your '
|
||||
'service provider') % limits['maxServerMeta']
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
def handle_delete(self):
|
||||
'''
|
||||
Delete a server, blocking until it is disposed by OpenStack
|
||||
|
@ -1156,3 +1156,57 @@ class ServersTest(HeatTestCase):
|
||||
self.assertEqual(msg, str(ex))
|
||||
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_validate_metadata_too_many(self):
|
||||
stack_name = 'srv_val_metadata'
|
||||
(t, stack) = self._setup_test_stack(stack_name)
|
||||
|
||||
t['Resources']['WebServer']['Properties']['metadata'] = {'a': 1,
|
||||
'b': 2,
|
||||
'c': 3,
|
||||
'd': 4}
|
||||
server = servers.Server('server_create_image_err',
|
||||
t['Resources']['WebServer'], stack)
|
||||
|
||||
limits = self.m.CreateMockAnything()
|
||||
max_server_meta = self.m.CreateMockAnything()
|
||||
max_server_meta.name = 'maxServerMeta'
|
||||
max_server_meta.value = 3
|
||||
limits.absolute = [max_server_meta]
|
||||
self.m.StubOutWithMock(self.fc.limits, 'get')
|
||||
self.fc.limits.get().AndReturn(limits)
|
||||
|
||||
self.m.StubOutWithMock(server, 'nova')
|
||||
server.nova().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.ReplayAll()
|
||||
|
||||
ex = self.assertRaises(exception.StackValidationFailed,
|
||||
server.validate)
|
||||
self.assertIn('Instance metadata must not contain greater than 3 '
|
||||
'entries', str(ex))
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_validate_metadata_okay(self):
|
||||
stack_name = 'srv_val_metadata'
|
||||
(t, stack) = self._setup_test_stack(stack_name)
|
||||
|
||||
t['Resources']['WebServer']['Properties']['metadata'] = {'a': 1,
|
||||
'b': 2,
|
||||
'c': 3}
|
||||
server = servers.Server('server_create_image_err',
|
||||
t['Resources']['WebServer'], stack)
|
||||
|
||||
limits = self.m.CreateMockAnything()
|
||||
max_server_meta = self.m.CreateMockAnything()
|
||||
max_server_meta.name = 'maxServerMeta'
|
||||
max_server_meta.value = 3
|
||||
limits.absolute = [max_server_meta]
|
||||
self.m.StubOutWithMock(self.fc.limits, 'get')
|
||||
self.fc.limits.get().AndReturn(limits)
|
||||
|
||||
self.m.StubOutWithMock(server, 'nova')
|
||||
server.nova().MultipleTimes().AndReturn(self.fc)
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertIsNone(server.validate())
|
||||
self.m.VerifyAll()
|
||||
|
@ -360,3 +360,9 @@ class FakeHTTPClient(base_client.HTTPClient):
|
||||
'id': '42'},
|
||||
{'label': 'foo',
|
||||
'id': '42'}]})
|
||||
|
||||
#
|
||||
# Limits
|
||||
#
|
||||
def get_limits(self, *kw):
|
||||
return (200, {'limits': {'absolute': {'maxServerMeta': 3}}})
|
||||
|
Loading…
Reference in New Issue
Block a user