Added ability to set several quota settings upon project creation.
[snaps.git] / snaps / openstack / create_project.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 logging
16
17 from keystoneclient.exceptions import NotFound, Conflict
18
19 from snaps.config.project import ProjectConfig
20 from snaps.openstack.openstack_creator import OpenStackIdentityObject
21 from snaps.openstack.utils import keystone_utils, neutron_utils, nova_utils
22
23 __author__ = 'spisarski'
24
25 logger = logging.getLogger('create_image')
26
27
28 class OpenStackProject(OpenStackIdentityObject):
29     """
30     Class responsible for managing a project/project in OpenStack
31     """
32
33     def __init__(self, os_creds, project_settings):
34         """
35         Constructor
36         :param os_creds: The OpenStack connection credentials
37         :param project_settings: The project's settings
38         :return:
39         """
40         super(self.__class__, self).__init__(os_creds)
41
42         self.project_settings = project_settings
43         self.__project = None
44         self.__role = None
45         self.__role_name = self.project_settings.name + '-role'
46
47     def initialize(self):
48         """
49         Loads the existing Project object if it exists
50         :return: The Project domain object
51         """
52         super(self.__class__, self).initialize()
53
54         self.__project = keystone_utils.get_project(
55             keystone=self._keystone, project_settings=self.project_settings)
56         return self.__project
57
58     def create(self):
59         """
60         Creates a Project/Tenant in OpenStack if it does not already exist
61         :return: The Project domain object
62         """
63         self.initialize()
64
65         if not self.__project:
66             self.__project = keystone_utils.create_project(
67                 self._keystone, self.project_settings)
68             for username in self.project_settings.users:
69                 user = keystone_utils.get_user(self._keystone, username)
70                 if user:
71                     try:
72                         self.assoc_user(user)
73                     except Conflict as e:
74                         logger.warn('Unable to associate user %s due to %s',
75                                     user.name, e)
76
77             if self.project_settings.quotas:
78                 quota_dict = self.project_settings.quotas
79                 nova = nova_utils.nova_client(self._os_creds, self._os_session)
80                 quotas = nova_utils.get_compute_quotas(nova, self.__project.id)
81                 if quotas:
82                     if 'cores' in quota_dict:
83                         quotas.cores = quota_dict['cores']
84                     if 'instances' in quota_dict:
85                         quotas.instances = quota_dict['instances']
86                     if 'injected_files' in quota_dict:
87                         quotas.injected_files = quota_dict['injected_files']
88                     if 'injected_file_content_bytes' in quota_dict:
89                         quotas.injected_file_content_bytes = \
90                             quota_dict['injected_file_content_bytes']
91                     if 'ram' in quota_dict:
92                         quotas.ram = quota_dict['ram']
93                     if 'fixed_ips' in quota_dict:
94                         quotas.fixed_ips = quota_dict['fixed_ips']
95                     if 'key_pairs' in quota_dict:
96                         quotas.key_pairs = quota_dict['key_pairs']
97
98                     nova_utils.update_quotas(nova, self.__project.id, quotas)
99
100         return self.__project
101
102     def clean(self):
103         """
104         Cleanse environment of all artifacts
105         :return: void
106         """
107         if self.__project:
108             # Delete security group 'default' if exists
109             neutron = neutron_utils.neutron_client(
110                 self._os_creds, self._os_session)
111             try:
112                 default_sec_grp = neutron_utils.get_security_group(
113                     neutron, self._keystone, sec_grp_name='default',
114                     project_name=self.__project.name)
115                 if default_sec_grp:
116                     try:
117                         neutron_utils.delete_security_group(
118                             neutron, default_sec_grp)
119                     except:
120                         pass
121             finally:
122                 neutron.httpclient.session.session.close()
123
124             # Delete Project
125             try:
126                 keystone_utils.delete_project(self._keystone, self.__project)
127             except NotFound:
128                 pass
129             self.__project = None
130
131         if self.__role:
132             try:
133                 keystone_utils.delete_role(self._keystone, self.__role)
134             except NotFound:
135                 pass
136             self.__project = None
137
138         # Final role check in case init was done from an existing instance
139         role = keystone_utils.get_role_by_name(
140             self._keystone, self.__role_name)
141         if role:
142             keystone_utils.delete_role(self._keystone, role)
143
144         super(self.__class__, self).clean()
145
146     def get_project(self):
147         """
148         Returns the OpenStack project object populated on create()
149         :return:
150         """
151         return self.__project
152
153     def assoc_user(self, user):
154         """
155         The user object to associate with the project
156         :param user: the OpenStack User domain object to associate with project
157         :return:
158         """
159         if not self.__role:
160             self.__role = keystone_utils.get_role_by_name(
161                 self._keystone, self.__role_name)
162             if not self.__role:
163                 self.__role = keystone_utils.create_role(
164                     self._keystone, self.__role_name)
165
166         keystone_utils.grant_user_role_to_project(self._keystone, self.__role,
167                                                   user, self.__project)
168
169     def get_compute_quotas(self):
170         """
171         Returns the compute quotas as an instance of the ComputeQuotas class
172         :return:
173         """
174         nova = nova_utils.nova_client(self._os_creds, self._os_session)
175
176         try:
177             return nova_utils.get_compute_quotas(nova, self.__project.id)
178         finally:
179             nova.client.session.session.close()
180
181     def get_network_quotas(self):
182         """
183         Returns the network quotas as an instance of the NetworkQuotas class
184         :return:
185         """
186         neutron = neutron_utils.neutron_client(
187             self._os_creds, self._os_session)
188         try:
189             return neutron_utils.get_network_quotas(neutron, self.__project.id)
190         finally:
191             neutron.httpclient.session.session.close()
192
193     def update_compute_quotas(self, compute_quotas):
194         """
195         Updates the compute quotas for this project
196         :param compute_quotas: a ComputeQuotas object.
197         """
198         nova = nova_utils.nova_client(self._os_creds, self._os_session)
199         try:
200             nova_utils.update_quotas(nova, self.__project.id, compute_quotas)
201         finally:
202             nova.client.session.session.close()
203
204     def update_network_quotas(self, network_quotas):
205         """
206         Updates the network quotas for this project
207         :param network_quotas: a NetworkQuotas object.
208         """
209         neutron = neutron_utils.neutron_client(
210             self._os_creds, self._os_session)
211         try:
212             neutron_utils.update_quotas(
213                 neutron, self.__project.id, network_quotas)
214         finally:
215             neutron.httpclient.session.session.close()
216
217
218 class ProjectSettings(ProjectConfig):
219     """
220     Class to hold the configuration settings required for creating OpenStack
221     project objects
222     deprecated
223     """
224
225     def __init__(self, **kwargs):
226         from warnings import warn
227         warn('Use snaps.config.project.ProjectConfig instead',
228              DeprecationWarning)
229         super(self.__class__, self).__init__(**kwargs)