4 ## Copyright (c) 2020 Intel Corporation
6 ## Licensed under the Apache License, Version 2.0 (the "License");
7 ## you may not use this file except in compliance with the License.
8 ## You may obtain a copy of the License at
10 ## http://www.apache.org/licenses/LICENSE-2.0
12 ## Unless required by applicable law or agreed to in writing, software
13 ## distributed under the License is distributed on an "AS IS" BASIS,
14 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ## See the License for the specific language governing permissions and
16 ## limitations under the License.
19 import os_client_config
21 from heatclient.client import Client as Heat_Client
22 from keystoneclient.v3 import Client as Keystone_Client
23 from heatclient.common import template_utils
24 from novaclient import client as NovaClient
29 from collections import OrderedDict
30 from rapid_log import RapidLog
32 class StackDeployment(object):
33 """Deployment class to create VMs for test execution in OpenStack
36 def __init__(self, cloud_name):
37 # RapidLog.log_init('CREATEStack.log', 'DEBUG', 'INFO', '2020.05.05')
42 self.number_of_servers = 0
43 self.cloud_name = cloud_name
44 self.heat_template = 'L6_heat_template.yaml'
45 self.heat_param = 'params_rapid.yaml'
46 self.cloud_config = os_client_config.OpenStackConfig().get_all_clouds()
48 for cloud in self.cloud_config:
49 if cloud.name == self.cloud_name:
50 ks_client = Keystone_Client(**cloud.config['auth'])
54 heat_endpoint = ks_client.service_catalog.url_for(service_type='orchestration',
55 endpoint_type='publicURL')
56 self.heatclient = Heat_Client('1', heat_endpoint, token=ks_client.auth_token)
57 self.nova_client = NovaClient.Client(2, **cloud.config['auth'])
59 def generate_paramDict(self):
60 for output in self.stack.output_list()['outputs']:
61 output_value = self.stack.output_show(output['output_key'])['output']['output_value']
62 for server_group_output in output_value:
63 if (output['output_key'] == 'number_of_servers'):
64 self.number_of_servers += int (server_group_output)
65 elif (output['output_key'] == 'mngmt_ips'):
66 for ip in server_group_output:
67 self.mngmt_ips.append(ip)
68 elif (output['output_key'] == 'data_plane_ips'):
69 for dps in server_group_output:
70 self.dp_ips.append(dps)
71 elif (output['output_key'] == 'data_plane_macs'):
72 for mac in server_group_output:
73 self.dp_macs.append(mac)
74 elif (output['output_key'] == 'server_name'):
75 for name in server_group_output:
76 self.names.append(name)
78 def print_paramDict(self, user):
79 if not(len(self.dp_ips) == len(self.dp_macs) == len(self.mngmt_ips)):
81 _ENV_FILE_DIR = os.path.dirname(os.path.realpath(__file__))
82 env_file = os.path.join(_ENV_FILE_DIR, self.stack.stack_name)+ '.env'
83 with open(env_file, 'w') as env_file:
84 env_file.write('[rapid]\n')
85 env_file.write('total_number_of_machines = {}\n'.format(str(self.number_of_servers)))
87 for count in range(self.number_of_servers):
88 env_file.write('[M' + str(count+1) + ']\n')
89 env_file.write('name = {}\n'.format(str(self.names[count])))
90 env_file.write('admin_ip = {}\n'.format(str(self.mngmt_ips[count])))
91 if type(self.dp_ips[count]) == list:
92 for i, dp_ip in enumerate(self.dp_ips[count], start = 1):
93 env_file.write('dp_ip{} = {}\n'.format(i, str(dp_ip)))
95 env_file.write('dp_ip1 = {}\n'.format(str(self.dp_ips[count])))
96 if type(self.dp_macs[count]) == list:
97 for i, dp_mac in enumerate(self.dp_macs[count], start = 1):
98 env_file.write('dp_mac{} = {}\n'.format(i, str(dp_mac)))
100 env_file.write('dp_mac1 = {}\n'.format(str(self.dp_macs[count])))
102 env_file.write('[ssh]\n')
103 env_file.write('key = {}\n'.format(self.private_key_filename))
104 env_file.write('user = {}\n'.format(user))
106 env_file.write('[Varia]\n')
107 env_file.write('vim = OpenStack\n')
108 env_file.write('stack = {}\n'.format(self.stack.stack_name))
110 def create_stack(self, stack_name, stack_file_path, param_file):
111 files, template = template_utils.process_template_path(stack_file_path)
112 heat_parameters = open(param_file)
113 temp_params = yaml.load(heat_parameters,Loader=yaml.BaseLoader)
114 heat_parameters.close()
115 stack_created = self.heatclient.stacks.create(stack_name=stack_name, template=template,
116 parameters=temp_params["parameters"], files=files)
117 stack = self.heatclient.stacks.get(stack_created['stack']['id'], resolve_outputs=True)
118 # Poll at 5 second intervals, until the status is no longer 'BUILD'
119 while stack.stack_status == 'CREATE_IN_PROGRESS':
122 stack = self.heatclient.stacks.get(stack_created['stack']['id'], resolve_outputs=True)
123 if stack.stack_status == 'CREATE_COMPLETE':
126 RapidLog.exception('Error in stack deployment')
128 def create_key(self):
129 keypair = self.nova_client.keypairs.create(name=self.key_name)
130 # Create a file for writing that can only be read and written by owner
131 fp = os.open(self.private_key_filename, os.O_WRONLY | os.O_CREAT, 0o600)
132 with os.fdopen(fp, 'w') as f:
133 f.write(keypair.private_key)
134 RapidLog.info('Keypair {} created'.format(self.key_name))
136 def IsDeployed(self, stack_name):
137 for stack in self.heatclient.stacks.list():
138 if stack.stack_name == stack_name:
139 RapidLog.info('Stack already existing: {}'.format(stack_name))
145 keypairs = self.nova_client.keypairs.list()
146 if next((x for x in keypairs if x.name == self.key_name), None):
147 RapidLog.info('Keypair {} already exists'.format(self.key_name))
151 def deploy(self, stack_name, keypair_name, heat_template, heat_param):
152 self.key_name = keypair_name
153 self.private_key_filename = '{}.pem'.format(keypair_name)
154 if not self.IsDeployed(stack_name):
157 self.stack = self.create_stack(stack_name, heat_template, heat_param)
159 def generate_env_file(self, user = 'centos'):
160 self.generate_paramDict()
161 self.print_paramDict(user)