| ######### |
| # Copyright (c) 2014 GigaSpaces Technologies Ltd. All rights reserved |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # * See the License for the specific language governing permissions and |
| # * limitations under the License. |
| |
| import mock |
| import os |
| import tempfile |
| import unittest |
| |
| import glance_plugin |
| from glance_plugin import image |
| |
| from cloudify.mocks import MockCloudifyContext |
| from cloudify.test_utils import workflow_test |
| from cloudify.exceptions import NonRecoverableError |
| |
| |
| def ctx_mock(image_dict): |
| return MockCloudifyContext( |
| node_id='d', |
| properties=image_dict) |
| |
| |
| class TestCheckImage(unittest.TestCase): |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image': {}})) |
| def test_check_image_no_file_no_url(self): |
| # Test if it throws exception no file & no url |
| self.assertRaises(NonRecoverableError, |
| image._validate_image) |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image_url': 'test-url', 'image': {'data': '.'}})) |
| def test_check_image_and_url(self): |
| # Test if it throws exception file & url |
| self.assertRaises(NonRecoverableError, |
| image._validate_image) |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image_url': 'test-url', 'image': {}})) |
| def test_check_image_url(self): |
| # test if it passes no file & url |
| http_connection_mock = mock.MagicMock() |
| http_connection_mock.return_value.getresponse.return_value.status = 200 |
| with mock.patch('httplib.HTTPConnection', http_connection_mock): |
| glance_plugin.image._validate_image() |
| |
| def test_check_image_file(self): |
| # test if it passes file & no url |
| image_file_path = tempfile.mkstemp()[1] |
| with mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image': {'data': image_file_path}})): |
| glance_plugin.image._validate_image() |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image': {'data': '/test/path'}})) |
| # test when open file throws IO error |
| def test_check_image_bad_file(self): |
| open_name = '%s.open' % __name__ |
| with mock.patch(open_name, create=True) as mock_open: |
| mock_open.side_effect = [mock_open(read_data='Data').return_value] |
| self.assertRaises(NonRecoverableError, |
| glance_plugin.image._validate_image) |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image_url': '?', 'image': {}})) |
| # test when bad url |
| def test_check_image_bad_url(self): |
| http_connection_mock = mock.MagicMock() |
| http_connection_mock.return_value.getresponse.return_value.status = 400 |
| with mock.patch('httplib.HTTPConnection', http_connection_mock): |
| self.assertRaises(NonRecoverableError, |
| glance_plugin.image._validate_image) |
| |
| |
| class TestValidateProperties(unittest.TestCase): |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image': {'container_format': 'bare'}})) |
| def test_check_image_container_format_no_disk_format(self): |
| # Test if it throws exception no file & no url |
| self.assertRaises(NonRecoverableError, |
| image._validate_image_dictionary) |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image': {'disk_format': 'qcow2'}})) |
| def test_check_image_no_container_format_disk_format(self): |
| # Test if it throws exception no container_format & disk_format |
| self.assertRaises(NonRecoverableError, |
| image._validate_image_dictionary) |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock({'image': {}})) |
| def test_check_image_no_container_format_no_disk_format(self): |
| # Test if it throws exception no container_format & no disk_format |
| self.assertRaises(NonRecoverableError, |
| image._validate_image_dictionary) |
| |
| @mock.patch('glance_plugin.image.ctx', |
| ctx_mock( |
| {'image': |
| {'container_format': 'bare', |
| 'disk_format': 'qcow2'}})) |
| def test_check_image_container_format_disk_format(self): |
| # Test if it do not throw exception container_format & disk_format |
| image._validate_image_dictionary() |
| |
| |
| class TestStartImage(unittest.TestCase): |
| blueprint_path = os.path.join('resources', |
| 'test-image-start.yaml') |
| |
| @mock.patch('glance_plugin.image.create') |
| @workflow_test(blueprint_path, copy_plugin_yaml=True) |
| def test_image_lifecycle_start(self, cfy_local, *_): |
| test_vars = { |
| 'counter': 0, |
| 'image': mock.MagicMock() |
| } |
| |
| def _mock_get_image_by_ctx(*_): |
| i = test_vars['image'] |
| if test_vars['counter'] == 0: |
| i.status = 'different image status' |
| else: |
| i.status = glance_plugin.image.IMAGE_STATUS_ACTIVE |
| test_vars['counter'] += 1 |
| return i |
| |
| with mock.patch('openstack_plugin_common.GlanceClient'): |
| with mock.patch('glance_plugin.image._get_image_by_ctx', |
| side_effect=_mock_get_image_by_ctx): |
| cfy_local.execute('install', task_retries=3) |
| |
| self.assertEqual(2, test_vars['counter']) |
| self.assertEqual(0, test_vars['image'].start.call_count) |