Modified code to support both Python 2.7 and 3.x
[snaps.git] / snaps / openstack / create_flavor.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 novaclient.exceptions import NotFound
18
19 from snaps.openstack.utils import nova_utils
20
21 __author__ = 'spisarski'
22
23 logger = logging.getLogger('create_image')
24
25 MEM_PAGE_SIZE_ANY = {'hw:mem_page_size': 'any'}
26 MEM_PAGE_SIZE_LARGE = {'hw:mem_page_size': 'large'}
27
28
29 class OpenStackFlavor:
30     """
31     Class responsible for creating a user in OpenStack
32     """
33
34     def __init__(self, os_creds, flavor_settings):
35         """
36         Constructor
37         :param os_creds: The OpenStack connection credentials
38         :param flavor_settings: The flavor settings
39         :return:
40         """
41         self.__os_creds = os_creds
42         self.flavor_settings = flavor_settings
43         self.__flavor = None
44         self.__nova = nova_utils.nova_client(self.__os_creds)
45
46     def create(self, cleanup=False):
47         """
48         Creates the image in OpenStack if it does not already exist
49         :param cleanup: Denotes whether or not this is being called for cleanup or not
50         :return: The OpenStack flavor object
51         """
52         self.__flavor = nova_utils.get_flavor_by_name(self.__nova, self.flavor_settings.name)
53         if self.__flavor:
54             logger.info('Found flavor with name - ' + self.flavor_settings.name)
55         elif not cleanup:
56             self.__flavor = nova_utils.create_flavor(self.__nova, self.flavor_settings)
57             if self.flavor_settings.metadata:
58                 self.__flavor.set_keys(self.flavor_settings.metadata)
59             self.__flavor = nova_utils.get_flavor_by_name(self.__nova, self.flavor_settings.name)
60         else:
61             logger.info('Did not create flavor due to cleanup mode')
62
63         return self.__flavor
64
65     def clean(self):
66         """
67         Cleanse environment of all artifacts
68         :return: void
69         """
70         if self.__flavor:
71             try:
72                 nova_utils.delete_flavor(self.__nova, self.__flavor)
73             except NotFound:
74                 pass
75
76             self.__flavor = None
77
78     def get_flavor(self):
79         """
80         Returns the OpenStack flavor object
81         :return:
82         """
83         return self.__flavor
84
85
86 class FlavorSettings:
87     """
88     Configuration settings for OpenStack flavor creation
89     """
90
91     def __init__(self, config=None, name=None, flavor_id='auto', ram=None, disk=None, vcpus=None, ephemeral=0, swap=0,
92                  rxtx_factor=1.0, is_public=True, metadata=None):
93         """
94         Constructor
95         :param config: dict() object containing the configuration settings using the attribute names below as each
96                        member's the key and overrides any of the other parameters.
97         :param name: the flavor's name (required)
98         :param flavor_id: the string ID (default 'auto')
99         :param ram: the required RAM in MB (required)
100         :param disk: the size of the root disk in GB (required)
101         :param vcpus: the number of virtual CPUs (required)
102         :param ephemeral: the size of the ephemeral disk in GB (default 0)
103         :param swap: the size of the dedicated swap disk in GB (default 0)
104         :param rxtx_factor: the receive/transmit factor to be set on ports if backend supports
105                             QoS extension (default 1.0)
106         :param is_public: denotes whether or not the flavor is public (default True)
107         :param metadata: freeform dict() for special metadata (default hw:mem_page_size=any)
108         """
109
110         if config:
111             self.name = config.get('name')
112
113             if config.get('flavor_id'):
114                 self.flavor_id = config['flavor_id']
115             else:
116                 self.flavor_id = flavor_id
117
118             self.ram = config.get('ram')
119             self.disk = config.get('disk')
120             self.vcpus = config.get('vcpus')
121
122             if config.get('ephemeral'):
123                 self.ephemeral = config['ephemeral']
124             else:
125                 self.ephemeral = ephemeral
126
127             if config.get('swap'):
128                 self.swap = config['swap']
129             else:
130                 self.swap = swap
131
132             if config.get('rxtx_factor'):
133                 self.rxtx_factor = config['rxtx_factor']
134             else:
135                 self.rxtx_factor = rxtx_factor
136
137             if config.get('is_public') is not None:
138                 self.is_public = config['is_public']
139             else:
140                 self.is_public = is_public
141
142             if config.get('metadata'):
143                 self.metadata = config['metadata']
144             else:
145                 self.metadata = metadata
146         else:
147             self.name = name
148             self.flavor_id = flavor_id
149             self.ram = ram
150             self.disk = disk
151             self.vcpus = vcpus
152             self.ephemeral = ephemeral
153             self.swap = swap
154             self.rxtx_factor = rxtx_factor
155             self.is_public = is_public
156             self.metadata = metadata
157
158         if not self.name or not self.ram or not self.disk or not self.vcpus:
159             raise Exception('The attributes name, ram, disk, and vcpus are required for FlavorSettings')
160
161         if not isinstance(self.ram, int):
162             raise Exception('The ram attribute must be a integer')
163
164         if not isinstance(self.disk, int):
165             raise Exception('The ram attribute must be a integer')
166
167         if not isinstance(self.vcpus, int):
168             raise Exception('The vcpus attribute must be a integer')
169
170         if self.ephemeral and not isinstance(self.ephemeral, int):
171             raise Exception('The ephemeral attribute must be an integer')
172
173         if self.swap and not isinstance(self.swap, int):
174             raise Exception('The swap attribute must be an integer')
175
176         if self.rxtx_factor and not isinstance(self.rxtx_factor, (int, float)):
177             raise Exception('The is_public attribute must be an integer or float')
178
179         if self.is_public and not isinstance(self.is_public, bool):
180             raise Exception('The is_public attribute must be a boolean')