summaryrefslogtreecommitdiffstats
path: root/.gitignore
blob: 7c4785069a7d2084df5b1888c7f3a73ebbf6e090 (plain)
1
2
3
4
5
6
*~
.*.sw?
/docs_build/
/docs/projects/
/docs_output/
/releng/
t */ .highlight .err { color: #960050; background-color: #1e0010 } /* Error */ .highlight .k { color: #66d9ef } /* Keyword */ .highlight .l { color: #ae81ff } /* Literal */ .highlight .n { color: #f8f8f2 } /* Name */ .highlight .o { color: #f92672 } /* Operator */ .highlight .p { color: #f8f8f2 } /* Punctuation */ .highlight .ch { color: #75715e } /* Comment.Hashbang */ .highlight .cm { color: #75715e } /* Comment.Multiline */ .highlight .cp { color: #75715e } /* Comment.Preproc */ .highlight .cpf { color: #75715e } /* Comment.PreprocFile */ .highlight .c1 { color: #75715e } /* Comment.Single */ .highlight .cs { color: #75715e } /* Comment.Special */ .highlight .gd { color: #f92672 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gi { color: #a6e22e } /* Generic.Inserted */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #75715e } /* Generic.Subheading */ .highlight .kc { color: #66d9ef } /* Keyword.Constant */ .highlight .kd { color: #66d9ef } /* Keyword.Declaration */ .highlight .kn { color: #f92672 } /* Keyword.Namespace */ .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ .highlight .kt { color: #66d9ef } /* Keyword.Type */ .highlight .ld { color: #e6db74 } /* Literal.Date */ .highlight .m { color: #ae81ff } /* Literal.Number */ .highlight .s { color: #e6db74 } /* Literal.String */ .highlight .na { color: #a6e22e } /* Name.Attribute */ .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ .highlight .nc { color: #a6e22e } /* Name.Class */ .highlight .no { color: #66d9ef } /* Name.Constant */ .highlight .nd { color: #a6e22e } /* Name.Decorator */ .highlight .ni { color: #f8f8f2 } /* Name.Entity */ .highlight .ne { color: #a6e22e } /* Name.Exception */ .highlight .nf { color: #a6e22e } /* Name.Function */ .highlight .nl { color: #f8f8f2 } /* Name.Label */ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ .highlight .nx { color: #a6e22e } /* Name.Other */ .highlight .py { color: #f8f8f2 } /* Name.Property */ .highlight .nt { color: #f92672 } /* Name.Tag */ .highlight .nv { color: #f8f8f2 } /* Name.Variable */ .highlight .ow { color: #f92672 } /* Operator.Word */ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
# 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.
from cinderclient.exceptions import NotFound, BadRequest

from snaps.openstack.create_image import OpenStackImage
from snaps.openstack.create_volume_type import (
    VolumeTypeSettings, OpenStackVolumeType)
from snaps.openstack.tests import openstack_tests

try:
    from urllib.request import URLError
except ImportError:
    from urllib2 import URLError

import logging
import unittest
import uuid

from snaps.openstack import create_volume
from snaps.openstack.create_volume import (
    VolumeSettings, VolumeSettingsError, OpenStackVolume)
from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
from snaps.openstack.utils import cinder_utils

__author__ = 'spisarski'

logger = logging.getLogger('create_volume_tests')


class VolumeSettingsUnitTests(unittest.TestCase):
    """
    Tests the construction of the VolumeSettings class
    """

    def test_no_params(self):
        with self.assertRaises(VolumeSettingsError):
            VolumeSettings()

    def test_empty_config(self):
        with self.assertRaises(VolumeSettingsError):
            VolumeSettings(**dict())

    def test_name_only(self):
        settings = VolumeSettings(name='foo')
        self.assertEqual('foo', settings.name)
        self.assertIsNone(settings.description)
        self.assertEquals(1, settings.size)
        self.assertIsNone(settings.image_name)
        self.assertIsNone(settings.type_name)
        self.assertIsNone(settings.availability_zone)
        self.assertFalse(settings.multi_attach)

    def test_config_with_name_only(self):
        settings = VolumeSettings(**{'name': 'foo'})
        self.assertEqual('foo', settings.name)
        self.assertIsNone(settings.description)
        self.assertEquals(1, settings.size)
        self.assertIsNone(settings.image_name)
        self.assertIsNone(settings.type_name)
        self.assertIsNone(settings.availability_zone)
        self.assertFalse(settings.multi_attach)

    def test_all_strings(self):
        settings = VolumeSettings(
            name='foo', description='desc', size='2', image_name='image',
            type_name='type', availability_zone='zone1', multi_attach='true')

        self.assertEqual('foo', settings.name)
        self.assertEqual('desc', settings.description)
        self.assertEqual(2, settings.size)
        self.assertEqual('image', settings.image_name)
        self.assertEqual('type', settings.type_name)
        self.assertEqual('zone1', settings.availability_zone)
        self.assertTrue(settings.multi_attach)

    def test_all_correct_type(self):
        settings = VolumeSettings(
            name='foo', description='desc', size=2, image_name='image',
            type_name='bar', availability_zone='zone1', multi_attach=True)

        self.assertEqual('foo', settings.name)
        self.assertEqual('desc', settings.description)
        self.assertEqual(2, settings.size)
        self.assertEqual('image', settings.image_name)
        self.assertEqual('bar', settings.type_name)
        self.assertEqual('zone1', settings.availability_zone)
        self.assertTrue(settings.multi_attach)

    def test_config_all(self):
        settings = VolumeSettings(
            **{'name': 'foo', 'description': 'desc', 'size': '2',
               'image_name': 'foo', 'type_name': 'bar',
               'availability_zone': 'zone1', 'multi_attach': 'true'})

        self.assertEqual('foo', settings.name)
        self.assertEqual('desc', settings.description)
        self.assertEqual(2, settings.size)
        self.assertEqual('foo', settings.image_name)
        self.assertEqual('bar', settings.type_name)
        self.assertEqual('zone1', settings.availability_zone)
        self.assertTrue(settings.multi_attach)


class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase):
    """
    Test for the CreateVolume class defined in create_volume.py
    """

    def setUp(self):
        """
        Instantiates the CreateVolume object that is responsible for
        downloading and creating an OS volume file within OpenStack
        """
        super(self.__class__, self).__start__()

        guid = uuid.uuid4()
        self.volume_settings = VolumeSettings(
            name=self.__class__.__name__ + '-' + str(guid))

        self.cinder = cinder_utils.cinder_client(self.os_creds)
        self.volume_creator = None

    def tearDown(self):
        """
        Cleans the volume and downloaded volume file
        """
        if self.volume_creator:
            self.volume_creator.clean()

        super(self.__class__, self).__clean__()

    def test_create_volume_simple(self):
        """
        Tests the creation of an OpenStack volume from a URL.
        """
        # Create Volume
        self.volume_creator = create_volume.OpenStackVolume(
            self.os_creds, self.volume_settings)
        created_volume = self.volume_creator.create(block=True)
        self.assertIsNotNone(created_volume)

        retrieved_volume = cinder_utils.get_volume(
            self.cinder, volume_settings=self.volume_settings)

        self.assertIsNotNone(retrieved_volume)
        self.assertEqual(created_volume.id, retrieved_volume.id)
        self.assertTrue(created_volume == retrieved_volume)

    def test_create_delete_volume(self):
        """
        Tests the creation then deletion of an OpenStack volume to ensure
        clean() does not raise an Exception.
        """
        # Create Volume
        self.volume_creator = create_volume.OpenStackVolume(
            self.os_creds, self.volume_settings)
        created_volume = self.volume_creator.create(block=True)
        self.assertIsNotNone(created_volume)

        retrieved_volume = cinder_utils.get_volume(
            self.cinder, volume_settings=self.volume_settings)
        self.assertIsNotNone(retrieved_volume)
        self.assertEqual(created_volume, retrieved_volume)

        # Delete Volume manually
        self.volume_creator.clean()

        self.assertIsNone(cinder_utils.get_volume(
            self.cinder, volume_settings=self.volume_settings))

        # Must not throw an exception when attempting to cleanup non-existent
        # volume
        self.volume_creator.clean()
        self.assertIsNone(self.volume_creator.get_volume())

    def test_create_same_volume(self):
        """
        Tests the creation of an OpenStack volume when one already exists.
        """
        # Create Volume
        self.volume_creator = OpenStackVolume(
            self.os_creds, self.volume_settings)
        volume1 = self.volume_creator.create(block=True)

        retrieved_volume = cinder_utils.get_volume(
            self.cinder, volume_settings=self.volume_settings)
        self.assertEqual(volume1, retrieved_volume)

        # Should be retrieving the instance data
        os_volume_2 = OpenStackVolume(
            self.os_creds, self.volume_settings)
        volume2 = os_volume_2.create(block=True)
        self.assertEqual(volume1, volume2)


