Changed pattern on how objects lookup themselves by name and project.
[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 import VolumeConfig, VolumeConfigError
18 from snaps.config.volume_type import VolumeTypeConfig
19 from snaps.openstack.create_image import OpenStackImage
20 from snaps.openstack.create_volume_type import OpenStackVolumeType
21 from snaps.openstack.tests import openstack_tests
22
23 try:
24     from urllib.request import URLError
25 except ImportError:
26     from urllib2 import URLError
27
28 import logging
29 import unittest
30 import uuid
31
32 from snaps.openstack.create_volume import (
33     VolumeSettings, OpenStackVolume)
34 from snaps.openstack.tests.os_source_file_test import OSIntegrationTestCase
35 from snaps.openstack.utils import cinder_utils
36
37 __author__ = 'spisarski'
38
39 logger = logging.getLogger('create_volume_tests')
40
41
42 class VolumeSettingsUnitTests(unittest.TestCase):
43     """
44     Tests the construction of the VolumeSettings class
45     """
46
47     def test_no_params(self):
48         with self.assertRaises(VolumeConfigError):
49             VolumeSettings()
50
51     def test_empty_config(self):
52         with self.assertRaises(VolumeConfigError):
53             VolumeSettings(**dict())
54
55     def test_name_only(self):
56         settings = VolumeSettings(name='foo')
57         self.assertEqual('foo', settings.name)
58         self.assertIsNone(settings.description)
59         self.assertEquals(1, settings.size)
60         self.assertIsNone(settings.image_name)
61         self.assertIsNone(settings.type_name)
62         self.assertIsNone(settings.availability_zone)
63         self.assertFalse(settings.multi_attach)
64
65     def test_config_with_name_only(self):
66         settings = VolumeSettings(**{'name': 'foo'})
67         self.assertEqual('foo', settings.name)
68         self.assertIsNone(settings.description)
69         self.assertEquals(1, settings.size)
70         self.assertIsNone(settings.image_name)
71         self.assertIsNone(settings.type_name)
72         self.assertIsNone(settings.availability_zone)
73         self.assertFalse(settings.multi_attach)
74
75     def test_all_strings(self):
76         settings = VolumeSettings(
77             name='foo', description='desc', size='2', image_name='image',
78             type_name='type', availability_zone='zone1', multi_attach='true')
79
80         self.assertEqual('foo', settings.name)
81         self.assertEqual('desc', settings.description)
82         self.assertEqual(2, settings.size)
83         self.assertEqual('image', settings.image_name)
84         self.assertEqual('type', settings.type_name)
85         self.assertEqual('zone1', settings.availability_zone)
86         self.assertTrue(settings.multi_attach)
87
88     def test_all_correct_type(self):
89         settings = VolumeSettings(
90             name='foo', description='desc', size=2, image_name='image',
91             type_name='bar', availability_zone='zone1', multi_attach=True)
92
93         self.assertEqual('foo', settings.name)
94         self.assertEqual('desc', settings.description)
95         self.assertEqual(2, settings.size)
96         self.assertEqual('image', settings.image_name)
97         self.assertEqual('bar', settings.type_name)
98         self.assertEqual('zone1', settings.availability_zone)
99         self.assertTrue(settings.multi_attach)
100
101     def test_config_all(self):
102         settings = VolumeSettings(
103             **{'name': 'foo', 'description': 'desc', 'size': '2',
104                'image_name': 'foo', 'type_name': 'bar',
105                'availability_zone': 'zone1', 'multi_attach': 'true'})
106
107         self.assertEqual('foo', settings.name)
108         self.assertEqual('desc', settings.description)
109         self.assertEqual(2, settings.size)
110         self.assertEqual('foo', settings.image_name)
111         self.assertEqual('bar', settings.type_name)
112         self.assertEqual('zone1', settings.availability_zone)
113         self.assertTrue(settings.multi_attach)
114
115
116 class CreateSimpleVolumeSuccessTests(OSIntegrationTestCase):
117     """
118     Test for the CreateVolume class defined in create_volume.py
119     """
120
121     def setUp(self):
122         """
123         Instantiates the CreateVolume object that is responsible for
124         downloading and creating an OS volume file within OpenStack
125         """
126         super(self.__class__, self).__start__()
127
128         guid = uuid.uuid4()
129         self.volume_settings = VolumeConfig(
130             name=self.__class__.__name__ + '-' + str(guid))
131
132         self.cinder = cinder_utils.cinder_client(self.os_creds)
133         self.volume_creator = None
134
135     def tearDown(self):
136         """
137         Cleans the volume and downloaded volume file
138         """
139         if self.volume_creator:
140             self.volume_creator.clean()
141
142         super(self.__class__, self).__clean__()
143
144     def test_create_volume_simple(self):
145         """
146         Tests the creation of a simple OpenStack volume.
147         """
148         # Create Volume
149         self.volume_creator = OpenStackVolume(
150             self.os_creds, self.volume_settings)
151         created_volume = self.volume_creator.create(block=True)
152         self.assertIsNotNone(created_volume)
153
154         retrieved_volume = cinder_utils.get_volume(
155             self.cinder, volume_settings=self.volume_settings)
156
157         self.assertIsNotNone(retrieved_volume)
158         self.assertEqual(created_volume.id, retrieved_volume.id)
159         self.assertTrue(created_volume == retrieved_volume)
160
161     def test_create_delete_volume(self):
162         """
163         Tests the creation then deletion of an OpenStack volume to ensure
164         clean() does not raise an Exception.
165         """
166         # Create Volume
167         self.volume_creator = OpenStackVolume(
168             self.os_creds, self.volume_settings)
169         created_volume = self.volume_creator.create(block=True)
170         self.assertIsNotNone(created_volume)
171
172         retrieved_volume = cinder_utils.get_volume(
173             self.cinder, volume_settings=self.volume_settings)
174         self.assertIsNotNone(retrieved_volume)
175         self.assertEqual(created_volume, retrieved_volume)
176
177         # Delete Volume manually
178         self.volume_creator.clean()
179
180         self.assertIsNone(cinder_utils.get_volume(
181             self.cinder, volume_settings=self.volume_settings))
182
183         # Must not throw an exception when attempting to cleanup non-existent
184         # volume
185         self.volume_creator.clean()
186         self.assertIsNone(self.volume_creator.get_volume())
187
188     def test_create_same_volume(self):
189         """
190         Tests the creation of an OpenStack volume when one already exists.
191         """
192         # Create Volume
193         self.volume_creator = OpenStackVolume(
194             self.os_creds, self.volume_settings)
195         volume1 = self.volume_creator.create(block=True)
196
197         retrieved_volume = cinder_utils.get_volume(
198             self.cinder, volume_settings=self.volume_settings)
199         self.assertEqual(volume1, retrieved_volume)
200
201         # Should be retrieving the instance data
202         os_volume_2 = OpenStackVolume(
203             self.os_creds, self.volume_settings)
204         volume2 = os_volume_2.create(block=True)
205         self.assertEqual(volume1, volume2)
206
207
208 class CreateSimpleVolumeFailureTests(OSIntegrationTestCase):
209     """
210     Test for the CreateVolume class defined in create_volume.py
211     """
212
213     def setUp(self):
214         """
215         Instantiates the CreateVolume object that is responsible for
216         downloading and creating an OS volume file within OpenStack
217         """
218         super(self.__class__, self).__start__()
219
220         self.guid = uuid.uuid4()
221         self.cinder = cinder_utils.cinder_client(self.os_creds)
222         self.volume_creator = None
223
224     def tearDown(self):
225         """
226         Cleans the volume and downloaded volume file
227         """
228         if self.volume_creator:
229             self.volume_creator.clean()
230
231         super(self.__class__, self).__clean__()
232
233     def test_create_volume_bad_size(self):
234         """
235         Tests the creation of an OpenStack volume with a negative size to
236         ensure it raises a BadRequest exception.
237         """
238         volume_settings = VolumeConfig(
239             name=self.__class__.__name__ + '-' + str(self.guid), size=-1)
240
241         # Create Volume
242         self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
243
244         with self.assertRaises(BadRequest):
245             self.volume_creator.create(block=True)
246
247     def test_create_volume_bad_type(self):
248         """
249         Tests the creation of an OpenStack volume with a type that does not
250         exist to ensure it raises a NotFound exception.
251         """
252         volume_settings = VolumeConfig(
253             name=self.__class__.__name__ + '-' + str(self.guid),
254             type_name='foo')
255
256         # Create Volume
257         self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
258
259         with self.assertRaises(NotFound):
260             self.volume_creator.create(block=True)
261
262     def test_create_volume_bad_image(self):
263         """
264         Tests the creation of an OpenStack volume with an image that does not
265         exist to ensure it raises a BadRequest exception.
266         """
267         volume_settings = VolumeConfig(
268             name=self.__class__.__name__ + '-' + str(self.guid),
269             image_name='foo')
270
271         # Create Volume
272         self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
273
274         with self.assertRaises(BadRequest):
275             self.volume_creator.create(block=True)
276
277     def test_create_volume_bad_zone(self):
278         """
279         Tests the creation of an OpenStack volume with an availability zone
280         that does not exist to ensure it raises a BadRequest exception.
281         """
282         volume_settings = VolumeConfig(
283             name=self.__class__.__name__ + '-' + str(self.guid),
284             availability_zone='foo')
285
286         # Create Volume
287         self.volume_creator = OpenStackVolume(self.os_creds, volume_settings)
288
289         with self.assertRaises(BadRequest):
290             self.volume_creator.create(block=True)
291
292
293 class CreateVolumeWithTypeTests(OSIntegrationTestCase):
294     """
295     Test cases for the CreateVolume when attempting to associate it to a
296     Volume Type
297     """
298
299     def setUp(self):
300         super(self.__class__, self).__start__()
301
302         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
303         self.volume_name = guid + '-vol'
304         self.volume_type_name = guid + '-vol-type'
305
306         self.volume_type_creator = OpenStackVolumeType(
307             self.admin_os_creds, VolumeTypeConfig(name=self.volume_type_name))
308         self.volume_type_creator.create()
309         self.volume_creator = None
310
311     def tearDown(self):
312         if self.volume_creator:
313             self.volume_creator.clean()
314         if self.volume_type_creator:
315             self.volume_type_creator.clean()
316
317         super(self.__class__, self).__clean__()
318
319     def test_bad_volume_type(self):
320         """
321         Expect a NotFound to be raised when the volume type does not exist
322         """
323         self.volume_creator = OpenStackVolume(
324             self.os_creds,
325             VolumeConfig(name=self.volume_name, type_name='foo'))
326
327         with self.assertRaises(NotFound):
328             self.volume_creator.create()
329
330     def test_valid_volume_type(self):
331         """
332         Expect a NotFound to be raised when the volume type does not exist
333         """
334         self.volume_creator = OpenStackVolume(
335             self.admin_os_creds, VolumeConfig(
336                 name=self.volume_name, 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             VolumeConfig(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             VolumeConfig(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)