4 ## Copyright (c) 2010-2017 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 from __future__ import print_function
29 from logging.handlers import RotatingFileHandler
30 from logging import handlers
31 from prox_ctrl import prox_ctrl
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
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]")
71 print("Command-line interface to createrapid")
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.")
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)
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("===========================================")
101 print("===========================================")
107 for opt, arg in opts:
108 if opt in ("-h", "--help"):
111 if opt in ("-v", "--version"):
112 print("Rapid Automated Performance Indication for Dataplane "+version)
114 if opt in ("--stack"):
116 print ("Using '"+stack+"' as name for the stack")
117 elif opt in ("--yaml"):
119 print ("Using stack: "+yaml)
120 elif opt in ("--key"):
122 print ("Using key: "+key)
123 elif opt in ("--flavor"):
125 print ("Using flavor: "+flavor)
126 elif opt in ("--image"):
128 print ("Using image: "+image)
129 elif opt in ("--image_file"):
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"):
137 print ("Using dataplane subnet: "+ subnet)
138 elif opt in ("--subnet_cidr"):
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"):
158 print ("Log level: "+ loglevel)
162 screen_formatter = logging.Formatter("%(message)s")
163 file_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
165 # get a top-level logger,
167 # BUT PREVENT IT from propagating messages to the root logger
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)
176 # create a console handler
177 # and set its log level to the command-line option
179 console_handler = logging.StreamHandler(sys.stdout)
180 console_handler.setLevel(logging.INFO)
181 console_handler.setFormatter(screen_formatter)
183 # create a file handler
184 # and set its log level to DEBUG
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)
192 # add handlers to the logger
194 log.addHandler(file_handler)
195 log.addHandler(console_handler)
197 # Check if log exists and should therefore be rolled
198 needRoll = os.path.isfile(log_file)
201 # This is a stale log, so roll it
204 log.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime())
206 # Roll over on application start
207 log.handlers[0].doRollover()
210 log.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime())
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
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")
222 log.exception("Control plane network " + internal_network + " not existing")
223 raise Exception("Control plane network " + internal_network + " not existing")
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
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")
235 log.exception("Floating ip network " + floating_network + " not existing")
236 raise Exception("Floating ip network " + floating_network + " not existing")
238 # Checking if the image already exists, if not create it
239 log.debug("Checking image: "+image)
240 cmd = 'openstack image show '+image
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")
247 log.info('Creating image ...')
248 cmd = 'openstack image create --disk-format qcow2 --container-format bare --public --file ./'+image_file+ ' ' +image
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)
257 log.exception("Failed to create image")
258 raise Exception("Failed to create image")
260 # Checking if the key already exists, if not create it
261 log.debug("Checking key: "+key)
262 cmd = 'openstack keypair show '+key
264 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
265 KeyExist = subprocess.check_output(cmd , shell=True).strip()
267 log.info("Key ("+key+") already installed")
269 log.info('Creating key ...')
270 cmd = 'openstack keypair create '+ key + '>' +key+'.pem'
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
277 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
278 KeyExist = subprocess.check_output(cmd , shell=True).strip()
280 log.info("Key created")
282 log.exception("Failed to create key: " + key)
283 raise Exception("Failed to create key: " + key)
285 # Checking if the flavor already exists, if not create it
286 log.debug("Checking flavor: "+flavor)
287 cmd = 'openstack flavor show '+flavor
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")
294 log.info('Creating flavor ...')
295 cmd = 'openstack flavor create '+flavor+' --ram 8192 --disk 20 --vcpus 4'
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"'
302 subprocess.check_call(cmd , shell=True)
303 log.info("Flavor created")
305 log.exception("Failed to create flavor: " + flavor)
306 raise Exception("Failed to create flavor: " + flavor)
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
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")
317 log.info('Creating dataplane network ...')
318 cmd = 'openstack network create '+dataplane_network
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")
325 log.exception("Failed to create dataplane network: " + dataplane_network)
326 raise Exception("Failed to create dataplane network: " + dataplane_network)
328 # Checking if the dataplane subnet already exists, if not create it
329 log.debug("Checking subnet: "+subnet)
330 cmd = 'openstack subnet show '+ subnet
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")
337 log.info('Creating subnet ...')
338 cmd = 'openstack subnet create --network ' + dataplane_network + ' --subnet-range ' + subnet_cidr +' --gateway none ' + subnet
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")
345 log.exception("Failed to create subnet: " + subnet)
346 raise Exception("Failed to create subnet: " + subnet)
348 # Checking if the stack already exists, if not create it
349 log.debug("Checking Stack: "+stack)
350 cmd = 'openstack stack show '+stack
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
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")
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
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)
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))
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)