867ce3240ed3ff7c666306a6663b1adc5f8c3ae1
[samplevnf.git] / VNFs / DPPD-PROX / helper-scripts / openstackrapid / createrapid.py
1 #!/usr/bin/python
2
3 ##
4 ## Copyright (c) 2010-2017 Intel Corporation
5 ##
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
9 ##
10 ##     http://www.apache.org/licenses/LICENSE-2.0
11 ##
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.
17 ##
18
19 from __future__ import print_function
20
21 import os
22 import stat
23 import sys
24 import time
25 import subprocess
26 import getopt
27 import re
28 import logging
29 from logging.handlers import RotatingFileHandler
30 from logging import handlers
31 from prox_ctrl import prox_ctrl
32 import ConfigParser
33
34 version="18.2.12"
35 stack = "rapid" #Default string for stack
36 yaml = "rapid.yaml" #Default string for yaml file
37 key = "prox" # This is also the default in the yaml file....
38 flavor = "prox_flavor" # This is also the default in the yaml file....
39 image = "rapidVM" # This is also the default in the yaml file....
40 image_file = "rapidVM.qcow2"
41 dataplane_network = "dataplane-network" # This is also the default in the yaml file....
42 subnet = "dpdk-subnet" #subnet for dataplane
43 subnet_cidr="10.10.10.0/24" # cidr for dataplane
44 internal_network="admin_internal_net"
45 floating_network="admin_floating_net"
46 vm1_availability_zone="nova"
47 vm2_availability_zone="nova"
48 vm3_availability_zone="nova"
49 loglevel="DEBUG" # sets log level for writing to file
50 runtime=10 # time in seconds for 1 test run
51
52 def usage():
53         print("usage: createrapid [--version] [-v]")
54         print("                   [--stack STACK_NAME]")
55         print("                   [--yaml YAML_FILE]")
56         print("                   [--key KEY_NAME]")
57         print("                   [--flavor FLAVOR_NAME]")
58         print("                   [--image IMAGE_NAME]")
59         print("                   [--image_file IMAGE_FILE]")
60         print("                   [--dataplane_network DP_NETWORK]")
61         print("                   [--subnet DP_SUBNET]")
62         print("                   [--subnet_cidr SUBNET_CIDR]")
63         print("                   [--internal_network ADMIN_NETWORK]")
64         print("                   [--floating_network ADMIN_NETWORK]")
65         print("                   [--vm1_availability_zone ZONE_FOR_VM1]")
66         print("                   [--vm2_availability_zone ZONE_FOR_VM2]")
67         print("                   [--vm3_availability_zone ZONE_FOR_VM3]")
68         print("                   [--log DEBUG|INFO|WARNING|ERROR|CRITICAL")
69         print("                   [-h] [--help]")
70         print("")
71         print("Command-line interface to createrapid")
72         print("")
73         print("optional arguments:")
74         print("  -v,  --version                 Show program's version number and exit")
75         print("  --stack STACK_NAME             Specify a name for the heat stack. Default is %s."%stack)
76         print("  --yaml YAML_FILE               Specify the yaml file to be used. Default is %s."%yaml)
77         print("  --key KEY_NAME                 Specify the key to be used. Default is %s."%key)
78         print("  --flavor FLAVOR_NAME           Specify the flavor to be used. Default is %s."%flavor)
79         print("  --image IMAGE_NAME             Specify the image to be used. Default is %s."%image)
80         print("  --image_file IMAGE_FILE        Specify the image qcow2 file to be used. Default is %s."%image_file)
81         print("  --dataplane_network NETWORK    Specify the network name to be used for the dataplane. Default is %s."%dataplane_network)
82         print("  --subnet DP_SUBNET             Specify the subnet name to be used for the dataplane. Default is %s."%subnet)
83         print("  --subnet_cidr SUBNET_CIDR      Specify the subnet CIDR to be used for the dataplane. Default is %s."%subnet_cidr)
84         print("  --internal_network NETWORK     Specify the network name to be used for the control plane. Default is %s."%internal_network)
85         print("  --floating_network NETWORK     Specify the external floating ip network name. Default is %s. NO if no floating ip used."%floating_network)
86         print("  --vm1_availability_zone ZONE   Specify the availability zone for VM1. Default is %s."%vm1_availability_zone)
87         print("  --vm2_availability_zone ZONE   Specify the availability zone for VM2. Default is %s."%vm2_availability_zone)
88         print("  --vm3_availability_zone ZONE   Specify the availability zone for VM3. Default is %s."%vm3_availability_zone)
89         print("  --log                          Specify logging level for log file output, screen output level is hard coded")
90         print("  -h, --help                     Show help message and exit.")
91         print("")
92         print("To delete the rapid stack, type the following command")
93         print("   openstack stack delete --yes --wait %s"%stack)
94         print("Note that %s is the default stack name. Replace with STACK_NAME if needed"%stack)
95
96 try:
97         opts, args = getopt.getopt(sys.argv[1:], "vh", ["version","help", "yaml=","stack=","key=","flavor=","image=","image_file=","dataplane_network=","subnet=","subnet_cidr=","internal_network=","floating_network=","vm1_availability_zone=","vm2_availability_zone=","vm3_availability_zone=","log="])
98 except getopt.GetoptError as err:
99         print("===========================================")
100         print(str(err))
101         print("===========================================")
102         usage()
103         sys.exit(2)
104 if args:
105         usage()
106         sys.exit(2)
107 for opt, arg in opts:
108         if opt in ("-h", "--help"):
109                 usage()
110                 sys.exit()
111         if opt in ("-v", "--version"):
112                 print("Rapid Automated Performance Indication for Dataplane "+version)
113                 sys.exit()
114         if opt in ("--stack"):
115                 stack = arg
116                 print ("Using '"+stack+"' as name for the stack")
117         elif opt in ("--yaml"):
118                 yaml = arg
119                 print ("Using stack: "+yaml)
120         elif opt in ("--key"):
121                 key = arg
122                 print ("Using key: "+key)
123         elif opt in ("--flavor"):
124                 flavor = arg
125                 print ("Using flavor: "+flavor)
126         elif opt in ("--image"):
127                 image = arg
128                 print ("Using image: "+image)
129         elif opt in ("--image_file"):
130                 image_file = arg
131                 print ("Using qcow2 file: "+image_file)
132         elif opt in ("--dataplane_network"):
133                 dataplane_network = arg
134                 print ("Using dataplane network: "+ dataplane_network)
135         elif opt in ("--subnet"):
136                 subnet = arg
137                 print ("Using dataplane subnet: "+ subnet)
138         elif opt in ("--subnet_cidr"):
139                 subnet_cidr = arg
140                 print ("Using dataplane subnet: "+ subnet_cidr)
141         elif opt in ("--internal_network"):
142                 internal_network = arg
143                 print ("Using control plane network: "+ internal_network)
144         elif opt in ("--floating_network"):
145                 floating_network = arg
146                 print ("Using floating ip network: "+ floating_network)
147         elif opt in ("--vm1_availability_zone"):
148                 vm1_availability_zone = arg
149                 print ("Using VM1 availability zone: "+ vm1_availability_zone)
150         elif opt in ("--vm2_availability_zone"):
151                 vm2_availability_zone = arg
152                 print ("Using VM2 availability zone: "+ vm2_availability_zone)
153         elif opt in ("--vm3_availability_zone"):
154                 vm3_availability_zone = arg
155                 print ("Using VM3 availability zone: "+ vm3_availability_zone)
156         elif opt in ("--log"):
157                 loglevel = arg
158                 print ("Log level: "+ loglevel)
159
160
161 # create formatters
162 screen_formatter = logging.Formatter("%(message)s")
163 file_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
164
165 # get a top-level logger,
166 # set its log level,
167 # BUT PREVENT IT from propagating messages to the root logger
168 #
169 log = logging.getLogger()
170 numeric_level = getattr(logging, loglevel.upper(), None)
171 if not isinstance(numeric_level, int):
172     raise ValueError('Invalid log level: %s' % loglevel)
173 log.setLevel(numeric_level)
174 log.propagate = 0
175
176 # create a console handler
177 # and set its log level to the command-line option 
178
179 console_handler = logging.StreamHandler(sys.stdout)
180 console_handler.setLevel(logging.INFO)
181 console_handler.setFormatter(screen_formatter)
182
183 # create a file handler
184 # and set its log level to DEBUG
185 #
186 log_file = 'CREATE' +stack +'.log'
187 file_handler = logging.handlers.RotatingFileHandler(log_file, backupCount=10)
188 #file_handler = log.handlers.TimedRotatingFileHandler(log_file, 'D', 1, 5)
189 file_handler.setLevel(numeric_level)
190 file_handler.setFormatter(file_formatter)
191
192 # add handlers to the logger
193 #
194 log.addHandler(file_handler)
195 log.addHandler(console_handler)
196
197 # Check if log exists and should therefore be rolled
198 needRoll = os.path.isfile(log_file)
199
200
201 # This is a stale log, so roll it
202 if needRoll:    
203     # Add timestamp
204     log.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime())
205
206     # Roll over on application start
207     log.handlers[0].doRollover()
208
209 # Add timestamp
210 log.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime())
211
212 log.debug("createrapid.py version: "+version)
213 # Checking if the control network already exists, if not, stop the script
214 log.debug("Checking control plane network: "+internal_network)
215 cmd = 'openstack network show '+internal_network
216 log.debug (cmd)
217 cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
218 NetworkExist = subprocess.check_output(cmd , shell=True).strip()
219 if NetworkExist == 'ACTIVE':
220         log.info("Control plane network ("+internal_network+")  already active")
221 else:
222         log.exception("Control plane network " + internal_network + " not existing")
223         raise Exception("Control plane network " + internal_network + " not existing")
224
225 # Checking if the floating ip network already exists, if not, stop the script
226 if floating_network <>'NO':
227         log.debug("Checking floating ip network: "+floating_network)
228         cmd = 'openstack network show '+floating_network
229         log.debug (cmd)
230         cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
231         NetworkExist = subprocess.check_output(cmd , shell=True).strip()
232         if NetworkExist == 'ACTIVE':
233                 log.info("Floating ip network ("+floating_network+")  already active")
234         else:
235                 log.exception("Floating ip network " + floating_network + " not existing")
236                 raise Exception("Floating ip network " + floating_network + " not existing")
237
238 # Checking if the image already exists, if not create it
239 log.debug("Checking image: "+image)
240 cmd = 'openstack image show '+image
241 log.debug(cmd)
242 cmd = cmd +' |grep "status " | tr -s " " | cut -d" " -f 4'
243 ImageExist = subprocess.check_output(cmd , shell=True).strip()
244 if ImageExist == 'active':
245         log.info("Image ("+image+") already available")
246 else:
247         log.info('Creating image ...')
248         cmd = 'openstack image create --disk-format qcow2 --container-format bare --public --file ./'+image_file+ ' ' +image
249         log.debug(cmd)
250         cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
251         ImageExist = subprocess.check_output(cmd , shell=True).strip()
252         if ImageExist == 'active':
253                 log.info('Image created and active')
254                 cmd = 'openstack image set --property hw_vif_multiqueue_enabled="true" ' +image
255 #               subprocess.check_call(cmd , shell=True)
256         else :
257                 log.exception("Failed to create image")
258                 raise Exception("Failed to create image")
259
260 # Checking if the key already exists, if not create it
261 log.debug("Checking key: "+key)
262 cmd = 'openstack keypair show '+key
263 log.debug (cmd)
264 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
265 KeyExist = subprocess.check_output(cmd , shell=True).strip()
266 if KeyExist == key:
267         log.info("Key ("+key+") already installed")
268 else:
269         log.info('Creating key ...')
270         cmd = 'openstack keypair create '+ key + '>' +key+'.pem'
271         log.debug(cmd)
272         subprocess.check_call(cmd , shell=True)
273         cmd = 'chmod 600 ' +key+'.pem'
274         subprocess.check_call(cmd , shell=True)
275         cmd = 'openstack keypair show '+key
276         log.debug(cmd)
277         cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
278         KeyExist = subprocess.check_output(cmd , shell=True).strip()
279         if KeyExist == key:
280                 log.info("Key created")
281         else :
282                 log.exception("Failed to create key: " + key)
283                 raise Exception("Failed to create key: " + key)
284
285 # Checking if the flavor already exists, if not create it
286 log.debug("Checking flavor: "+flavor)
287 cmd = 'openstack flavor show '+flavor
288 log.debug (cmd)
289 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
290 FlavorExist = subprocess.check_output(cmd , shell=True).strip()
291 if FlavorExist == flavor:
292         log.info("Flavor ("+flavor+") already installed")
293 else:
294         log.info('Creating flavor ...')
295         cmd = 'openstack flavor create '+flavor+' --ram 8192 --disk 20 --vcpus 4'
296         log.debug(cmd)
297         cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
298         FlavorExist = subprocess.check_output(cmd , shell=True).strip()
299         if FlavorExist == flavor:
300                 cmd = 'openstack flavor set '+ flavor +' --property hw:mem_page_size="large" --property hw:cpu_policy="dedicated" --property hw:cpu_thread_policy="isolate"'
301                 log.debug(cmd)
302                 subprocess.check_call(cmd , shell=True)
303                 log.info("Flavor created")
304         else :
305                 log.exception("Failed to create flavor: " + flavor)
306                 raise Exception("Failed to create flavor: " + flavor)
307
308 # Checking if the dataplane network already exists, if not create it
309 log.debug("Checking dataplane network: "+dataplane_network)
310 cmd = 'openstack network show '+dataplane_network
311 log.debug (cmd)
312 cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
313 NetworkExist = subprocess.check_output(cmd , shell=True).strip()
314 if NetworkExist == 'ACTIVE':
315         log.info("Dataplane network ("+dataplane_network+") already active")
316 else:
317         log.info('Creating dataplane network ...')
318         cmd = 'openstack network create '+dataplane_network
319         log.debug(cmd)
320         cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
321         NetworkExist = subprocess.check_output(cmd , shell=True).strip()
322         if NetworkExist == 'ACTIVE':
323                 log.info("Dataplane network created")
324         else :
325                 log.exception("Failed to create dataplane network: " + dataplane_network)
326                 raise Exception("Failed to create dataplane network: " + dataplane_network)
327
328 # Checking if the dataplane subnet already exists, if not create it
329 log.debug("Checking subnet: "+subnet)
330 cmd = 'openstack subnet show '+ subnet
331 log.debug (cmd)
332 cmd = cmd +' |grep "name " | tr -s " " | cut -d"|" -f 3'
333 SubnetExist = subprocess.check_output(cmd , shell=True).strip()
334 if SubnetExist == subnet:
335         log.info("Subnet (" +subnet+ ") already exists")
336 else:
337         log.info('Creating subnet ...')
338         cmd = 'openstack subnet create --network ' + dataplane_network + ' --subnet-range ' + subnet_cidr +' --gateway none ' + subnet
339         log.debug(cmd)
340         cmd = cmd + ' |grep "name " | tr -s " " | cut -d"|" -f 3'
341         SubnetExist = subprocess.check_output(cmd , shell=True).strip()
342         if SubnetExist == subnet:
343                 log.info("Subnet created")
344         else :
345                 log.exception("Failed to create subnet: " + subnet)
346                 raise Exception("Failed to create subnet: " + subnet)
347
348 # Checking if the stack already exists, if not create it
349 log.debug("Checking Stack: "+stack)
350 cmd = 'openstack stack show '+stack
351 log.debug (cmd)
352 cmd = cmd+' |grep "stack_status " | tr -s " " | cut -d"|" -f 3'
353 StackRunning = subprocess.check_output(cmd , shell=True).strip()
354 if StackRunning == '':
355         log.info('Creating Stack ...')
356         cmd = 'openstack stack create -t '+ yaml +  ' --parameter flavor="'+flavor  +'" --parameter key="'+ key + '" --parameter image="'+image  + '" --parameter dataplane_network="'+dataplane_network+ '" --parameter internal_network="'+internal_network+'" --parameter floating_network="'+floating_network+'" --parameter vm1_availability_zone="'+vm1_availability_zone+'" --parameter vm2_availability_zone="'+vm2_availability_zone+'" --parameter vm3_availability_zone="'+vm3_availability_zone+'" --wait '+stack 
357         log.debug(cmd)
358         cmd = cmd + ' |grep "stack_status " | tr -s " " | cut -d"|" -f 3'
359         StackRunning = subprocess.check_output(cmd , shell=True).strip()
360 if StackRunning != 'CREATE_COMPLETE':
361         log.exception("Failed to create stack")
362         raise Exception("Failed to create stack")
363
364 # Obtaining IP & MAC addresses for the VMs created in the stack
365 log.info("Stack ("+stack+") running")
366 cmd='openstack stack show -f yaml -c outputs ' + stack
367 log.debug(cmd)
368 output = subprocess.check_output(cmd , shell=True).strip()
369 matchObj = re.search('.*total_number_of_VMs.*?([0-9])', output, re.DOTALL)
370 total_number_of_VMs = matchObj.group(1)
371 vmDPIP =[]
372 vmAdminIP =[]
373 vmDPmac =[]
374 config = ConfigParser.RawConfigParser()
375 for vm in range(1, int(total_number_of_VMs)+1):
376         searchString = '.*vm%d_dataplane_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)' % vm
377         matchObj = re.search(searchString, output, re.DOTALL)
378         vmDPIP.append(matchObj.group(1))
379         if floating_network <> 'NO':
380                 searchString = '.*vm%d_public_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)' % vm
381                 matchObj = re.search(searchString, output, re.DOTALL)
382                 vmAdminIP.append(matchObj.group(1))
383         else:
384                 searchString = '.*vm%d_private_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)' % vm
385                 matchObj = re.search(searchString, output, re.DOTALL)
386                 vmAdminIP.append(matchObj.group(1))
387         searchString = '.*vm%d_dataplane_mac.*?([a-fA-F0-9:]{17})' % vm
388         matchObj = re.search(searchString, output, re.DOTALL)
389         vmDPmac.append(matchObj.group(1))
390         log.info('VM%d: (admin IP: %s), (dataplane IP: %s), (dataplane MAC: %s)' % (vm,vmAdminIP[-1],vmDPIP[-1],vmDPmac[-1]))
391         config.add_section('VM%d'%vm)
392         config.set('VM%d'%vm, 'admin_ip', vmAdminIP[-1])
393         config.set('VM%d'%vm, 'dp_ip', vmDPIP[-1])
394         config.set('VM%d'%vm, 'dp_mac', vmDPmac[-1])
395 config.add_section('OpenStack')
396 config.set('OpenStack', 'stack', stack)
397 config.set('OpenStack', 'yaml', yaml)
398 config.set('OpenStack', 'key', key)
399 config.set('OpenStack', 'flavor', flavor)
400 config.set('OpenStack', 'image', image)
401 config.set('OpenStack', 'image_file', image_file)
402 config.set('OpenStack', 'dataplane_network', dataplane_network)
403 config.set('OpenStack', 'subnet', subnet)
404 config.set('OpenStack', 'subnet_cidr', subnet_cidr)
405 config.set('OpenStack', 'internal_network', internal_network)
406 config.set('OpenStack', 'floating_network', floating_network)
407 config.add_section('rapid')
408 config.set('rapid', 'loglevel', loglevel)
409 config.set('rapid', 'version', version)
410 config.set('rapid', 'total_number_of_VMs', total_number_of_VMs)
411 config.set('DEFAULT', 'admin_ip', 'none')
412 # Writing the environment file
413 with open(stack+'.env', 'wb') as envfile:
414     config.write(envfile)
415