class CreateVolumeWithTypeTests(OSIntegrationTestCase):
    """
    Test cases for the CreateVolume when attempting to associate it to a
    Volume Type
    """

    def setUp(self):
        super(self.__class__, self).__start__()

        guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
        self.volume_name = guid + '-vol'
        self.volume_type_name = guid + '-vol-type'

        self.volume_type_creator = OpenStackVolumeType(
            self.os_creds, VolumeTypeSettings(name=self.volume_type_name))
        self.volume_type_creator.create()
        self.volume_creator = None

    def tearDown(self):
        if self.volume_creator:
            self.volume_creator.clean()
        if self.volume_type_creator:
            self.volume_type_creator.clean()

        super(self.__class__, self).__clean__()

    def test_bad_volume_type(self):
        """
        Expect a NotFound to be raised when the volume type does not exist
        """
        self.volume_creator = OpenStackVolume(
            self.os_creds,
            VolumeSettings(name=self.volume_name, type_name='foo'))

        with self.assertRaises(NotFound):
            self.volume_creator.create()

    def test_valid_volume_type(self):
        """
        Expect a NotFound to be raised when the volume type does not exist
        """
        self.volume_creator = OpenStackVolume(
            self.os_creds,
            VolumeSettings(name=self.volume_name,
                           type_name=self.volume_type_name))

        created_volume = self.volume_creator.create()
        self.assertIsNotNone(created_volume)
        self.assertEqual(self.volume_type_name, created_volume.type)


