91b52b1ecf3ddb32e23e6ea156a15d17283f3461
[snaps.git] / snaps / openstack / tests / create_volume_tests.py
1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 #                    and others.  All rights reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 from cinderclient.exceptions import NotFound, BadRequest
16
17 from snaps.config.volume_type import VolumeTypeConfig
18 from snaps.openstack.create_image import OpenStackImage
19 from snaps.openstack.create_volume_type import OpenStackVolumeType
20 from snaps.openstack.tests import openstack_tests
21
22 try:
23     from urllib.request import URLError
24 except ImportError:
25     from urllib2 import URLError
26
27 import logging
28 import unittest
29 import uuid
30
31 from snaps.openstack.create_volume import (
32     VolumeSettings, VolumeSettingsError, OpenStackVolume)
33 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
34 from snaps.openstack.utils import cinder_utils
35
36 __author__ = 'spisarski'
37
38 logger = logging.getLogger('create_volume_tests')
39
40
41 class VolumeSettingsUnitTests(unittest.TestCase):
42     """
43     Tests the construction of the VolumeSettings class
44     """
45
46     def test_no_params(self):
47         with self.assertRaises(VolumeSettingsError):
48             VolumeSettings()
49
50     def test_empty_config(self):
51         with self.assertRaises(VolumeSettingsError):
52             VolumeSettings(**dict())
53
54     def test_name_only(self):
55         settings = VolumeSettings(name='foo')
56         self.assertEqual('foo', settings.name)
57         self.assertIsNone(settings.description)
58         self.assertEquals(1, settings.size)
59         self.assertIsNone(settings.image_name)
60         self.assertIsNone(settings.type_name)
61         self.assertIsNone(settings.availability_zone)
62         self.assertFalse(settings.multi_attach)
63
64     def test_config_with_name_only(self):
65         settings = VolumeSettings(**{'name': 'foo'})
66         self.assertEqual('foo', settings.name)
67         self.assertIsNone(settings.description)
68         self.assertEquals(1, settings.size)
69         self.assertIsNone(settings.image_name)
70         self.assertIsNone(settings.type_name)
71         self.assertIsNone(settings.availability_zone)
72         self.assertFalse(settings.multi_attach)
73
74     def test_all_strings(self):
75         settings = VolumeSettings(
76             name='foo', description='desc', size='2', image_name='image',
77             type_name='type', availability_zone='zone1', multi_attach='true')
78
79         self.assertEqual('foo', settings.name)
80         self.assertEqual('desc', settings.description)
81         self.assertEqual(2, settings.size)
82         self.assertEqual('image', settings.image_name)
83         self.assertEqual('type', settings.type_name)
84         self.assertEqual('zone1', settings.availability_zone)
85         self.assertTrue(settings.multi_attach)
86
87     def test_all_correct_type(self):
88         settings = VolumeSettings(
89             name='foo', description='desc', size=2, image_name='image',
90             type_name='bar', availability_zone='zone1', multi_attach=True)
91
92         self.assertEqual('foo', settings.name)
93         self.assertEqual('desc', settings.description)
94         self.assertEqual(2, settings.size)
95         self.assertEqual('image', settings.image_name)
96         self.assertEqual('bar', settings.type_name)
97         self.assertEqual('zone1', settings.availability_zone)
98         self.assertTrue(settings.multi_attach)
99
100     def test_config_all(self):
101         settings = VolumeSettings(
102             **{'name': 'foo', 'description': 'desc', 'size': '2',
103                'image_name': 'foo', 'type_name': 'bar',
104                'availability_zone': 'zone1', 'multi_attach': 'true'})
105
106         self.assertEqual('foo', settings.name)
107         self.assertEqual('desc', settings.description)
108         self.assertEqual(2, settings.size)
109         self.assertEqual('foo', settings.image_name)
110         self.assertEqual('bar', settings.type_name)
111         self.assertEqual('zone1', settings.availability_zone)
112         self.assertTrue(settings.multi_attach)
113
114
115 class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase):
116     """
117     Test for the CreateVolume class defined in create_volume.py
118     """
119
120     def setUp(self):
121         """
122         Instantiates the CreateVolume object that is responsible for
123         downloading and creating an OS volume file within OpenStack
124         """
125         super(self.__class__, self).__start__()
126
127         guid = uuid.uuid4()
128         self.volume_settings = VolumeSettings(
129             name=self.__class__.__name__ + '-' + str(guid))
130
131         self.cinder = cinder_utils.cinder_client(self.os_creds)
132         self.volume_creator = None
133
134     def tearDown(self):
135         """
136         Cleans the volume and downloaded volume file
137         """
138         if self.volume_creator:
139             self.volume_creator.clean()
140
141         super(self.__class__, self).__clean__()
142
143     def test_create_volume_simple(self):
144         """
145         Tests the creation of a simple OpenStack volume.
146         """
147         # Create Volume
148         self.volume_creator = OpenStackVolume(
149             self.os_creds, self.volume_settings)
150         created_volume = self.volume_creator.create(block=True)
151         self.assertIsNotNone(created_volume)
152
153         retrieved_volume = cinder_utils.get_volume(
154             self.cinder, volume_settings=self.volume_settings)
155
156         self.assertIsNotNone(retrieved_volume)
157         self.assertEqual(created_volume.id, retrieved_volume.id)
158         self.assertTrue(created_volume == retrieved_volume)
159
160     def test_create_delete_volume(self):
161         """
162         Tests the creation then deletion of an OpenStack volume to ensure
163         clean() does not raise an Exception.
164         """
165         # Create Volume
166         self.volume_creator = OpenStackVolume(
167             self.os_creds, self.volume_settings)
168         created_volume = self.volume_creator.create(block=True)
169         self.assertIsNotNone(created_volume)
170
171         retrieved_volume = cinder_utils.get_volume(
172             self.cinder, volume_settings=self.volume_settings)
173         self.assertIsNotNone(retrieved_volume)
174         self.assertEqual(created_volume, retrieved_volume)
175
176         # Delete Volume manually
177         self.volume_creator.clean()
178
179         self.assertIsNone(cinder_utils.get_volume(
180             self.cinder, volume_settings=self.volume_settings))
181
182         # Must not throw an exception when attempting to cleanup non-existent
183         # volume
184         self.volume_creator.clean()
185         self.assertIsNone(self.volume_creator.get_volume())
186
187     def test_create_same_volume(self):
188         """
189         Tests the creation of an OpenStack volume when one already exists.
190         """
191         # Create Volume
192         self.volume_creator = OpenStackVolume(
193             self.os_creds, self.volume_settings)
194         volume1 = self.volume_creator.create(block=True)
195
196         retrieved_volume = cinder_utils.get_volume(
197             self.cinder, volume_settings=self.volume_settings)
198         self.assertEqual(volume1, retrieved_volume)
199
200         # Should be retrieving the instance data
201         os_volume_2 = OpenStackVolume(
202             self.os_creds, self.volume_settings)
203         volume2 = os_volume_2.create(block=True)
204         self.assertEqual(volume1, volume2)
205
206
207 class CreateSimpleVolumeFailureTests(OSIntegrationTestCase):
208     """
209     Test for the CreateVolume class defined in create_volume.py
210     """
211
212     def setUp(self):
213         """
214         Instantiates the CreateVolume object that is responsible for
215         downloading and creating an OS volume file within OpenStack
216         """
217         super(self.__class__, self).__start__()
218
219         self.guid = uuid.uuid4()
220         self.cinder = cinder_utils.cinder_client(self.os_creds)
221         self.volume_creator = None
222
223     def tearDown(self):
224         """
225         Cleans the volume and downloaded volume file
226         """
227         if self.volume_creator:
228             self.volume_creator.clean()
229
230         super(self.__class__, self).__clean__()
231
232     def test_create_volume_bad_size(self):
233         """
234         Tests the creation of an OpenStack volume with a negative size to
235         ensure it raises a BadRequest exception.
236         """
237         volume_settings = VolumeSettings(
238             name=self.__class__.__name__ + '-' + str(self.guid), size=-1)
239
240         # Create Volume
241         self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
242
243         with self.assertRaises(BadRequest):
244             self.volume_creator.create(block=True)
245
246     def test_create_volume_bad_type(self):
247         """
248         Tests the creation of an OpenStack volume with a type that does not
249         exist to ensure it raises a NotFound exception.
250         """
251         volume_settings = VolumeSettings(
252             name=self.__class__.__name__ + '-' + str(self.guid),
253             type_name='foo')
254
255         # Create Volume
256         self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
257
258         with self.assertRaises(NotFound):
259             self.volume_creator.create(block=True)
260
261     def test_create_volume_bad_image(self):
262         """
263         Tests the creation of an OpenStack volume with an image that does not
264         exist to ensure it raises a BadRequest exception.
265         """
266         volume_settings = VolumeSettings(
267             name=self.__class__.__name__ + '-' + str(self.guid),
268             image_name='foo')
269
270         # Create Volume
271         self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
272
273         with self.assertRaises(BadRequest):
274             self.volume_creator.create(block=True)
275
276     def test_create_volume_bad_zone(self):
277         """
278         Tests the creation of an OpenStack volume with an availability zone
279         that does not exist to ensure it raises a BadRequest exception.
280         """
281         volume_settings = VolumeSettings(
282             name=self.__class__.__name__ + '-' + str(self.guid),
283             availability_zone='foo')
284
285         # Create Volume
286         self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
287
288         with self.assertRaises(BadRequest):
289             self.volume_creator.create(block=True)
290
291
292 class CreateVolumeWithTypeTests(OSIntegrationTestCase):
293     """
294     Test cases for the CreateVolume when attempting to associate it to a
295     Volume Type
296     """
297
298     def setUp(self):
299         super(self.__class__, self).__start__()
300
301         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
302         self.volume_name = guid + '-vol'
303         self.volume_type_name = guid + '-vol-type'
304
305         self.volume_type_creator = OpenStackVolumeType(
306             self.os_creds, VolumeTypeConfig(name=self.volume_type_name))
307         self.volume_type_creator.create()
308         self.volume_creator = None
309
310     def tearDown(self):
311         if self.volume_creator:
312             self.volume_creator.clean()
313         if self.volume_type_creator:
314             self.volume_type_creator.clean()
315
316         super(self.__class__, self).__clean__()
317
318     def test_bad_volume_type(self):
319         """
320         Expect a NotFound to be raised when the volume type does not exist
321         """
322         self.volume_creator = OpenStackVolume(
323             self.os_creds,
324             VolumeSettings(name=self.volume_name, type_name='foo'))
325
326         with self.assertRaises(NotFound):
327             self.volume_creator.create()
328
329     def test_valid_volume_type(self):
330         """
331         Expect a NotFound to be raised when the volume type does not exist
332         """
333         self.volume_creator = OpenStackVolume(
334             self.os_creds,
335             VolumeSettings(name=self.volume_name,
336                            type_name=self.volume_type_name))
337
338         created_volume = self.volume_creator.create(block=True)
339         self.assertIsNotNone(created_volume)
340         self.assertEqual(self.volume_type_name, created_volume.type)
341
342
343 class CreateVolumeWithImageTests(OSIntegrationTestCase):
344     """
345     Test cases for the CreateVolume when attempting to associate it to an Image
346     """
347
348     def setUp(self):
349         super(self.__class__, self).__start__()
350
351         self.cinder = cinder_utils.cinder_client(self.os_creds)
352
353         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
354         self.volume_name = guid + '-vol'
355         self.image_name = guid + '-image'
356
357         os_image_settings = openstack_tests.cirros_image_settings(
358             name=self.image_name, image_metadata=self.image_metadata)
359         # Create Image
360         self.image_creator = OpenStackImage(self.os_creds,
361                                             os_image_settings)
362         self.image_creator.create()
363         self.volume_creator = None
364
365     def tearDown(self):
366         if self.volume_creator:
367             try:
368                 self.volume_creator.clean()
369             except:
370                 pass
371         if self.image_creator:
372             try:
373                 self.image_creator.clean()
374             except:
375                 pass
376
377         super(self.__class__, self).__clean__()
378
379     def test_bad_image_name(self):
380         """
381         Tests OpenStackVolume#create() method to ensure a volume is NOT created
382         when associating it to an invalid image name
383         """
384         self.volume_creator = OpenStackVolume(
385             self.os_creds,
386             VolumeSettings(name=self.volume_name, image_name='foo'))
387
388         with self.assertRaises(BadRequest):
389             self.volume_creator.create(block=True)
390
391     def test_valid_volume_image(self):
392         """
393         Tests OpenStackVolume#create() method to ensure a volume is NOT created
394         when associating it to an invalid image name
395         """
396         self.volume_creator = OpenStackVolume(
397             self.os_creds,
398             VolumeSettings(name=self.volume_name, image_name=self.image_name))
399
400         created_volume = self.volume_creator.create(block=True)
401         self.assertIsNotNone(created_volume)
402         self.assertEqual(
403             self.volume_creator.volume_settings.name, created_volume.name)
404         self.assertTrue(self.volume_creator.volume_active())
405
406         retrieved_volume = cinder_utils.get_volume_by_id(
407             self.cinder, created_volume.id)
408
409         self.assertEqual(created_volume, retrieved_volume)