1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
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:
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
18 from snaps import file_utils
19 from snaps.config.flavor import FlavorConfig
20 from snaps.config.image import ImageConfig
21 from snaps.config.network import NetworkConfig, SubnetConfig
22 from snaps.config.router import RouterConfig
23 from snaps.openstack.os_credentials import OSCreds, ProxySettings
25 __author__ = 'spisarski'
27 logger = logging.getLogger('openstack_tests')
29 CIRROS_DEFAULT_IMAGE_URL =\
30 'http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img'
31 CIRROS_DEFAULT_KERNEL_IMAGE_URL =\
32 'http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-kernel'
33 CIRROS_DEFAULT_RAMDISK_IMAGE_URL =\
34 'http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-initramfs'
35 CIRROS_USER = 'cirros'
37 CENTOS_DEFAULT_IMAGE_URL =\
38 'http://cloud.centos.org/centos/7/images/' \
39 'CentOS-7-x86_64-GenericCloud.qcow2'
40 CENTOS_USER = 'centos'
42 UBUNTU_DEFAULT_IMAGE_URL = \
43 'http://uec-images.ubuntu.com/releases/trusty/14.04/' \
44 'ubuntu-14.04-server-cloudimg-amd64-disk1.img'
45 UBUNTU_USER = 'ubuntu'
47 DEFAULT_IMAGE_FORMAT = 'qcow2'
50 def get_credentials(os_env_file=None, proxy_settings_str=None,
51 ssh_proxy_cmd=None, dev_os_env_file=None, overrides=None):
53 Returns the OpenStack credentials object. It first attempts to retrieve
54 them from a standard OpenStack source file. If that file is None, it will
55 attempt to retrieve them with a YAML file.
56 :param os_env_file: the OpenStack source file
57 :param proxy_settings_str: proxy settings string <host>:<port> (optional)
58 :param ssh_proxy_cmd: the SSH proxy command for your environment (optional)
59 :param dev_os_env_file: the YAML file to retrieve both the OS credentials
61 :param overrides: dict() containing values to override the credentials
63 :return: the SNAPS credentials object
66 logger.debug('Reading RC file - ' + os_env_file)
67 config = file_utils.read_os_env_file(os_env_file)
68 proj_name = config.get('OS_PROJECT_NAME')
70 proj_name = config.get('OS_TENANT_NAME')
73 if proxy_settings_str:
74 tokens = re.split(':', proxy_settings_str)
75 proxy_settings = ProxySettings(host=tokens[0], port=tokens[1],
76 ssh_proxy_cmd=ssh_proxy_cmd)
79 if config.get('OS_CACERT'):
80 https_cacert = config.get('OS_CACERT')
81 elif config.get('OS_INSECURE'):
85 if config.get('OS_INTERFACE'):
86 interface = config.get('OS_INTERFACE')
89 'username': config['OS_USERNAME'],
90 'password': config['OS_PASSWORD'],
91 'auth_url': config['OS_AUTH_URL'],
92 'project_name': proj_name,
93 'identity_api_version': config.get('OS_IDENTITY_API_VERSION'),
94 'image_api_version': config.get('OS_IMAGE_API_VERSION'),
95 'network_api_version': config.get('OS_NETWORK_API_VERSION'),
96 'compute_api_version': config.get('OS_COMPUTE_API_VERSION'),
97 'heat_api_version': config.get('OS_HEAT_API_VERSION'),
98 'user_domain_id': config.get('OS_USER_DOMAIN_ID'),
99 'user_domain_name': config.get('OS_USER_DOMAIN_NAME'),
100 'project_domain_id': config.get('OS_PROJECT_DOMAIN_ID'),
101 'project_domain_name': config.get('OS_PROJECT_DOMAIN_NAME'),
102 'volume_api_version': config.get('OS_VOLUME_API_VERSION'),
103 'interface': interface,
104 'proxy_settings': proxy_settings,
105 'cacert': https_cacert,
106 'region_name': config.get('OS_REGION_NAME')}
108 logger.info('Reading development os_env file - ' + dev_os_env_file)
109 config = file_utils.read_yaml(dev_os_env_file)
111 proxy_settings = None
112 proxy_str = config.get('http_proxy')
114 tokens = re.split(':', proxy_str)
115 proxy_settings = ProxySettings(
116 host=tokens[0], port=tokens[1],
117 ssh_proxy_cmd=config.get('ssh_proxy_cmd'))
120 'username': config['username'],
121 'password': config['password'],
122 'auth_url': config['os_auth_url'],
123 'project_name': config['project_name'],
124 'identity_api_version': config.get('identity_api_version'),
125 'image_api_version': config.get('image_api_version'),
126 'network_api_version': config.get('network_api_version'),
127 'compute_api_version': config.get('compute_api_version'),
128 'heat_api_version': config.get('heat_api_version'),
129 'user_domain_id': config.get('user_domain_id'),
130 'user_domain_name': config.get('user_domain_name'),
131 'project_domain_id': config.get('project_domain_id'),
132 'project_domain_name': config.get('project_domain_name'),
133 'volume_api_version': config.get('volume_api_version'),
134 'interface': config.get('interface'),
135 'proxy_settings': proxy_settings,
136 'cacert': config.get('cacert'),
137 'region_name': config.get('region_name')}
139 if overrides and isinstance(overrides, dict):
140 creds_dict.update(overrides)
142 for key, value in creds_dict.items():
143 if value is not None and isinstance(value, str):
144 creds_dict[key] = value.replace('"', '').replace('\'', '')
146 os_creds = OSCreds(**creds_dict)
147 logger.info('OS Credentials = %s', os_creds.__str__)
151 def create_image_settings(image_name, image_user, image_format, metadata,
152 disk_url=None, default_url=None,
153 kernel_settings=None, ramdisk_settings=None,
154 public=False, nic_config_pb_loc=None):
156 Returns the image settings object
157 :param image_name: the name of the image
158 :param image_user: the image's sudo user
159 :param image_format: the image's format string
160 :param metadata: custom metadata for overriding default behavior for test
162 :param disk_url: the disk image's URL
163 :param default_url: the default URL for the disk image
164 :param kernel_settings: override to the kernel settings from the
166 :param ramdisk_settings: override to the ramdisk settings from the
168 :param public: True denotes image can be used by other projects where False
169 indicates the converse (default: False)
170 :param nic_config_pb_loc: The location of the playbook used for configuring
175 logger.debug('Image metadata - ' + str(metadata))
177 if metadata and 'config' in metadata:
178 return ImageConfig(**metadata['config'])
181 if metadata and ('disk_url' in metadata or 'disk_file' in metadata):
182 disk_url = metadata.get('disk_url')
183 disk_file = metadata.get('disk_file')
185 disk_url = default_url
188 and ('kernel_file' in metadata or 'kernel_url' in metadata)
189 and kernel_settings is None):
190 kernel_image_settings = ImageConfig(
191 name=image_name + '-kernel', image_user=image_user,
192 img_format=image_format, image_file=metadata.get('kernel_file'),
193 url=metadata.get('kernel_url'), public=public)
195 kernel_image_settings = kernel_settings
198 and ('ramdisk_file' in metadata or 'ramdisk_url' in metadata)
199 and ramdisk_settings is None):
200 ramdisk_image_settings = ImageConfig(
201 name=image_name + '-ramdisk', image_user=image_user,
202 img_format=image_format,
203 image_file=metadata.get('ramdisk_file'),
204 url=metadata.get('ramdisk_url'), public=public)
206 ramdisk_image_settings = ramdisk_settings
208 extra_properties = None
209 if metadata and 'extra_properties' in metadata:
210 extra_properties = metadata['extra_properties']
212 return ImageConfig(name=image_name, image_user=image_user,
213 img_format=image_format, image_file=disk_file,
214 url=disk_url, extra_properties=extra_properties,
215 kernel_image_settings=kernel_image_settings,
216 ramdisk_image_settings=ramdisk_image_settings,
218 nic_config_pb_loc=nic_config_pb_loc)
221 def cirros_image_settings(name=None, url=None, image_metadata=None,
222 kernel_settings=None, ramdisk_settings=None,
225 Returns the image settings for a Cirros QCOW2 image
226 :param name: the name of the image
227 :param url: the image's URL
228 :param image_metadata: dict() values to override URLs for disk, kernel, and
230 :param kernel_settings: override to the kernel settings from the
232 :param ramdisk_settings: override to the ramdisk settings from the
234 :param public: True denotes image can be used by other projects where False
235 indicates the converse
238 if image_metadata and 'cirros' in image_metadata:
239 metadata = image_metadata['cirros']
241 metadata = image_metadata
243 return create_image_settings(
244 image_name=name, image_user=CIRROS_USER,
245 image_format=DEFAULT_IMAGE_FORMAT, metadata=metadata, disk_url=url,
246 default_url=CIRROS_DEFAULT_IMAGE_URL,
247 kernel_settings=kernel_settings, ramdisk_settings=ramdisk_settings,
251 def file_image_test_settings(name, file_path, image_user=CIRROS_USER):
252 return ImageConfig(name=name, image_user=image_user,
253 img_format=DEFAULT_IMAGE_FORMAT, image_file=file_path)
256 def centos_image_settings(name, url=None, image_metadata=None,
257 kernel_settings=None, ramdisk_settings=None,
260 Returns the image settings for a Centos QCOW2 image
261 :param name: the name of the image
262 :param url: the image's URL
263 :param image_metadata: dict() values to override URLs for disk, kernel, and
265 :param kernel_settings: override to the kernel settings from the
267 :param ramdisk_settings: override to the ramdisk settings from the
269 :param public: True denotes image can be used by other projects where False
270 indicates the converse
273 if image_metadata and 'centos' in image_metadata:
274 metadata = image_metadata['centos']
276 metadata = image_metadata
278 return create_image_settings(
279 image_name=name, image_user=CENTOS_USER,
280 image_format=DEFAULT_IMAGE_FORMAT, metadata=metadata, disk_url=url,
281 default_url=CENTOS_DEFAULT_IMAGE_URL,
282 kernel_settings=kernel_settings, ramdisk_settings=ramdisk_settings,
286 def ubuntu_image_settings(name, url=None, image_metadata=None,
287 kernel_settings=None, ramdisk_settings=None,
290 Returns the image settings for a Ubuntu QCOW2 image
291 :param name: the name of the image
292 :param url: the image's URL
293 :param image_metadata: dict() values to override URLs for disk, kernel, and
295 :param kernel_settings: override to the kernel settings from the
297 :param ramdisk_settings: override to the ramdisk settings from the
299 :param public: True denotes image can be used by other projects where False
300 indicates the converse
303 if image_metadata and 'ubuntu' in image_metadata:
304 metadata = image_metadata['ubuntu']
306 metadata = image_metadata
308 return create_image_settings(
309 image_name=name, image_user=UBUNTU_USER,
310 image_format=DEFAULT_IMAGE_FORMAT, metadata=metadata, disk_url=url,
311 default_url=UBUNTU_DEFAULT_IMAGE_URL,
312 kernel_settings=kernel_settings, ramdisk_settings=ramdisk_settings,
316 def get_priv_net_config(project_name, net_name, subnet_name, router_name=None,
317 cidr='10.55.0.0/24', external_net=None,
318 netconf_override=None):
319 return OSNetworkConfig(
320 project_name, net_name, subnet_name, cidr, router_name,
321 external_gateway=external_net, netconf_override=netconf_override)
324 def get_pub_net_config(
325 project_name, net_name, subnet_name=None, router_name=None,
326 cidr='10.55.1.0/24', external_net=None, netconf_override=None):
327 return OSNetworkConfig(project_name, net_name, subnet_name, cidr,
328 router_name, external_gateway=external_net,
329 netconf_override=netconf_override)
332 def get_flavor_config(name, ram, disk, vcpus, ephemeral=None, swap=None,
333 rxtx_factor=None, is_public=None, metadata=None):
334 """This method replaces the hard coded basic element (e.g. ram, vcpu, disk
335 etc) with those are included in the new freeform dict() of metadata
338 :param name: the flavor name (required)
339 :param ram: memory in MB to allocate to VM (required)
340 :param disk: disk storage in GB (required)
341 :param vcpus: the number of CPUs to allocate to VM (required)
342 :param ephemeral: the size of the ephemeral disk in GB (default=0)
343 :param swap: the size of the swap disk in GB (default=0)
344 :param rxtx_factor: the receive/transmit factor to be set on ports
345 if backend supports QoS extension (default=1.0)
346 :param is_public: flag that denotes whether or not other projects
347 can access image (default=True)
348 :param metadata: - freeform dict() for special metadata (optional)
349 - freeform dict() for values of basic elements
350 (e.g. ram, vcpu, disk, etc) could be added.
351 As result the hard coded values of those elements will be
352 overwritten by the new ones (optional)
353 :return: The FlavorConfig replacing the hard coded basic element values
354 (e.g. ram, vcpu, disk etc) with those are included in the metadata
355 dict [optional]. The metadata parameter in the FlavorConfig
356 consist of the metadata data only.
359 metadata_excl = metadata
361 if 'ram' in metadata:
362 ram = metadata['ram']
363 del metadata_excl['ram']
364 if 'disk' in metadata:
365 disk = metadata['disk']
366 del metadata_excl['disk']
367 if 'vcpus' in metadata:
368 vcpus = metadata['vcpus']
369 del metadata_excl['vcpus']
370 if 'ephemeral' in metadata:
371 ephemeral = metadata['ephemeral']
372 del metadata_excl['ephemeral']
373 if 'swap' in metadata:
374 swap = metadata['swap']
375 del metadata_excl['swap']
376 if 'rxtx_factor' in metadata:
377 rxtx_factor = metadata['rxtx_factor']
378 del metadata_excl['rxtx_factor']
379 if 'is_public' in metadata:
380 is_public = metadata['is_public']
381 del metadata_excl['is_public']
382 if 'metadata' in metadata:
383 metadata_excl = metadata['metadata']
386 name=name, ram=ram, disk=disk, vcpus=vcpus, ephemeral=ephemeral,
387 swap=swap, rxtx_factor=rxtx_factor, is_public=is_public,
388 metadata=metadata_excl)
391 class OSNetworkConfig:
393 Represents the settings required for the creation of a network in OpenStack
394 where netconf_override is used to reconfigure the network_type,
395 physical_network and segmentation_id
398 def __init__(self, project_name, net_name, subnet_name=None,
399 subnet_cidr=None, router_name=None, external_gateway=None,
400 netconf_override=None):
402 :param netconf_override: dict() containing the reconfigured
403 network_type, physical_network and
406 if subnet_name and subnet_cidr:
407 network_conf = NetworkConfig(
408 name=net_name, subnet_settings=[
409 SubnetConfig(cidr=subnet_cidr, name=subnet_name)])
411 network_conf = NetworkConfig(name=net_name)
413 network_conf.network_type = netconf_override.get('network_type')
414 network_conf.physical_network = netconf_override.get(
416 network_conf.segmentation_id = netconf_override.get(
418 self.network_settings = network_conf
422 self.router_settings = RouterConfig(
423 name=router_name, external_gateway=external_gateway,
424 internal_subnets=[{'subnet': {
425 'project_name': project_name,
426 'network_name': net_name,
427 'subnet_name': subnet_name}}])
429 self.router_settings = RouterConfig(
430 name=router_name, external_gateway=external_gateway)