From 4cad4f7d1f53189900f9024fa5478e98a64d3760 Mon Sep 17 00:00:00 2001 From: spisarski Date: Thu, 16 Nov 2017 16:07:47 -0700 Subject: [PATCH] Refactoring of ImageSettings to extend ImageConfig ImageSettings and glance_utils have a runtime cyclical dependency. This patch reduces this dependency and deprecates the ImageSettings class. JIRA: SNAPS-217 Change-Id: I09f34531366f2a5bd3202c9cbbdef878b2542abe Signed-off-by: spisarski --- docs/how-to-use/APITests.rst | 2 +- docs/how-to-use/IntegrationTests.rst | 2 +- docs/how-to-use/LibraryUsage.rst | 11 +- docs/how-to-use/UnitTests.rst | 8 +- examples/demo.py | 7 +- examples/launch.py | 5 +- snaps/config/__init__.py | 14 ++ snaps/config/image.py | 110 ++++++++++ snaps/config/tests/__init__.py | 14 ++ snaps/config/tests/image_tests.py | 226 +++++++++++++++++++++ snaps/openstack/create_image.py | 108 +--------- snaps/openstack/create_stack.py | 6 +- snaps/openstack/tests/create_image_tests.py | 56 ++--- snaps/openstack/tests/create_instance_tests.py | 15 +- snaps/openstack/tests/create_stack_tests.py | 5 +- snaps/openstack/tests/openstack_tests.py | 29 ++- snaps/openstack/utils/settings_utils.py | 8 +- snaps/openstack/utils/tests/heat_utils_tests.py | 6 +- .../openstack/utils/tests/settings_utils_tests.py | 4 +- snaps/test_suite_builder.py | 8 +- 20 files changed, 469 insertions(+), 175 deletions(-) create mode 100644 snaps/config/__init__.py create mode 100644 snaps/config/image.py create mode 100644 snaps/config/tests/__init__.py create mode 100644 snaps/config/tests/image_tests.py diff --git a/docs/how-to-use/APITests.rst b/docs/how-to-use/APITests.rst index f71426c..fe8e51d 100644 --- a/docs/how-to-use/APITests.rst +++ b/docs/how-to-use/APITests.rst @@ -566,6 +566,6 @@ settings_utils_tests.py - SettingsUtilsVmInstTests | test_derive_vm_inst_settings | Neutron 2 | Tests to ensure that derived VmInstanceSettings from an | | | | OpenStack VM instance is correct | +---------------------------------------+---------------+-----------------------------------------------------------+ -| test_derive_image_settings | Neutron 2 | Tests to ensure that derived ImageSettings from an | +| test_derive_image_settings | Neutron 2 | Tests to ensure that derived ImageConfig from an | | | | OpenStack VM instance is correct | +---------------------------------------+---------------+-----------------------------------------------------------+ diff --git a/docs/how-to-use/IntegrationTests.rst b/docs/how-to-use/IntegrationTests.rst index 1368eaf..f3d17f7 100644 --- a/docs/how-to-use/IntegrationTests.rst +++ b/docs/how-to-use/IntegrationTests.rst @@ -80,7 +80,7 @@ create_image_tests.py - CreateImageNegativeTests | Test Name | Glance API | Description | +=======================================+===============+===========================================================+ | test_bad_image_name | 1 & 2 | Ensures OpenStackImage.create() results in an Exception | -| | | being raised when the ImageSettings.name attribute has | +| | | being raised when the ImageConfig.name attribute has | | | | not been set | +---------------------------------------+---------------+-----------------------------------------------------------+ | test_bad_image_url | 1 & 2 | Ensures OpenStackImage.create() results in an Exception | diff --git a/docs/how-to-use/LibraryUsage.rst b/docs/how-to-use/LibraryUsage.rst index 9518c2b..a842be0 100644 --- a/docs/how-to-use/LibraryUsage.rst +++ b/docs/how-to-use/LibraryUsage.rst @@ -170,7 +170,7 @@ Create Image ------------ - Image - snaps.openstack.create\_image.OpenStackImage - - snaps.openstack.create\_image.ImageSettings + - snaps.config.image.ImageConfig - name - the image name (required) - image\_user - the default image user generally used by @@ -193,9 +193,10 @@ Create Image .. code:: python - from snaps.openstack.create_image import ImageSettings, OpenStackImage - image_settings = ImageSettings(name='image-name', image_user='ubuntu', img_format='qcow2', - url='http://uec-images.ubuntu.com/releases/trusty/14.04/ubuntu-14.04-server-cloudimg-amd64-disk1.img') + from snaps.openstack.create_image import OpenStackImage + from snaps.config.image import ImageConfig + image_settings = ImageConfig(name='image-name', image_user='ubuntu', img_format='qcow2', + url='http://uec-images.ubuntu.com/releases/trusty/14.04/ubuntu-14.04-server-cloudimg-amd64-disk1.img') image_creator = OpenStackImage(os_creds, image_settings) image_creator.create() @@ -571,7 +572,7 @@ Create VM Instance - userdata - the cloud-init script to execute after VM has been started - - image\_settings - see snaps.openstack.create\_image.ImageSettings + - image\_settings - see snaps.config.image.ImageConfig above (required) - keypair\_settings - see snaps.openstack.create\_keypairs.KeypairSettings above (optional) diff --git a/docs/how-to-use/UnitTests.rst b/docs/how-to-use/UnitTests.rst index 4a360d4..e6b95ab 100644 --- a/docs/how-to-use/UnitTests.rst +++ b/docs/how-to-use/UnitTests.rst @@ -60,11 +60,17 @@ SecurityGroupDomainObjectTests Ensures that all required members are included when constructing a SecurityGroup domain object +ImageConfigUnitTests +-------------------- + +Ensures that all required members are included when constructing a +ImageConfig object + ImageSettingsUnitTests ---------------------- Ensures that all required members are included when constructing a -ImageSettings object +ImageSettings object (deprecated see ImageConfigUnitTests) ImageDomainObjectTests ---------------------- diff --git a/examples/demo.py b/examples/demo.py index 108bdc0..faf6459 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -13,10 +13,11 @@ os_creds = OSCreds(username='admin', password='cable123', auth_url='http://192.1 # Images -from snaps.openstack.create_image import ImageSettings, OpenStackImage +from snaps.openstack.create_image import OpenStackImage +from snaps.config.image import ImageConfig -image_settings = ImageSettings(name='cirros-test', image_user='cirros', img_format='qcow2', - url='http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img') +image_settings = ImageConfig(name='cirros-test', image_user='cirros', img_format='qcow2', + url='http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img') image = OpenStackImage(os_creds, image_settings) image.create() diff --git a/examples/launch.py b/examples/launch.py index 88ff420..debb52f 100644 --- a/examples/launch.py +++ b/examples/launch.py @@ -27,7 +27,8 @@ import yaml from snaps import file_utils from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor -from snaps.openstack.create_image import ImageSettings, OpenStackImage +from snaps.openstack.create_image import OpenStackImage +from snaps.config.image import ImageConfig from snaps.openstack.create_instance import VmInstanceSettings from snaps.openstack.create_keypairs import KeypairSettings, OpenStackKeypair from snaps.openstack.create_network import ( @@ -659,7 +660,7 @@ def main(arguments): # Create images images_dict = __create_instances( - os_creds_dict, OpenStackImage, ImageSettings, + os_creds_dict, OpenStackImage, ImageConfig, os_config.get('images'), 'image', clean, users_dict) creators.append(images_dict) diff --git a/snaps/config/__init__.py b/snaps/config/__init__.py new file mode 100644 index 0000000..fb7560b --- /dev/null +++ b/snaps/config/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs") +# and others. 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. diff --git a/snaps/config/image.py b/snaps/config/image.py new file mode 100644 index 0000000..fe1c913 --- /dev/null +++ b/snaps/config/image.py @@ -0,0 +1,110 @@ +# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs") +# and others. 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. + + +class ImageConfig(object): + def __init__(self, **kwargs): + """ + Constructor + :param name: the image's name (required) + :param image_user: the image's default sudo user (required) + :param format or img_format: the image format type (required) + :param url or download_url: the image download location (requires url + or img_file) + :param image_file: the image file location (requires url or img_file) + :param extra_properties: dict() object containing extra parameters to + pass when loading the image; + can be ids of kernel and initramfs images for + a 3-part image + :param nic_config_pb_loc: the file location to the Ansible Playbook + that can configure multiple NICs + :param kernel_image_settings: the settings for a kernel image + :param ramdisk_image_settings: the settings for a ramdisk image + :param exists: When True, an image with the given name must exist + :param public: When True, an image will be created with public + visibility + """ + + self.name = kwargs.get('name') + self.image_user = kwargs.get('image_user') + self.format = kwargs.get('format') + if not self.format: + self.format = kwargs.get('img_format') + + self.url = kwargs.get('url') + if not self.url: + self.url = kwargs.get('download_url') + if self.url == 'None': + self.url = None + + self.image_file = kwargs.get('image_file') + if self.image_file == 'None': + self.image_file = None + + self.extra_properties = kwargs.get('extra_properties') + self.nic_config_pb_loc = kwargs.get('nic_config_pb_loc') + + kernel_image_settings = kwargs.get('kernel_image_settings') + if kernel_image_settings: + if isinstance(kernel_image_settings, dict): + self.kernel_image_settings = ImageConfig( + **kernel_image_settings) + else: + self.kernel_image_settings = kernel_image_settings + else: + self.kernel_image_settings = None + + ramdisk_image_settings = kwargs.get('ramdisk_image_settings') + if ramdisk_image_settings: + if isinstance(ramdisk_image_settings, dict): + self.ramdisk_image_settings = ImageConfig( + **ramdisk_image_settings) + else: + self.ramdisk_image_settings = ramdisk_image_settings + else: + self.ramdisk_image_settings = None + + if 'exists' in kwargs and kwargs['exists'] is True: + self.exists = True + else: + self.exists = False + + if 'public' in kwargs and kwargs['public'] is True: + self.public = True + else: + self.public = False + + if not self.name: + raise ImageConfigError("The attribute name is required") + + if not (self.url or self.image_file) and not self.exists: + raise ImageConfigError( + 'URL or image file must be set or image must already exist') + + if not self.image_user: + raise ImageConfigError('Image user is required') + + if not self.format and not self.exists: + raise ImageConfigError( + 'Format is required when the image should not already exist') + + +class ImageConfigError(Exception): + """ + Exception to be thrown when an image settings are incorrect + """ + + def __init__(self, message): + Exception.__init__(self, message) diff --git a/snaps/config/tests/__init__.py b/snaps/config/tests/__init__.py new file mode 100644 index 0000000..fb7560b --- /dev/null +++ b/snaps/config/tests/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs") +# and others. 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. diff --git a/snaps/config/tests/image_tests.py b/snaps/config/tests/image_tests.py new file mode 100644 index 0000000..8dcd2b4 --- /dev/null +++ b/snaps/config/tests/image_tests.py @@ -0,0 +1,226 @@ +# Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs") +# and others. 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 unittest + +from snaps.config.image import ImageConfigError, ImageConfig + + +class ImageConfigUnitTests(unittest.TestCase): + """ + Tests the construction of the ImageConfig class + """ + + def test_no_params(self): + with self.assertRaises(ImageConfigError): + ImageConfig() + + def test_empty_config(self): + with self.assertRaises(ImageConfigError): + ImageConfig(**dict()) + + def test_name_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(name='foo') + + def test_config_with_name_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(**{'name': 'foo'}) + + def test_name_user_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(name='foo', image_user='bar') + + def test_config_with_name_user_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(**{'name': 'foo', 'image_user': 'bar'}) + + def test_name_user_format_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig(name='foo', image_user='bar', img_format='qcow2') + + def test_config_with_name_user_format_only(self): + with self.assertRaises(ImageConfigError): + ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2'}) + + def test_name_user_format_url_only(self): + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', url='http://foo.com') + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertIsNone(settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_name_user_format_url_only_properties(self): + properties = {'hw_video_model': 'vga'} + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', url='http://foo.com', + extra_properties=properties) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertEqual(properties, settings.extra_properties) + self.assertIsNone(settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_config_with_name_user_format_url_only(self): + settings = ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2', + 'download_url': 'http://foo.com'}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertIsNone(settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_name_user_format_file_only(self): + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', + image_file='/foo/bar.qcow') + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertIsNone(settings.url) + self.assertEqual('/foo/bar.qcow', settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_config_with_name_user_format_file_only(self): + settings = ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2', + 'image_file': '/foo/bar.qcow'}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertIsNone(settings.url) + self.assertEqual('/foo/bar.qcow', settings.image_file) + self.assertFalse(settings.exists) + self.assertFalse(settings.public) + self.assertIsNone(settings.nic_config_pb_loc) + + def test_all_url(self): + properties = {'hw_video_model': 'vga'} + kernel_settings = ImageConfig(name='kernel', url='http://kernel.com', + image_user='bar', img_format='qcow2') + ramdisk_settings = ImageConfig(name='ramdisk', + url='http://ramdisk.com', + image_user='bar', img_format='qcow2') + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', url='http://foo.com', + extra_properties=properties, + nic_config_pb_loc='/foo/bar', + kernel_image_settings=kernel_settings, + ramdisk_image_settings=ramdisk_settings, + exists=True, public=True) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertEqual(properties, settings.extra_properties) + self.assertIsNone(settings.image_file) + self.assertEqual('/foo/bar', settings.nic_config_pb_loc) + self.assertEqual('kernel', settings.kernel_image_settings.name) + self.assertEqual('http://kernel.com', + settings.kernel_image_settings.url) + self.assertEqual('bar', settings.kernel_image_settings.image_user) + self.assertEqual('qcow2', settings.kernel_image_settings.format) + self.assertEqual('ramdisk', settings.ramdisk_image_settings.name) + self.assertEqual('http://ramdisk.com', + settings.ramdisk_image_settings.url) + self.assertEqual('bar', settings.ramdisk_image_settings.image_user) + self.assertEqual('qcow2', settings.ramdisk_image_settings.format) + self.assertTrue(settings.exists) + self.assertTrue(settings.public) + + def test_config_all_url(self): + settings = ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2', + 'download_url': 'http://foo.com', + 'extra_properties': '{\'hw_video_model\': \'vga\'}', + 'nic_config_pb_loc': '/foo/bar', + 'kernel_image_settings': { + 'name': 'kernel', + 'download_url': 'http://kernel.com', + 'image_user': 'bar', + 'format': 'qcow2'}, + 'ramdisk_image_settings': { + 'name': 'ramdisk', + 'download_url': 'http://ramdisk.com', + 'image_user': 'bar', + 'format': 'qcow2'}, + 'exists': True, 'public': True}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertEqual('http://foo.com', settings.url) + self.assertEqual('{\'hw_video_model\': \'vga\'}', + settings.extra_properties) + self.assertIsNone(settings.image_file) + self.assertEqual('/foo/bar', settings.nic_config_pb_loc) + self.assertEqual('kernel', settings.kernel_image_settings.name) + self.assertEqual('http://kernel.com', + settings.kernel_image_settings.url) + self.assertEqual('ramdisk', settings.ramdisk_image_settings.name) + self.assertEqual('http://ramdisk.com', + settings.ramdisk_image_settings.url) + self.assertTrue(settings.exists) + self.assertTrue(settings.public) + + def test_all_file(self): + properties = {'hw_video_model': 'vga'} + settings = ImageConfig(name='foo', image_user='bar', + img_format='qcow2', + image_file='/foo/bar.qcow', + extra_properties=properties, + nic_config_pb_loc='/foo/bar', exists=True, + public=True) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertIsNone(settings.url) + self.assertEqual('/foo/bar.qcow', settings.image_file) + self.assertEqual(properties, settings.extra_properties) + self.assertEqual('/foo/bar', settings.nic_config_pb_loc) + self.assertTrue(settings.exists) + self.assertTrue(settings.public) + + def test_config_all_file(self): + settings = ImageConfig( + **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2', + 'image_file': '/foo/bar.qcow', + 'extra_properties': '{\'hw_video_model\' : \'vga\'}', + 'nic_config_pb_loc': '/foo/bar', 'exists': True, + 'public': True}) + self.assertEqual('foo', settings.name) + self.assertEqual('bar', settings.image_user) + self.assertEqual('qcow2', settings.format) + self.assertIsNone(settings.url) + self.assertEqual('/foo/bar.qcow', settings.image_file) + self.assertEqual('{\'hw_video_model\' : \'vga\'}', + settings.extra_properties) + self.assertEqual('/foo/bar', settings.nic_config_pb_loc) + self.assertTrue(settings.exists) + self.assertTrue(settings.public) diff --git a/snaps/openstack/create_image.py b/snaps/openstack/create_image.py index c8782bf..2e7aa39 100644 --- a/snaps/openstack/create_image.py +++ b/snaps/openstack/create_image.py @@ -19,6 +19,7 @@ import time from snaps.openstack.openstack_creator import OpenStackCloudObject from snaps.openstack.utils import glance_utils +from snaps.config import image __author__ = 'spisarski' @@ -38,8 +39,7 @@ class OpenStackImage(OpenStackCloudObject): """ Constructor :param os_creds: The OpenStack connection credentials - :param image_settings: The image settings - :return: + :param image_settings: An snaps.config.image.ImageConfig object """ super(self.__class__, self).__init__(os_creds) @@ -132,10 +132,10 @@ class OpenStackImage(OpenStackCloudObject): Cleanse environment of all artifacts :return: void """ - for image in [self.__image, self.__kernel_image, self.__ramdisk_image]: - if image: + for img in [self.__image, self.__kernel_image, self.__ramdisk_image]: + if img: try: - glance_utils.delete_image(self.__glance, image) + glance_utils.delete_image(self.__glance, img) except HTTPNotFound: pass @@ -236,100 +236,14 @@ class OpenStackImage(OpenStackCloudObject): return status == expected_status_code -class ImageSettings: - def __init__(self, **kwargs): - """ - Constructor - :param name: the image's name (required) - :param image_user: the image's default sudo user (required) - :param format or img_format: the image format type (required) - :param url or download_url: the image download location (requires url - or img_file) - :param image_file: the image file location (requires url or img_file) - :param extra_properties: dict() object containing extra parameters to - pass when loading the image; - can be ids of kernel and initramfs images for - a 3-part image - :param nic_config_pb_loc: the file location to the Ansible Playbook - that can configure multiple NICs - :param kernel_image_settings: the settings for a kernel image - :param ramdisk_image_settings: the settings for a ramdisk image - :param exists: When True, an image with the given name must exist - :param public: When True, an image will be created with public - visibility - """ - - self.name = kwargs.get('name') - self.image_user = kwargs.get('image_user') - self.format = kwargs.get('format') - if not self.format: - self.format = kwargs.get('img_format') - - self.url = kwargs.get('url') - if not self.url: - self.url = kwargs.get('download_url') - if self.url == 'None': - self.url = None - - self.image_file = kwargs.get('image_file') - if self.image_file == 'None': - self.image_file = None - - self.extra_properties = kwargs.get('extra_properties') - self.nic_config_pb_loc = kwargs.get('nic_config_pb_loc') - - kernel_image_settings = kwargs.get('kernel_image_settings') - if kernel_image_settings: - if isinstance(kernel_image_settings, dict): - self.kernel_image_settings = ImageSettings( - **kernel_image_settings) - else: - self.kernel_image_settings = kernel_image_settings - else: - self.kernel_image_settings = None - - ramdisk_image_settings = kwargs.get('ramdisk_image_settings') - if ramdisk_image_settings: - if isinstance(ramdisk_image_settings, dict): - self.ramdisk_image_settings = ImageSettings( - **ramdisk_image_settings) - else: - self.ramdisk_image_settings = ramdisk_image_settings - else: - self.ramdisk_image_settings = None - - if 'exists' in kwargs and kwargs['exists'] is True: - self.exists = True - else: - self.exists = False - - if 'public' in kwargs and kwargs['public'] is True: - self.public = True - else: - self.public = False - - if not self.name: - raise ImageSettingsError("The attribute name is required") - - if not (self.url or self.image_file) and not self.exists: - raise ImageSettingsError( - 'URL or image file must be set or image must already exist') - - if not self.image_user: - raise ImageSettingsError('Image user is required') - - if not self.format and not self.exists: - raise ImageSettingsError( - 'Format is required when the image should not already exist') - - -class ImageSettingsError(Exception): +class ImageSettings(image.ImageConfig): """ - Exception to be thrown when an image settings are incorrect + Deprecated, use snaps.config.image.ImageSettings instead """ - - def __init__(self, message): - Exception.__init__(self, message) + def __init__(self, **kwargs): + from warnings import warn + warn('Use snaps.config.image.ImageConfig instead', DeprecationWarning) + super(ImageSettings, self).__init__(**kwargs) class ImageCreationError(Exception): diff --git a/snaps/openstack/create_stack.py b/snaps/openstack/create_stack.py index 6075e7f..50d364d 100644 --- a/snaps/openstack/create_stack.py +++ b/snaps/openstack/create_stack.py @@ -56,9 +56,7 @@ class OpenStackHeatStack(OpenStackCloudObject, object): Constructor :param os_creds: The OpenStack connection credentials :param stack_settings: The stack settings - :param image_settings: A list of ImageSettings objects that were used - for spawning this stack - :param image_settings: A list of ImageSettings objects that were used + :param image_settings: A list of ImageConfig objects that were used for spawning this stack :param keypair_settings: A list of KeypairSettings objects that were used for spawning this stack @@ -299,7 +297,7 @@ class OpenStackHeatStack(OpenStackCloudObject, object): for stack_server in stack_servers: vm_inst_settings = settings_utils.create_vm_inst_settings( nova, neutron, stack_server) - image_settings = settings_utils.determine_image_settings( + image_settings = settings_utils.determine_image_config( glance, stack_server, self.image_settings) keypair_settings = settings_utils.determine_keypair_settings( self.__heat_cli, self.__stack, stack_server, diff --git a/snaps/openstack/tests/create_image_tests.py b/snaps/openstack/tests/create_image_tests.py index f70a71c..9965f87 100644 --- a/snaps/openstack/tests/create_image_tests.py +++ b/snaps/openstack/tests/create_image_tests.py @@ -27,9 +27,10 @@ import uuid import os from snaps import file_utils +from snaps.config.image import ImageConfigError from snaps.openstack import create_image -from snaps.openstack.create_image import (ImageSettings, ImageCreationError, - ImageSettingsError) +from snaps.openstack.create_image import ImageSettings, ImageCreationError +from snaps.config.image import ImageConfig from snaps.openstack.tests import openstack_tests from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase from snaps.openstack.utils import glance_utils @@ -42,38 +43,40 @@ logger = logging.getLogger('create_image_tests') class ImageSettingsUnitTests(unittest.TestCase): """ Tests the construction of the ImageSettings class + To be removed once the deprecated class ImageSettings is finally removed + from the source tree """ def test_no_params(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings() def test_empty_config(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(**dict()) def test_name_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(name='foo') def test_config_with_name_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(**{'name': 'foo'}) def test_name_user_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(name='foo', image_user='bar') def test_config_with_name_user_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(**{'name': 'foo', 'image_user': 'bar'}) def test_name_user_format_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings(name='foo', image_user='bar', img_format='qcow2') def test_config_with_name_user_format_only(self): - with self.assertRaises(ImageSettingsError): + with self.assertRaises(ImageConfigError): ImageSettings( **{'name': 'foo', 'image_user': 'bar', 'format': 'qcow2'}) @@ -448,8 +451,8 @@ class CreateImageSuccessTests(OSIntegrationTestCase): self.assertEqual(image1.properties, retrieved_image.properties) # Should be retrieving the instance data - image_2_settings = ImageSettings(name=self.image_settings.name, - image_user='foo', exists=True) + image_2_settings = ImageConfig(name=self.image_settings.name, + image_user='foo', exists=True) os_image_2 = create_image.OpenStackImage(self.os_creds, image_2_settings) image2 = os_image_2.create() @@ -478,8 +481,8 @@ class CreateImageNegativeTests(OSIntegrationTestCase): Expect an ImageCreationError when the image name does not exist when a file or URL has not been configured """ - os_image_settings = ImageSettings(name='foo', image_user='bar', - exists=True) + os_image_settings = ImageConfig(name='foo', image_user='bar', + exists=True) self.image_creator = create_image.OpenStackImage(self.os_creds, os_image_settings) @@ -497,10 +500,11 @@ class CreateImageNegativeTests(OSIntegrationTestCase): name=self.image_name) self.image_creator = create_image.OpenStackImage( self.os_creds, - create_image.ImageSettings(name=os_image_settings.name, - image_user=os_image_settings.image_user, - img_format=os_image_settings.format, - url="http://foo.bar")) + ImageConfig( + name=os_image_settings.name, + image_user=os_image_settings.image_user, + img_format=os_image_settings.format, + url="http://foo.bar")) try: self.image_creator.create() @@ -519,10 +523,10 @@ class CreateImageNegativeTests(OSIntegrationTestCase): name=self.image_name) self.image_creator = create_image.OpenStackImage( self.os_creds, - create_image.ImageSettings(name=os_image_settings.name, - image_user=os_image_settings.image_user, - img_format='foo', - url=os_image_settings.url)) + ImageConfig( + name=os_image_settings.name, + image_user=os_image_settings.image_user, + img_format='foo', url=os_image_settings.url)) with self.assertRaises(Exception): self.image_creator.create() @@ -535,10 +539,10 @@ class CreateImageNegativeTests(OSIntegrationTestCase): name=self.image_name) self.image_creator = create_image.OpenStackImage( self.os_creds, - create_image.ImageSettings(name=os_image_settings.name, - image_user=os_image_settings.image_user, - img_format=os_image_settings.format, - image_file="/foo/bar.qcow")) + ImageConfig( + name=os_image_settings.name, + image_user=os_image_settings.image_user, + img_format=os_image_settings.format, image_file="/foo/bar.qcow")) with self.assertRaises(IOError): self.image_creator.create() diff --git a/snaps/openstack/tests/create_instance_tests.py b/snaps/openstack/tests/create_instance_tests.py index cd4e4da..1f50786 100644 --- a/snaps/openstack/tests/create_instance_tests.py +++ b/snaps/openstack/tests/create_instance_tests.py @@ -26,7 +26,8 @@ from novaclient.exceptions import BadRequest from snaps import file_utils from snaps.openstack import create_network, create_router from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings -from snaps.openstack.create_image import OpenStackImage, ImageSettings +from snaps.openstack.create_image import OpenStackImage +from snaps.config.image import ImageConfig from snaps.openstack.create_instance import ( VmInstanceSettings, OpenStackVmInstance, FloatingIpSettings, VmInstanceSettingsError, FloatingIpSettingsError) @@ -2316,9 +2317,9 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase): image_settings = self.image_creator.image_settings test_image_creator = OpenStackImage( self.os_creds, - ImageSettings(name=image_settings.name, - image_user=image_settings.image_user, - exists=True)) + ImageConfig( + name=image_settings.name, image_user=image_settings.image_user, + exists=True)) test_image_creator.create() self.assertEqual(self.image_creator.get_image().id, test_image_creator.get_image().id) @@ -2611,9 +2612,9 @@ class CreateInstanceMockOfflineTests(OSComponentTestCase): image_settings = self.image_creator.image_settings test_image_creator = OpenStackImage( self.os_creds, - ImageSettings(name=image_settings.name, - image_user=image_settings.image_user, - exists=True)) + ImageConfig( + name=image_settings.name, image_user=image_settings.image_user, + exists=True)) test_image_creator.create() self.assertEqual(self.image_creator.get_image().id, test_image_creator.get_image().id) diff --git a/snaps/openstack/tests/create_stack_tests.py b/snaps/openstack/tests/create_stack_tests.py index 9a26918..4400001 100644 --- a/snaps/openstack/tests/create_stack_tests.py +++ b/snaps/openstack/tests/create_stack_tests.py @@ -19,7 +19,8 @@ import pkg_resources from heatclient.exc import HTTPBadRequest from snaps import file_utils from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings -from snaps.openstack.create_image import OpenStackImage, ImageSettings +from snaps.openstack.create_image import OpenStackImage +from snaps.config.image import ImageConfig try: from urllib.request import URLError @@ -974,7 +975,7 @@ class CreateStackFailureTests(OSIntegrationTestCase): self.tmp_file = file_utils.save_string_to_file( ' ', str(uuid.uuid4()) + '-bad-image') self.image_creator = OpenStackImage( - self.heat_creds, ImageSettings( + self.heat_creds, ImageConfig( name=self.guid + 'image', image_file=self.tmp_file.name, image_user='foo', img_format='qcow2')) self.image_creator.create() diff --git a/snaps/openstack/tests/openstack_tests.py b/snaps/openstack/tests/openstack_tests.py index 16fb0b5..957825a 100644 --- a/snaps/openstack/tests/openstack_tests.py +++ b/snaps/openstack/tests/openstack_tests.py @@ -17,7 +17,7 @@ import re import pkg_resources from snaps import file_utils -from snaps.openstack.create_image import ImageSettings +from snaps.config.image import ImageConfig from snaps.openstack.create_network import NetworkSettings, SubnetSettings from snaps.openstack.create_router import RouterSettings from snaps.openstack.os_credentials import OSCreds, ProxySettings @@ -171,7 +171,7 @@ def create_image_settings(image_name, image_user, image_format, metadata, logger.debug('Image metadata - ' + str(metadata)) if metadata and 'config' in metadata: - return ImageSettings(**metadata['config']) + return ImageConfig(**metadata['config']) disk_file = None if metadata: @@ -185,10 +185,9 @@ def create_image_settings(image_name, image_user, image_format, metadata, if metadata and \ ('kernel_file' in metadata or 'kernel_url' in metadata) and \ kernel_settings is None: - kernel_image_settings = ImageSettings( + kernel_image_settings = ImageConfig( name=image_name + '-kernel', image_user=image_user, - img_format=image_format, - image_file=metadata.get('kernel_file'), + img_format=image_format, image_file=metadata.get('kernel_file'), url=metadata.get('kernel_url'), public=public) else: kernel_image_settings = kernel_settings @@ -196,7 +195,7 @@ def create_image_settings(image_name, image_user, image_format, metadata, if metadata and \ ('ramdisk_file' in metadata or 'ramdisk_url' in metadata) and \ ramdisk_settings is None: - ramdisk_image_settings = ImageSettings( + ramdisk_image_settings = ImageConfig( name=image_name + '-ramdisk', image_user=image_user, img_format=image_format, image_file=metadata.get('ramdisk_file'), @@ -208,13 +207,13 @@ def create_image_settings(image_name, image_user, image_format, metadata, if metadata and 'extra_properties' in metadata: extra_properties = metadata['extra_properties'] - return ImageSettings(name=image_name, image_user=image_user, - img_format=image_format, image_file=disk_file, - url=disk_url, extra_properties=extra_properties, - kernel_image_settings=kernel_image_settings, - ramdisk_image_settings=ramdisk_image_settings, - public=public, - nic_config_pb_loc=nic_config_pb_loc) + return ImageConfig(name=image_name, image_user=image_user, + img_format=image_format, image_file=disk_file, + url=disk_url, extra_properties=extra_properties, + kernel_image_settings=kernel_image_settings, + ramdisk_image_settings=ramdisk_image_settings, + public=public, + nic_config_pb_loc=nic_config_pb_loc) def cirros_image_settings(name=None, url=None, image_metadata=None, @@ -248,8 +247,8 @@ def cirros_image_settings(name=None, url=None, image_metadata=None, def file_image_test_settings(name, file_path, image_user=CIRROS_USER): - return ImageSettings(name=name, image_user=image_user, - img_format=DEFAULT_IMAGE_FORMAT, image_file=file_path) + return ImageConfig(name=name, image_user=image_user, + img_format=DEFAULT_IMAGE_FORMAT, image_file=file_path) def centos_image_settings(name, url=None, image_metadata=None, diff --git a/snaps/openstack/utils/settings_utils.py b/snaps/openstack/utils/settings_utils.py index ea1d018..2560b21 100644 --- a/snaps/openstack/utils/settings_utils.py +++ b/snaps/openstack/utils/settings_utils.py @@ -348,14 +348,14 @@ def __create_floatingip_settings(neutron, port_settings): return out -def determine_image_settings(glance, server, image_settings): +def determine_image_config(glance, server, image_settings): """ - Returns a ImageSettings object from the list that matches the name in one + Returns a ImageConfig object from the list that matches the name in one of the image_settings parameter :param glance: the glance client :param server: a SNAPS-OO VmInst domain object - :param image_settings: list of ImageSettings objects - :return: ImageSettings or None + :param image_settings: list of ImageConfig objects + :return: ImageConfig or None """ if image_settings: for image_setting in image_settings: diff --git a/snaps/openstack/utils/tests/heat_utils_tests.py b/snaps/openstack/utils/tests/heat_utils_tests.py index 1068903..a219df6 100644 --- a/snaps/openstack/utils/tests/heat_utils_tests.py +++ b/snaps/openstack/utils/tests/heat_utils_tests.py @@ -313,7 +313,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): for server in servers: vm_settings = settings_utils.create_vm_inst_settings( nova, neutron, server) - img_settings = settings_utils.determine_image_settings( + img_settings = settings_utils.determine_image_config( glance, server, [self.image_creator1.image_settings, self.image_creator2.image_settings]) @@ -385,7 +385,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): self.assertIsNotNone(servers) self.assertEqual(2, len(servers)) - image_settings = settings_utils.determine_image_settings( + image_settings = settings_utils.determine_image_config( glance, servers[0], [self.image_creator1.image_settings, self.image_creator2.image_settings]) @@ -398,7 +398,7 @@ class HeatUtilsCreateComplexStackTests(OSComponentTestCase): self.assertEqual( self.image_creator2.image_settings.name, image_settings.name) - image_settings = settings_utils.determine_image_settings( + image_settings = settings_utils.determine_image_config( glance, servers[1], [self.image_creator1.image_settings, self.image_creator2.image_settings]) diff --git a/snaps/openstack/utils/tests/settings_utils_tests.py b/snaps/openstack/utils/tests/settings_utils_tests.py index 3073d53..1c4c7b5 100644 --- a/snaps/openstack/utils/tests/settings_utils_tests.py +++ b/snaps/openstack/utils/tests/settings_utils_tests.py @@ -332,13 +332,13 @@ class SettingsUtilsVmInstTests(OSComponentTestCase): def test_derive_image_settings(self): """ Validates the utility function settings_utils#create_image_settings - returns an acceptable ImageSettings object + returns an acceptable ImageConfig object """ self.inst_creator.create(block=True) server = nova_utils.get_server( self.nova, vm_inst_settings=self.inst_creator.instance_settings) - derived_image_settings = settings_utils.determine_image_settings( + derived_image_settings = settings_utils.determine_image_config( self.glance, server, [self.image_creator.image_settings]) self.assertIsNotNone(derived_image_settings) self.assertEqual(self.image_creator.image_settings.name, diff --git a/snaps/test_suite_builder.py b/snaps/test_suite_builder.py index 6ee9099..e770618 100644 --- a/snaps/test_suite_builder.py +++ b/snaps/test_suite_builder.py @@ -16,6 +16,8 @@ import logging import unittest +import snaps.config.tests.image_tests as image_tests +import snaps.openstack.tests.create_image_tests as creator_tests from snaps.domain.test.flavor_tests import FlavorDomainObjectTests from snaps.domain.test.image_tests import ImageDomainObjectTests from snaps.domain.test.keypair_tests import KeypairDomainObjectTests @@ -40,7 +42,7 @@ from snaps.openstack.tests.conf.os_credentials_tests import ( from snaps.openstack.tests.create_flavor_tests import ( CreateFlavorTests, FlavorSettingsUnitTests) from snaps.openstack.tests.create_image_tests import ( - CreateImageSuccessTests, CreateImageNegativeTests, ImageSettingsUnitTests, + CreateImageSuccessTests, CreateImageNegativeTests, CreateMultiPartImageTests) from snaps.openstack.tests.create_instance_tests import ( CreateInstanceSingleNetworkTests, CreateInstancePubPrivNetTests, @@ -132,7 +134,9 @@ def add_unit_tests(suite): suite.addTest(unittest.TestLoader().loadTestsFromTestCase( SecurityGroupRuleDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( - ImageSettingsUnitTests)) + image_tests.ImageConfigUnitTests)) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase( + creator_tests.ImageSettingsUnitTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( ImageDomainObjectTests)) suite.addTest(unittest.TestLoader().loadTestsFromTestCase( -- 2.16.6