Merge "Fixed two tests that never had their networks removed on tearDown()"
[snaps.git] / snaps / openstack / create_project.py
1 # Copyright (c) 2016 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
18
19 from snaps.openstack.utils import keystone_utils
20
21 __author__ = 'spisarski'
22
23 logger = logging.getLogger('create_image')
24
25
26 class OpenStackProject:
27     """
28     Class responsible for creating a project/project in OpenStack
29     """
30
31     def __init__(self, os_creds, project_settings):
32         """
33         Constructor
34         :param os_creds: The OpenStack connection credentials
35         :param project_settings: The project's settings
36         :return:
37         """
38         self.__os_creds = os_creds
39         self.project_settings = project_settings
40         self.__project = None
41         self.__role = None
42         self.__keystone = keystone_utils.keystone_client(self.__os_creds)
43
44     def create(self, cleanup=False):
45         """
46         Creates the image in OpenStack if it does not already exist
47         :param cleanup: Denotes whether or not this is being called for cleanup or not
48         :return: The OpenStack Image object
49         """
50         try:
51             self.__project = keystone_utils.get_project(keystone=self.__keystone,
52                                                         project_name=self.project_settings.name)
53             if self.__project:
54                 logger.info('Found project with name - ' + self.project_settings.name)
55             elif not cleanup:
56                 self.__project = keystone_utils.create_project(self.__keystone, self.project_settings)
57             else:
58                 logger.info('Did not create image due to cleanup mode')
59         except Exception as e:
60             logger.error('Unexpected error. Rolling back')
61             self.clean()
62             raise Exception(e.message)
63
64         return self.__project
65
66     def clean(self):
67         """
68         Cleanse environment of all artifacts
69         :return: void
70         """
71         if self.__project:
72             try:
73                 keystone_utils.delete_project(self.__keystone, self.__project)
74             except NotFound:
75                 pass
76             self.__project = None
77
78         if self.__role:
79             try:
80                 keystone_utils.delete_role(self.__keystone, self.__role)
81             except NotFound:
82                 pass
83             self.__project = None
84
85     def get_project(self):
86         """
87         Returns the OpenStack project object populated on create()
88         :return:
89         """
90         return self.__project
91
92     def assoc_user(self, user):
93         """
94         The user object to associate with the project
95         :param user: the OpenStack user object to associate with project
96         :return:
97         """
98         if not self.__role:
99             self.__role = keystone_utils.create_role(self.__keystone, self.project_settings.name + '-role')
100
101         keystone_utils.assoc_user_to_project(self.__keystone, self.__role, user, self.__project)
102
103
104 class ProjectSettings:
105     """
106     Class to hold the configuration settings required for creating OpenStack project objects
107     """
108     def __init__(self, config=None, name=None, domain='default', description=None, enabled=True):
109
110         """
111         Constructor
112         :param config: dict() object containing the configuration settings using the attribute names below as each
113                        member's the key and overrides any of the other parameters.
114         :param name: the project's name (required)
115         :param domain: the project's domain name (default 'default'). Field is used for v3 clients
116         :param description: the description (optional)
117         :param enabled: denotes whether or not the user is enabled (default True)
118         """
119
120         if config:
121             self.name = config.get('name')
122             if config.get('domain'):
123                 self.domain = config['domain']
124             else:
125                 self.domain = domain
126
127             self.description = config.get('description')
128             if config.get('enabled') is not None:
129                 self.enabled = config['enabled']
130             else:
131                 self.enabled = enabled
132         else:
133             self.name = name
134             self.domain = domain
135             self.description = description
136             self.enabled = enabled
137
138         if not self.name:
139             raise Exception("The attribute name is required for ProjectSettings")