class CreateVolumeWithImageTests(OSIntegrationTestCase):
    """
    Test cases for the CreateVolume when attempting to associate it to an Image
    """

    def setUp(self):
        super(self.__class__, self).__start__()

        guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
        self.volume_name = guid + '-vol'
        self.image_name = guid + '-image'

        os_image_settings = openstack_tests.cirros_image_settings(
            name=self.image_name, image_metadata=self.image_metadata)
        # Create Image
        self.image_creator = OpenStackImage(self.os_creds,
                                            os_image_settings)
        self.image_creator.create()
        self.volume_creator = None

    def tearDown(self):
        if self.volume_creator:
            try:
                self.volume_creator.clean()
            except:
                pass
        if self.image_creator:
            try:
                self.image_creator.clean()
            except:
                pass

        super(self.__class__, self).__clean__()

    def test_bad_image_name(self):
        """
        Expect a NotFound to be raised when the volume type does not exist
        """
        self.volume_creator = OpenStackVolume(
            self.os_creds,
            VolumeSettings(name=self.volume_name, image_name='foo'))

        with self.assertRaises(BadRequest):
            self.volume_creator.create(block=True)

    def test_valid_volume_image(self):
        """
        Expect a NotFound to be raised when the volume type does not exist
        """
        self.volume_creator = OpenStackVolume(
            self.os_creds,
            VolumeSettings(name=self.volume_name, image_name=self.image_name))

        created_volume = self.volume_creator.create(block=True)
        self.assertIsNotNone(created_volume)
        self.assertIsNone(created_volume.type)
        self.assertTrue(self.volume_creator.volume_active())