Validate image when create a Bay

For good user experience, we should validate Baymodel's image
in Bay creation. The following 3 conditions will be checked:
1. Image not existed - 404 Not Found
2. Found multiple images with same image name - 409 Conflict
3. Image 'os_distro' field is None or empty string - 404 Not Found

Patially-Implements: blueprint api-parameter-validation

Change-Id: I54a75c005cd7dbf406e6dd31a2f27e8e46c0612c
This commit is contained in:
houming-wang 2015-11-30 10:09:48 -05:00
parent 743ff7526e
commit 3d3eaa1269
3 changed files with 106 additions and 3 deletions

View File

@ -12,9 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from glanceclient import exc as glance_exception
from novaclient import exceptions as nova_exception
import six
from magnum.api import utils as api_utils
from magnum.common import clients
from magnum.common import exception
from magnum.objects.baymodel import BayModel
@ -23,9 +25,16 @@ from magnum.objects.baymodel import BayModel
def validate_image(cli, image):
"""Validate image"""
# TODO(houming):this method implement will be added after this
# first pathch for bay's OpenStack resources validation is merged.
pass
try:
image_found = api_utils.get_openstack_resource(cli.glance().images,
image, 'images')
except (glance_exception.NotFound, exception.ResourceNotFound):
raise exception.ImageNotFound(image_id=image)
except glance_exception.HTTPForbidden:
raise exception.ImageNotAuthorized(image_id=image)
if not image_found.get('os_distro'):
raise exception.OSDistroFieldNotFound(image_id=image)
return image_found
def validate_flavor(cli, flavor):

View File

@ -604,6 +604,33 @@ class TestPost(api_base.FunctionalTest):
self.assertTrue(mock_valid_os_res.called)
self.assertEqual(404, response.status_int)
@mock.patch('magnum.api.attr_validator.validate_os_resources')
def test_create_bay_with_nonexist_image(self, mock_valid_os_res):
bdict = apiutils.bay_post_data()
mock_valid_os_res.side_effect = exception.ImageNotFound('test-img')
response = self.post_json('/bays', bdict, expect_errors=True)
self.assertEqual('application/json', response.content_type)
self.assertTrue(mock_valid_os_res.called)
self.assertEqual(404, response.status_int)
@mock.patch('magnum.api.attr_validator.validate_os_resources')
def test_create_bay_with_multi_images_same_name(self, mock_valid_os_res):
bdict = apiutils.bay_post_data()
mock_valid_os_res.side_effect = exception.Conflict('test-img')
response = self.post_json('/bays', bdict, expect_errors=True)
self.assertEqual('application/json', response.content_type)
self.assertTrue(mock_valid_os_res.called)
self.assertEqual(409, response.status_int)
@mock.patch('magnum.api.attr_validator.validate_os_resources')
def test_create_bay_with_on_os_distro_image(self, mock_valid_os_res):
bdict = apiutils.bay_post_data()
mock_valid_os_res.side_effect = exception.OSDistroFieldNotFound('img')
response = self.post_json('/bays', bdict, expect_errors=True)
self.assertEqual('application/json', response.content_type)
self.assertTrue(mock_valid_os_res.called)
self.assertEqual(404, response.status_int)
class TestDelete(api_base.FunctionalTest):

View File

@ -13,6 +13,7 @@
# under the License.
from glanceclient import exc as glance_exception
import mock
from novaclient import exceptions as nova_exc
@ -87,6 +88,72 @@ class TestAttrValidator(base.BaseTestCase):
attr_validator.validate_keypair,
mock_os_cli, 'test_keypair')
@mock.patch('magnum.api.utils.get_openstack_resource')
def test_validate_image_with_valid_image_by_name(self, mock_os_res):
mock_image = {'name': 'fedora-21-atomic-5',
'id': 'e33f0988-1730-405e-8401-30cbc8535302',
'os_distro': 'fedora-atomic'}
mock_os_res.return_value = mock_image
mock_os_cli = mock.MagicMock()
attr_validator.validate_image(mock_os_cli, 'fedora-21-atomic-5')
self.assertTrue(mock_os_res.called)
@mock.patch('magnum.api.utils.get_openstack_resource')
def test_validate_image_with_valid_image_by_id(self, mock_os_res):
mock_image = {'name': 'fedora-21-atomic-5',
'id': 'e33f0988-1730-405e-8401-30cbc8535302',
'os_distro': 'fedora-atomic'}
mock_os_res.return_value = mock_image
mock_os_cli = mock.MagicMock()
attr_validator.validate_image(mock_os_cli,
'e33f0988-1730-405e-8401-30cbc8535302')
self.assertTrue(mock_os_res.called)
@mock.patch('magnum.api.utils.get_openstack_resource')
def test_validate_image_with_nonexist_image_by_name(self, mock_os_res):
mock_os_res.side_effect = exception.ResourceNotFound
mock_os_cli = mock.MagicMock()
self.assertRaises(exception.ImageNotFound,
attr_validator.validate_image,
mock_os_cli, 'fedora-21-atomic-5')
@mock.patch('magnum.api.utils.get_openstack_resource')
def test_validate_image_with_nonexist_image_by_id(self, mock_os_res):
mock_os_res.side_effect = glance_exception.NotFound
mock_os_cli = mock.MagicMock()
self.assertRaises(exception.ImageNotFound,
attr_validator.validate_image,
mock_os_cli, 'fedora-21-atomic-5')
@mock.patch('magnum.api.utils.get_openstack_resource')
def test_validate_image_with_multi_images_same_name(self, mock_os_res):
mock_os_res.side_effect = exception.Conflict
mock_os_cli = mock.MagicMock()
self.assertRaises(exception.Conflict,
attr_validator.validate_image,
mock_os_cli, 'fedora-21-atomic-5')
@mock.patch('magnum.api.utils.get_openstack_resource')
def test_validate_image_without_os_distro(self, mock_os_res):
mock_image = {'name': 'fedora-21-atomic-5',
'id': 'e33f0988-1730-405e-8401-30cbc8535302'}
mock_os_res.return_value = mock_image
mock_os_cli = mock.MagicMock()
self.assertRaises(exception.OSDistroFieldNotFound,
attr_validator.validate_image,
mock_os_cli, 'fedora-21-atomic-5')
@mock.patch('magnum.api.utils.get_openstack_resource')
def test_validate_image_with_empty_os_distro(self, mock_os_res):
mock_image = {'name': 'fedora-21-atomic-5',
'id': 'e33f0988-1730-405e-8401-30cbc8535302',
'os_distro': ''}
mock_os_res.return_value = mock_image
mock_os_cli = mock.MagicMock()
self.assertRaises(exception.OSDistroFieldNotFound,
attr_validator.validate_image,
mock_os_cli, 'fedora-21-atomic-5')
@mock.patch('magnum.objects.baymodel.BayModel.get_by_uuid')
@mock.patch('magnum.common.clients.OpenStackClients')
def test_validate_os_resources_with_invalid_flavor(self,