Ignore image and flavor validations
Ignore image and flavor validations, if they are not yet created. This would happen in cases where user with sufficient privileges have them in the same template with server. Change-Id: I3450e85ee85fd40d96bc7d0506db6a2417ffec09 Closes-Bug: #1556317
This commit is contained in:
parent
575af8dfcb
commit
eb56cbc8a1
|
@ -1280,6 +1280,42 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
|||
|
||||
return bootable_vol
|
||||
|
||||
def _validate_image_flavor(self, image, flavor):
|
||||
try:
|
||||
image_obj = self.client_plugin('glance').get_image(image)
|
||||
flavor_obj = self.client_plugin().get_flavor(flavor)
|
||||
except Exception as ex:
|
||||
# Flavor or image may not have been created in the backend
|
||||
# yet when they are part of the same stack/template.
|
||||
if (self.client_plugin().is_not_found(ex) or
|
||||
self.client_plugin('glance').is_not_found(ex)):
|
||||
return
|
||||
raise
|
||||
else:
|
||||
if image_obj.status.lower() != self.IMAGE_STATUS_ACTIVE:
|
||||
msg = _('Image status is required to be %(cstatus)s not '
|
||||
'%(wstatus)s.') % {
|
||||
'cstatus': self.IMAGE_STATUS_ACTIVE,
|
||||
'wstatus': image_obj.status}
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
# validate image/flavor combination
|
||||
if flavor_obj.ram < image_obj.min_ram:
|
||||
msg = _('Image %(image)s requires %(imram)s minimum ram. '
|
||||
'Flavor %(flavor)s has only %(flram)s.') % {
|
||||
'image': image, 'imram': image_obj.min_ram,
|
||||
'flavor': flavor, 'flram': flavor_obj.ram}
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
# validate image/flavor disk compatibility
|
||||
if flavor_obj.disk < image_obj.min_disk:
|
||||
msg = _('Image %(image)s requires %(imsz)s GB minimum '
|
||||
'disk space. Flavor %(flavor)s has only '
|
||||
'%(flsz)s GB.') % {
|
||||
'image': image, 'imsz': image_obj.min_disk,
|
||||
'flavor': flavor, 'flsz': flavor_obj.disk}
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
def validate(self):
|
||||
"""Validate any of the provided params."""
|
||||
super(Server, self).validate()
|
||||
|
@ -1299,35 +1335,9 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
|||
' instance %s') % self.name
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
flavor = self.properties[self.FLAVOR]
|
||||
if image:
|
||||
image_obj = self.client_plugin('glance').get_image(image)
|
||||
|
||||
# validate image status
|
||||
if image_obj.status.lower() != self.IMAGE_STATUS_ACTIVE:
|
||||
msg = _('Image status is required to be %(cstatus)s not '
|
||||
'%(wstatus)s.') % {
|
||||
'cstatus': self.IMAGE_STATUS_ACTIVE,
|
||||
'wstatus': image_obj.status}
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
# validate image/flavor combination
|
||||
flavor = self.properties[self.FLAVOR]
|
||||
flavor_obj = self.client_plugin().get_flavor(flavor)
|
||||
if flavor_obj.ram < image_obj.min_ram:
|
||||
msg = _('Image %(image)s requires %(imram)s minimum ram. '
|
||||
'Flavor %(flavor)s has only %(flram)s.') % {
|
||||
'image': image, 'imram': image_obj.min_ram,
|
||||
'flavor': flavor, 'flram': flavor_obj.ram}
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
|
||||
# validate image/flavor disk compatibility
|
||||
if flavor_obj.disk < image_obj.min_disk:
|
||||
msg = _('Image %(image)s requires %(imsz)s GB minimum '
|
||||
'disk space. Flavor %(flavor)s has only '
|
||||
'%(flsz)s GB.') % {
|
||||
'image': image, 'imsz': image_obj.min_disk,
|
||||
'flavor': flavor, 'flsz': flavor_obj.disk}
|
||||
raise exception.StackValidationFailed(message=msg)
|
||||
self._validate_image_flavor(image, flavor)
|
||||
|
||||
# network properties 'uuid' and 'network' shouldn't be used
|
||||
# both at once for all networks
|
||||
|
|
|
@ -2900,6 +2900,38 @@ class ServersTest(common.HeatTestCase):
|
|||
six.text_type(error))
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_validate_image_flavor_not_found(self):
|
||||
stack_name = 'test_stack'
|
||||
tmpl, stack = self._setup_test_stack(stack_name)
|
||||
|
||||
resource_defns = tmpl.resource_definitions(stack)
|
||||
server = servers.Server('image_not_found',
|
||||
resource_defns['WebServer'], stack)
|
||||
|
||||
self._server_validate_mock(server)
|
||||
image = tmpl['Resources']['WebServer']['Properties']['image']
|
||||
flavor = tmpl['Resources']['WebServer']['Properties']['flavor']
|
||||
|
||||
self.m.StubOutWithMock(glance.GlanceClientPlugin, 'get_image')
|
||||
self.m.StubOutWithMock(nova.NovaClientPlugin, 'get_flavor')
|
||||
|
||||
self.stub_FlavorConstraint_validate()
|
||||
# Image not found
|
||||
glance.GlanceClientPlugin.get_image(
|
||||
image).AndRaise(glance.exceptions.NotFound())
|
||||
|
||||
# Flavor not found
|
||||
glance.GlanceClientPlugin.get_image(
|
||||
image).AndReturn(self.mock_image)
|
||||
nova.NovaClientPlugin.get_flavor(
|
||||
flavor).AndRaise(fakes_nova.fake_exception())
|
||||
self.m.ReplayAll()
|
||||
|
||||
self.assertIsNone(server.validate())
|
||||
|
||||
self.assertIsNone(server.validate())
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_validate_insufficient_disk_flavor(self):
|
||||
stack_name = 'test_stack'
|
||||
tmpl, stack = self._setup_test_stack(stack_name)
|
||||
|
|
Loading…
Reference in New Issue