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 = "rapidTestEnv" #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" #Hardcoded at this moment
43 subnet_cidr="10.10.10.0/24" # cidr for dataplane
44 admin_network="admin_internal_net"
45 loglevel="DEBUG" # sets log level for writing to file
46 runtime=10 # time in seconds for 1 test run
49 print("usage: rapid [--version] [-v]")
50 print(" [--stack STACK_NAME]")
51 print(" [--yaml YAML_FILE]")
52 print(" [--key KEY_NAME]")
53 print(" [--flavor FLAVOR_NAME]")
54 print(" [--image IMAGE_NAME]")
55 print(" [--image_file IMAGE_FILE]")
56 print(" [--dataplane_network DP_NETWORK]")
57 print(" [--admin_network ADMIN_NETWORK]")
58 print(" [--log DEBUG|INFO|WARNING|ERROR|CRITICAL")
59 print(" [-h] [--help]")
61 print("Command-line interface to RAPID")
63 print("optional arguments:")
64 print(" -v, --version Show program's version number and exit")
65 print(" --stack STACK_NAME Specify a name for the heat stack. Default is rapidTestEnv.")
66 print(" --yaml YAML_FILE Specify the yaml file to be used. Default is rapid.yaml.")
67 print(" --key KEY_NAME Specify the key to be used. Default is prox.")
68 print(" --flavor FLAVOR_NAME Specify the flavor to be used. Default is prox_flavor.")
69 print(" --image IMAGE_NAME Specify the image to be used. Default is rapidVM.")
70 print(" --image_file IMAGE_FILE Specify the image qcow2 file to be used. Default is rapidVM.qcow2.")
71 print(" --dataplane_network NETWORK Specify the network name to be used for the dataplane. Default is dataplane-network.")
72 print(" --admin_network NETWORK Specify the network name to be used for the control plane. Default is admin-network.")
73 print(" --log Specify logging level for log file output, screen output level is hard coded")
74 print(" -h, --help Show help message and exit.")
76 print("To delete the rapid stack, type the following command")
77 print(" openstack stack delete --yes --wait rapidTestEnv")
78 print("Note that rapidTestEnv is the default stack name. Replace with STACK_NAME if needed")
81 opts, args = getopt.getopt(sys.argv[1:], "vh", ["version","help", "yaml=","stack=","key=","flavor=","image=","dataplane_network=","admin_network=","log="])
82 except getopt.GetoptError as err:
83 print("===========================================")
85 print("===========================================")
92 if opt in ("-h", "--help"):
95 if opt in ("-v", "--version"):
96 print("Rapid Automated Performance Indication for Dataplane "+version)
98 if opt in ("--stack"):
100 print ("Using '"+stack+"' as name for the stack")
101 elif opt in ("--yaml"):
103 print ("Using stack: "+yaml)
104 elif opt in ("--key"):
106 print ("Using key: "+key)
107 elif opt in ("--flavor"):
109 print ("Using flavor: "+flavor)
110 elif opt in ("--image"):
112 print ("Using image: "+image)
113 elif opt in ("--image_file"):
115 print ("Using qcow2 file: "+image_file)
116 elif opt in ("--dataplane_network"):
117 dataplane_network = arg
118 print ("Using dataplane network: "+ dataplane_network)
119 elif opt in ("--admin_network"):
121 print ("Using controle plane network: "+ admin_network)
122 elif opt in ("--log"):
124 print ("Log level: "+ loglevel)
128 screen_formatter = logging.Formatter("%(message)s")
129 file_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
131 # get a top-level logger,
133 # BUT PREVENT IT from propagating messages to the root logger
135 log = logging.getLogger()
136 numeric_level = getattr(logging, loglevel.upper(), None)
137 if not isinstance(numeric_level, int):
138 raise ValueError('Invalid log level: %s' % loglevel)
139 log.setLevel(numeric_level)
142 # create a console handler
143 # and set its log level to the command-line option
145 console_handler = logging.StreamHandler(sys.stdout)
146 console_handler.setLevel(logging.INFO)
147 console_handler.setFormatter(screen_formatter)
149 # create a file handler
150 # and set its log level to DEBUG
152 log_file = 'CREATE' +stack +'.log'
153 file_handler = logging.handlers.RotatingFileHandler(log_file, backupCount=10)
154 #file_handler = log.handlers.TimedRotatingFileHandler(log_file, 'D', 1, 5)
155 file_handler.setLevel(numeric_level)
156 file_handler.setFormatter(file_formatter)
158 # add handlers to the logger
160 log.addHandler(file_handler)
161 log.addHandler(console_handler)
163 # Check if log exists and should therefore be rolled
164 needRoll = os.path.isfile(log_file)
167 # This is a stale log, so roll it
170 log.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime())
172 # Roll over on application start
173 log.handlers[0].doRollover()
176 log.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime())
178 log.debug("createrapid.py version: "+version)
179 # Checking if the control network already exists, if not, stop the script
180 log.debug("Checking control plane network: "+admin_network)
181 cmd = 'openstack network show '+admin_network
183 cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
184 NetworkExist = subprocess.check_output(cmd , shell=True).strip()
185 if NetworkExist == 'ACTIVE':
186 log.info("Control plane network ("+admin_network+") already active")
188 log.exception("Control plane network " + admin_network + " not existing")
189 raise Exception("Control plane network " + admin_network + " not existing")
191 # Checking if the image already exists, if not create it
192 log.debug("Checking image: "+image)
193 cmd = 'openstack image show '+image
195 cmd = cmd +' |grep "status " | tr -s " " | cut -d" " -f 4'
196 ImageExist = subprocess.check_output(cmd , shell=True).strip()
197 if ImageExist == 'active':
198 log.info("Image ("+image+") already available")
200 log.info('Creating image ...')
201 cmd = 'openstack image create --disk-format qcow2 --container-format bare --public --file ./'+image_file+ ' ' +image
203 cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
204 ImageExist = subprocess.check_output(cmd , shell=True).strip()
205 if ImageExist == 'active':
206 log.info('Image created and active')
207 cmd = 'openstack image set --property hw_vif_multiqueue_enabled="true" ' +image
208 # subprocess.check_call(cmd , shell=True)
210 log.exception("Failed to create image")
211 raise Exception("Failed to create image")
213 # Checking if the key already exists, if not create it
214 log.debug("Checking key: "+key)
215 cmd = 'openstack keypair show '+key
217 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
218 KeyExist = subprocess.check_output(cmd , shell=True).strip()
220 log.info("Key ("+key+") already installed")
222 log.info('Creating key ...')
223 cmd = 'openstack keypair create '+ key + '>' +key+'.pem'
225 subprocess.check_call(cmd , shell=True)
226 cmd = 'chmod 600 ' +key+'.pem'
227 subprocess.check_call(cmd , shell=True)
228 cmd = 'openstack keypair show '+key
230 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
231 KeyExist = subprocess.check_output(cmd , shell=True).strip()
233 log.info("Key created")
235 log.exception("Failed to create key: " + key)
236 raise Exception("Failed to create key: " + key)
238 # Checking if the flavor already exists, if not create it
239 log.debug("Checking flavor: "+flavor)
240 cmd = 'openstack flavor show '+flavor
242 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
243 FlavorExist = subprocess.check_output(cmd , shell=True).strip()
244 if FlavorExist == flavor:
245 log.info("Flavor ("+flavor+") already installed")
247 log.info('Creating flavor ...')
248 cmd = 'openstack flavor create '+flavor+' --ram 8192 --disk 20 --vcpus 4'
250 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
251 FlavorExist = subprocess.check_output(cmd , shell=True).strip()
252 if FlavorExist == flavor:
253 cmd = 'openstack flavor set '+ flavor +' --property hw:mem_page_size="large" --property hw:cpu_policy="dedicated" --property hw:cpu_threads_policy="isolate"'
255 subprocess.check_call(cmd , shell=True)
256 log.info("Flavor created")
258 log.exception("Failed to create flavor: " + flavor)
259 raise Exception("Failed to create flavor: " + flavor)
261 # Checking if the dataplane network already exists, if not create it
262 log.debug("Checking dataplane network: "+dataplane_network)
263 cmd = 'openstack network show '+dataplane_network
265 cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
266 NetworkExist = subprocess.check_output(cmd , shell=True).strip()
267 if NetworkExist == 'ACTIVE':
268 log.info("Dataplane network ("+dataplane_network+") already active")
270 log.info('Creating dataplane network ...')
271 cmd = 'openstack network create '+dataplane_network
273 cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
274 NetworkExist = subprocess.check_output(cmd , shell=True).strip()
275 if NetworkExist == 'ACTIVE':
276 log.info("Dataplane network created")
278 log.exception("Failed to create dataplane network: " + dataplane_network)
279 raise Exception("Failed to create dataplane network: " + dataplane_network)
281 # Checking if the dataplane subnet already exists, if not create it
282 log.debug("Checking subnet: "+subnet)
283 cmd = 'openstack subnet show '+ subnet
285 cmd = cmd +' |grep "name " | tr -s " " | cut -d"|" -f 3'
286 SubnetExist = subprocess.check_output(cmd , shell=True).strip()
287 if SubnetExist == subnet:
288 log.info("Subnet (" +subnet+ ") already exists")
290 log.info('Creating subnet ...')
291 cmd = 'openstack subnet create --network ' + dataplane_network + ' --subnet-range ' + subnet_cidr +' --gateway none ' + subnet
293 cmd = cmd + ' |grep "name " | tr -s " " | cut -d"|" -f 3'
294 SubnetExist = subprocess.check_output(cmd , shell=True).strip()
295 if SubnetExist == subnet:
296 log.info("Subnet created")
298 log.exception("Failed to create subnet: " + subnet)
299 raise Exception("Failed to create subnet: " + subnet)
301 # Checking if the stack already exists, if not create it
302 log.debug("Checking Stack: "+stack)
303 cmd = 'openstack stack show '+stack
305 cmd = cmd+' |grep "stack_status " | tr -s " " | cut -d"|" -f 3'
306 StackRunning = subprocess.check_output(cmd , shell=True).strip()
307 if StackRunning == '':
308 log.info('Creating Stack ...')
309 cmd = 'openstack stack create -t '+ yaml + ' --parameter flavor="'+flavor +'" --parameter key="'+ key + '" --parameter image="'+image + '" --parameter dataplane_network="'+dataplane_network+ '" --parameter admin_network="'+admin_network+'" --wait '+stack
311 cmd = cmd + ' |grep "stack_status " | tr -s " " | cut -d"|" -f 3'
312 StackRunning = subprocess.check_output(cmd , shell=True).strip()
313 if StackRunning != 'CREATE_COMPLETE':
314 log.exception("Failed to create stack")
315 raise Exception("Failed to create stack")
317 # Obtaining IP & MAC addresses for the VMs created in the stack
318 log.info("Stack ("+stack+") running")
319 cmd='openstack stack show -f yaml -c outputs ' + stack
321 output = subprocess.check_output(cmd , shell=True).strip()
322 matchObj = re.search('.*gen_dataplane_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)', output, re.DOTALL)
323 genDPIP = matchObj.group(1)
324 matchObj = re.search('.*gen_public_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)', output, re.DOTALL)
325 genAdminIP = matchObj.group(1)
326 matchObj = re.search('.*gen_dataplane_mac.*?([a-fA-F0-9:]{17})', output, re.DOTALL)
327 genDPmac = matchObj.group(1)
328 matchObj = re.search('.*sut_dataplane_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)', output, re.DOTALL)
329 sutDPIP = matchObj.group(1)
330 matchObj = re.search('.*sut_public_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)', output, re.DOTALL)
331 sutAdminIP = matchObj.group(1)
332 matchObj = re.search('.*sut_dataplane_mac.*?([a-fA-F0-9:]{17})', output, re.DOTALL)
333 sutDPmac = matchObj.group(1)
334 log.info('Generator: (admin IP: '+ genAdminIP + '), (dataplane IP: ' + genDPIP+'), (dataplane MAC: ' +genDPmac+')')
335 log.info('SUT: (admin IP: '+ sutAdminIP + '), (dataplane IP: ' + sutDPIP+'), (dataplane MAC: ' +sutDPmac+')')
336 config = ConfigParser.RawConfigParser()
337 config.add_section('Generator')
338 config.set('Generator', 'admin_ip', genAdminIP)
339 config.set('Generator', 'dp_ip', genDPIP)
340 config.set('Generator', 'dp_mac', genDPmac)
341 config.add_section('SUT')
342 config.set('SUT', 'admin_ip', sutAdminIP)
343 config.set('SUT', 'dp_ip', sutDPIP)
344 config.set('SUT', 'dp_mac', sutDPmac)
345 config.add_section('OpenStack')
346 config.set('OpenStack', 'stack', stack)
347 config.set('OpenStack', 'yaml', yaml)
348 config.set('OpenStack', 'key', key)
349 config.set('OpenStack', 'flavor', flavor)
350 config.set('OpenStack', 'image', image)
351 config.set('OpenStack', 'image_file', image_file)
352 config.set('OpenStack', 'dataplane_network', dataplane_network)
353 config.set('OpenStack', 'subnet', subnet)
354 config.set('OpenStack', 'subnet_cidr', subnet_cidr)
355 config.set('OpenStack', 'admin_network', admin_network)
356 config.add_section('rapid')
357 config.set('rapid', 'loglevel', loglevel)
358 config.set('rapid', 'version', version)
359 config.set('DEFAULT', 'admin_ip', 'none')
360 # Writing our configuration file
361 with open(stack+'.cfg', 'wb') as configfile:
362 config.write(configfile)