Added ability to set several quota settings upon project creation.
[snaps.git] / snaps / openstack / tests / create_project_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 import unittest
16 import uuid
17
18 from keystoneclient.exceptions import BadRequest
19
20 from snaps.config.security_group import SecurityGroupConfig
21 from snaps.config.user import UserConfig
22 from snaps.config.project import ProjectConfigError, ProjectConfig
23 from snaps.domain.project import ComputeQuotas, NetworkQuotas
24 from snaps.openstack.create_project import (
25     OpenStackProject, ProjectSettings)
26 from snaps.openstack.create_security_group import OpenStackSecurityGroup
27 from snaps.openstack.create_user import OpenStackUser
28 from snaps.openstack.tests.os_source_file_test import OSComponentTestCase
29 from snaps.openstack.utils import keystone_utils, nova_utils, neutron_utils
30
31 __author__ = 'spisarski'
32
33
34 class ProjectSettingsUnitTests(unittest.TestCase):
35     """
36     Tests the construction of the ProjectSettings class
37     """
38
39     def test_no_params(self):
40         with self.assertRaises(ProjectConfigError):
41             ProjectSettings()
42
43     def test_empty_config(self):
44         with self.assertRaises(ProjectConfigError):
45             ProjectSettings(**dict())
46
47     def test_name_only(self):
48         settings = ProjectSettings(name='foo')
49         self.assertEqual('foo', settings.name)
50         self.assertEqual('Default', settings.domain_name)
51         self.assertIsNone(settings.description)
52         self.assertTrue(settings.enabled)
53         self.assertEqual(list(), settings.users)
54
55     def test_config_with_name_only(self):
56         settings = ProjectSettings(**{'name': 'foo'})
57         self.assertEqual('foo', settings.name)
58         self.assertEqual('Default', settings.domain_name)
59         self.assertIsNone(settings.description)
60         self.assertTrue(settings.enabled)
61         self.assertEqual(list(), settings.users)
62
63     def test_all(self):
64         users = ['test1', 'test2']
65         settings = ProjectSettings(
66             name='foo', domain='bar', description='foobar', enabled=False,
67             users=users)
68         self.assertEqual('foo', settings.name)
69         self.assertEqual('bar', settings.domain_name)
70         self.assertEqual('foobar', settings.description)
71         self.assertFalse(settings.enabled)
72         self.assertEqual(users, settings.users)
73
74     def test_config_all(self):
75         users = ['test1', 'test2']
76         settings = ProjectSettings(
77             **{'name': 'foo', 'domain': 'bar', 'description': 'foobar',
78                'enabled': False, 'users': users})
79         self.assertEqual('foo', settings.name)
80         self.assertEqual('bar', settings.domain_name)
81         self.assertEqual('foobar', settings.description)
82         self.assertFalse(settings.enabled)
83         self.assertEqual(users, settings.users)
84
85
86 class CreateProjectSuccessTests(OSComponentTestCase):
87     """
88     Test for the CreateImage class defined in create_image.py
89     """
90
91     def setUp(self):
92         """
93         Instantiates the CreateImage object that is responsible for downloading
94         and creating an OS image file within OpenStack
95         """
96         guid = str(uuid.uuid4())[:-19]
97         guid = self.__class__.__name__ + '-' + guid
98         self.project_settings = ProjectConfig(
99             name=guid + '-name',
100             domain=self.os_creds.project_domain_name)
101
102         self.keystone = keystone_utils.keystone_client(
103             self.os_creds, self.os_session)
104
105         # Initialize for cleanup
106         self.project_creator = None
107
108     def tearDown(self):
109         """
110         Cleans the image and downloaded image file
111         """
112         if self.project_creator:
113             self.project_creator.clean()
114
115         super(self.__class__, self).__clean__()
116
117     def test_create_project_bad_domain(self):
118         """
119         Tests the creation of an OpenStack project with an invalid domain
120         value. This test will not do anything with a keystone v2.0 client.
121         """
122         if self.keystone.version != keystone_utils.V2_VERSION_STR:
123             self.project_settings.domain_name = 'foo'
124             self.project_creator = OpenStackProject(self.os_creds,
125                                                     self.project_settings)
126
127             with self.assertRaises(BadRequest):
128                 self.project_creator.create()
129
130     def test_create_project(self):
131         """
132         Tests the creation of an OpenStack project.
133         """
134         self.project_creator = OpenStackProject(self.os_creds,
135                                                 self.project_settings)
136         created_project = self.project_creator.create()
137         self.assertIsNotNone(created_project)
138
139         retrieved_project = keystone_utils.get_project(
140             keystone=self.keystone, project_settings=self.project_settings)
141         self.assertIsNotNone(retrieved_project)
142         self.assertEqual(created_project, retrieved_project)
143         self.assertTrue(validate_project(self.keystone, self.project_settings,
144                                          created_project))
145
146     def test_create_project_quota_override(self):
147         """
148         Tests the creation of an OpenStack project with new quotas.
149         """
150         quotas = {
151             'cores': 4, 'instances': 5, 'injected_files': 6,
152             'injected_file_content_bytes': 60000, 'ram': 70000, 'fixed_ips': 7,
153             'key_pairs': 8}
154         self.project_settings.quotas = quotas
155         self.project_creator = OpenStackProject(self.os_creds,
156                                                 self.project_settings)
157         created_project = self.project_creator.create()
158         self.assertIsNotNone(created_project)
159
160         retrieved_project = keystone_utils.get_project(
161             keystone=self.keystone, project_settings=self.project_settings)
162         self.assertIsNotNone(retrieved_project)
163         self.assertEqual(created_project, retrieved_project)
164         self.assertTrue(validate_project(self.keystone, self.project_settings,
165                                          created_project))
166
167         nova = nova_utils.nova_client(self.os_creds, self.os_session)
168         new_quotas = nova_utils.get_compute_quotas(nova, created_project.id)
169
170         self.assertEqual(4, new_quotas.cores)
171         self.assertEqual(5, new_quotas.instances)
172         self.assertEqual(6, new_quotas.injected_files)
173         self.assertEqual(60000, new_quotas.injected_file_content_bytes)
174         self.assertEqual(70000, new_quotas.ram)
175         self.assertEqual(7, new_quotas.fixed_ips)
176         self.assertEqual(8, new_quotas.key_pairs)
177
178     def test_create_project_2x(self):
179         """
180         Tests the creation of an OpenStack project twice to ensure it only
181         creates one.
182         """
183         self.project_creator = OpenStackProject(self.os_creds,
184                                                 self.project_settings)
185         created_project = self.project_creator.create()
186         self.assertIsNotNone(created_project)
187
188         retrieved_project = keystone_utils.get_project(
189             keystone=self.keystone, project_settings=self.project_settings)
190         self.assertIsNotNone(retrieved_project)
191         self.assertEqual(created_project, retrieved_project)
192
193         project2 = OpenStackProject(self.os_creds,
194                                     self.project_settings).create()
195         self.assertEqual(retrieved_project, project2)
196         self.assertTrue(validate_project(self.keystone, self.project_settings,
197                                          created_project))
198
199     def test_create_delete_project(self):
200         """
201         Tests the creation of an OpenStack project, it's deletion, then cleanup
202         """
203         # Create Image
204         self.project_creator = OpenStackProject(self.os_creds,
205                                                 self.project_settings)
206         created_project = self.project_creator.create()
207         self.assertIsNotNone(created_project)
208
209         keystone_utils.delete_project(self.keystone, created_project)
210
211         self.project_creator.clean()
212
213         self.assertIsNone(self.project_creator.get_project())
214
215         self.assertTrue(validate_project(self.keystone, self.project_settings,
216                                          created_project))
217
218     def test_update_quotas(self):
219         """
220         Tests the creation of an OpenStack project where the quotas get
221         updated.
222         """
223         self.project_creator = OpenStackProject(self.os_creds,
224                                                 self.project_settings)
225         created_project = self.project_creator.create()
226         self.assertIsNotNone(created_project)
227
228         retrieved_project = keystone_utils.get_project(
229             keystone=self.keystone, project_settings=self.project_settings)
230         self.assertIsNotNone(retrieved_project)
231         self.assertEqual(created_project, retrieved_project)
232         self.assertTrue(validate_project(self.keystone, self.project_settings,
233                                          created_project))
234
235         update_compute_quotas = ComputeQuotas(
236             **{'metadata_items': 64, 'cores': 5, 'instances': 5,
237                'injected_files': 3, 'injected_file_content_bytes': 5120,
238                'ram': 25600, 'fixed_ips': 100, 'key_pairs': 50})
239         self.project_creator.update_compute_quotas(update_compute_quotas)
240
241         update_network_quotas = NetworkQuotas(
242             **{'security_group': 5, 'security_group_rule': 50,
243                'floatingip': 25, 'network': 5, 'port': 25, 'router': 6,
244                'subnet': 7})
245         self.project_creator.update_network_quotas(update_network_quotas)
246
247         self.assertEqual(update_compute_quotas,
248                          self.project_creator.get_compute_quotas())
249         self.assertEqual(update_network_quotas,
250                          self.project_creator.get_network_quotas())
251
252         nova = nova_utils.nova_client(self.os_creds, self.os_session)
253         new_compute_quotas = nova_utils.get_compute_quotas(
254             nova, self.project_creator.get_project().id)
255         self.assertEqual(update_compute_quotas, new_compute_quotas)
256
257         neutron = neutron_utils.neutron_client(self.os_creds, self.os_session)
258         new_network_quotas = neutron_utils.get_network_quotas(
259             neutron, self.project_creator.get_project().id)
260         self.assertEqual(update_network_quotas, new_network_quotas)
261
262
263 class CreateProjectUserTests(OSComponentTestCase):
264     """
265     Test for the CreateImage class defined in create_image.py
266     """
267
268     def setUp(self):
269         """
270         Instantiates the CreateImage object that is responsible for downloading
271         and creating an OS image file within OpenStack
272         """
273         guid = str(uuid.uuid4())[:-19]
274         self.guid = self.__class__.__name__ + '-' + guid
275         self.project_settings = ProjectConfig(
276             name=self.guid + '-name',
277             domain=self.os_creds.project_domain_name)
278
279         self.keystone = keystone_utils.keystone_client(
280             self.os_creds, self.os_session)
281
282         # Initialize for cleanup
283         self.project_creator = None
284         self.user_creators = list()
285
286         self.sec_grp_creators = list()
287
288     def tearDown(self):
289         """
290         Cleans the image and downloaded image file
291         """
292         for sec_grp_creator in self.sec_grp_creators:
293             sec_grp_creator.clean()
294
295         for user_creator in self.user_creators:
296             user_creator.clean()
297
298         if self.project_creator:
299             self.project_creator.clean()
300
301         super(self.__class__, self).__clean__()
302
303     def test_create_project_sec_grp_one_user(self):
304         """
305         Tests the creation of an OpenStack object to a project with a new users
306         and to create a security group
307         """
308         self.project_creator = OpenStackProject(self.os_creds,
309                                                 self.project_settings)
310         created_project = self.project_creator.create()
311         self.assertIsNotNone(created_project)
312
313         user_creator = OpenStackUser(
314             self.os_creds, UserConfig(
315                 name=self.guid + '-user',
316                 password=self.guid,
317                 roles={'admin':  self.project_settings.name},
318                 domain_name=self.os_creds.user_domain_name))
319         self.project_creator.assoc_user(user_creator.create())
320         self.user_creators.append(user_creator)
321
322         sec_grp_os_creds = user_creator.get_os_creds(
323             self.project_creator.get_project().name)
324         sec_grp_creator = OpenStackSecurityGroup(
325             sec_grp_os_creds, SecurityGroupConfig(
326                 name=self.guid + '-name', description='hello group'))
327         sec_grp = sec_grp_creator.create()
328         self.assertIsNotNone(sec_grp)
329         self.sec_grp_creators.append(sec_grp_creator)
330
331         self.assertEqual(self.project_creator.get_project().id,
332                          sec_grp.project_id)
333
334     def test_create_project_sec_grp_two_users(self):
335         """
336         Tests the creation of an OpenStack object to a project with two new
337         users and use each user to create a security group
338         """
339         self.project_creator = OpenStackProject(self.os_creds,
340                                                 self.project_settings)
341         created_project = self.project_creator.create()
342         self.assertIsNotNone(created_project)
343
344         user_creator_1 = OpenStackUser(
345             self.os_creds, UserConfig(
346                 name=self.guid + '-user1', password=self.guid,
347                 roles={'admin': self.project_settings.name},
348                 domain_name=self.os_creds.user_domain_name))
349         self.project_creator.assoc_user(user_creator_1.create())
350         self.user_creators.append(user_creator_1)
351
352         user_creator_2 = OpenStackUser(
353             self.os_creds, UserConfig(
354                 name=self.guid + '-user2', password=self.guid,
355                 roles={'admin': self.project_settings.name},
356                 domain_name=self.os_creds.user_domain_name))
357         self.project_creator.assoc_user(user_creator_2.create())
358         self.user_creators.append(user_creator_2)
359
360         ctr = 0
361         for user_creator in self.user_creators:
362             ctr += 1
363             sec_grp_os_creds = user_creator.get_os_creds(
364                 self.project_creator.get_project().name)
365
366             sec_grp_creator = OpenStackSecurityGroup(
367                 sec_grp_os_creds,
368                 SecurityGroupConfig(
369                     name=self.guid + '-name', description='hello group'))
370             sec_grp = sec_grp_creator.create()
371             self.assertIsNotNone(sec_grp)
372             self.sec_grp_creators.append(sec_grp_creator)
373
374             self.assertEqual(self.project_creator.get_project().id,
375                              sec_grp.project_id)
376
377
378 def validate_project(keystone, project_settings, project):
379     """
380     Validates that the project_settings used to create the project have been
381     properly set
382     :param keystone: the keystone client for version checking
383     :param project_settings: the settings used to create the project
384     :param project: the SNAPS-OO Project domain object
385     :return: T/F
386     """
387     if keystone.version == keystone_utils.V2_VERSION_STR:
388         return project_settings.name == project.name
389     else:
390         domain = keystone_utils.get_domain_by_id(keystone, project.domain_id)
391         return (project_settings.name == project.name and
392                 project_settings.domain_name == domain.name)