Refactoring of ImageSettings to extend ImageConfig 77/47377/1
authorspisarski <s.pisarski@cablelabs.com>
Thu, 16 Nov 2017 23:07:47 +0000 (16:07 -0700)
committerspisarski <s.pisarski@cablelabs.com>
Thu, 16 Nov 2017 23:07:47 +0000 (16:07 -0700)
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 <s.pisarski@cablelabs.com>
20 files changed:
docs/how-to-use/APITests.rst
docs/how-to-use/IntegrationTests.rst
docs/how-to-use/LibraryUsage.rst
docs/how-to-use/UnitTests.rst
examples/demo.py
examples/launch.py
snaps/config/__init__.py [new file with mode: 0644]
snaps/config/image.py [new file with mode: 0644]
snaps/config/tests/__init__.py [new file with mode: 0644]
snaps/config/tests/image_tests.py [new file with mode: 0644]
snaps/openstack/create_image.py
snaps/openstack/create_stack.py
snaps/openstack/tests/create_image_tests.py
snaps/openstack/tests/create_instance_tests.py
snaps/openstack/tests/create_stack_tests.py
snaps/openstack/tests/openstack_tests.py
snaps/openstack/utils/settings_utils.py
snaps/openstack/utils/tests/heat_utils_tests.py
snaps/openstack/utils/tests/settings_utils_tests.py
snaps/test_suite_builder.py

index f71426c..fe8e51d 100644 (file)
@@ -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                          |
 +---------------------------------------+---------------+-----------------------------------------------------------+
index 1368eaf..f3d17f7 100644 (file)
@@ -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   |
index 9518c2b..a842be0 100644 (file)
@@ -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)
index 4a360d4..e6b95ab 100644 (file)
@@ -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
 ----------------------
index 108bdc0..faf6459 100644 (file)
@@ -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()
index 88ff420..debb52f 100644 (file)
@@ -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 (file)
index 0000000..fb7560b
--- /dev/null
@@ -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 (file)
index 0000000..fe1c913
--- /dev/null
@@ -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 (file)
index 0000000..fb7560b
--- /dev/null
@@ -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 (file)
index 0000000..8dcd2b4
--- /dev/null
@@ -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)
index c8782bf..2e7aa39 100644 (file)
@@ -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):
index 6075e7f..50d364d 100644 (file)
@@ -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,
index f70a71c..9965f87 100644 (file)
@@ -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()
 
index cd4e4da..1f50786 100644 (file)
@@ -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)
index 9a26918..4400001 100644 (file)
@@ -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()
index 16fb0b5..957825a 100644 (file)
@@ -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,
index ea1d018..2560b21 100644 (file)
@@ -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:
index 1068903..a219df6 100644 (file)
@@ -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])
index 3073d53..1c4c7b5 100644 (file)
@@ -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,
index 6ee9099..e770618 100644 (file)
@@ -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(