Some of the repetitive violations were suppressed.
15.40KiB; Python | 2018-01-28 18:59:31+01 | SLOC 354
1
#!/usr/bin/python
2
3
##
4
# Copyright(c) 2010-2015 Intel Corporation.
5
# Copyright(c) 2016-2018 Viosoft Corporation.
6
# All rights reserved.
7
#
8
# Redistribution and use in source and binary forms, with or without
9
# modification, are permitted provided that the following conditions
10
# are met:
11
#
12
#   * Redistributions of source code must retain the above copyright
13
#     notice, this list of conditions and the following disclaimer.
14
#   * Redistributions in binary form must reproduce the above copyright
15
#     notice, this list of conditions and the following disclaimer in
16
#     the documentation and/or other materials provided with the
17
#     distribution.
18
#   * Neither the name of Intel Corporation nor the names of its
19
#     contributors may be used to endorse or promote products derived
20
#     from this software without specific prior written permission.
21
#
22
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
##
34
35
from __future__ import print_function
36
37
import os
38 1
import stat
39
import sys
40
import time
41
import subprocess
42
import getopt
43
import re
44
import logging
45 1
from logging.handlers import RotatingFileHandler
46 1
from logging import handlers
47 1
from prox_ctrl import prox_ctrl
48 1
import ConfigParser
49
50
version="17.09.03"
51
stack = "rapidTestEnv" #Default string for stack
52
yaml = "rapid.yaml" #Default string for yaml file
53
key = "prox" # This is also the default in the yaml file....
54
flavor = "prox_flavor" # This is also the default in the yaml file....
55
image = "rapidVM" # This is also the default in the yaml file....
56
image_file = "rapidVM.qcow2"
57
dataplane_network = "dataplane-network" # This is also the default in the yaml file....
58
subnet = "dpdk-subnet" #Hardcoded at this moment
59
subnet_cidr="10.10.10.0/24" # cidr for dataplane
60
admin_network="admin_internal_net"
61
loglevel="DEBUG" # sets log level for writing to file
62
runtime=10 # time in seconds for 1 test run
63
64
def usage():
65 1
	print("usage: rapid       [--version] [-v]")
66 1
	print("                   [--stack STACK_NAME]")
67 1
	print("                   [--yaml YAML_FILE]")
68 1
	print("                   [--key KEY_NAME]")
69 1
	print("                   [--flavor FLAVOR_NAME]")
70 1
	print("                   [--image IMAGE_NAME]")
71 1
	print("                   [--image_file IMAGE_FILE]")
72 1
	print("                   [--dataplane_network DP_NETWORK]")
73 1
	print("                   [--admin_network ADMIN_NETWORK]")
74 1
	print("                   [--log DEBUG|INFO|WARNING|ERROR|CRITICAL")
75
	print("                   [-h] [--help]")
76
	print("")
77
	print("Command-line interface to RAPID")
78
	print("")
79
	print("optional arguments:")
80
	print("  -v,  --version           	Show program's version number and exit")
81
	print("  --stack STACK_NAME       	Specify a name for the heat stack. Default is rapidTestEnv.")
82
	print("  --yaml YAML_FILE         	Specify the yaml file to be used. Default is rapid.yaml.")
83
	print("  --key KEY_NAME           	Specify the key to be used. Default is prox.")
84
	print("  --flavor FLAVOR_NAME     	Specify the flavor to be used. Default is prox_flavor.")
85
	print("  --image IMAGE_NAME       	Specify the image to be used. Default is rapidVM.")
86
	print("  --image_file IMAGE_FILE  	Specify the image qcow2 file to be used. Default is rapidVM.qcow2.")
87
	print("  --dataplane_network NETWORK 	Specify the network name to be used for the dataplane. Default is dataplane-network.")
88
	print("  --admin_network NETWORK 	Specify the network name to be used for the control plane. Default is admin-network.")
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 rapidTestEnv")
94
	print("Note that rapidTestEnv is the default stack name. Replace with STACK_NAME if needed")
95
96
try:
97
	opts, args = getopt.getopt(sys.argv[1:], "vh", ["version","help", "yaml=","stack=","key=","flavor=","image=","dataplane_network=","admin_network=","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 ("--admin_network"):
136
		admin_network = arg
137
		print ("Using controle plane network: "+ admin_network)
138
	elif opt in ("--log"):
139
		loglevel = arg
140
		print ("Log level: "+ loglevel)
141
142
143
# create formatters
144
screen_formatter = logging.Formatter("%(message)s")
145
file_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
146
147
# get a top-level logger,
148
# set its log level,
149
# BUT PREVENT IT from propagating messages to the root logger
150
#
151
log = logging.getLogger()
152
numeric_level = getattr(logging, loglevel.upper(), None)
153
if not isinstance(numeric_level, int):
154
    raise ValueError('Invalid log level: %s' % loglevel)
155
log.setLevel(numeric_level)
156
log.propagate = 0
157
158
# create a console handler
159
# and set its log level to the command-line option␣
160
#␣
161
console_handler = logging.StreamHandler(sys.stdout)
162
console_handler.setLevel(logging.INFO)
163
console_handler.setFormatter(screen_formatter)
164
165
# create a file handler
166
# and set its log level to DEBUG
167
#
168
log_file = 'CREATE' +stack +'.log'
169
file_handler = logging.handlers.RotatingFileHandler(log_file, backupCount=10)
170
#file_handler = log.handlers.TimedRotatingFileHandler(log_file, 'D', 1, 5)
171
file_handler.setLevel(numeric_level)
172
file_handler.setFormatter(file_formatter)
173
174
# add handlers to the logger
175
#
176
log.addHandler(file_handler)
177
log.addHandler(console_handler)
178
179
# Check if log exists and should therefore be rolled
180
needRoll = os.path.isfile(log_file)
181
182
183
# This is a stale log, so roll it
184
if needRoll:␣␣␣␣
185
    # Add timestamp
186
    log.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime())
187
188
    # Roll over on application start
189
    log.handlers[0].doRollover()
190
191
# Add timestamp
192
log.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime())
193
194
log.debug("createrapid.py version: "+version)
195
# Checking if the control network already exists, if not, stop the script
196
log.debug("Checking control plane network: "+admin_network)
197
cmd = 'openstack network show '+admin_network
198
log.debug (cmd)
199
cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
200
NetworkExist = subprocess.check_output(cmd , shell=True).strip()
201
if NetworkExist == 'ACTIVE':
202
	log.info("Control plane network ("+admin_network+")  already active")
203
else:
204
	log.exception("Control plane network " + admin_network + " not existing")
205
	raise Exception("Control plane network " + admin_network + " not existing")
206
207
# Checking if the image already exists, if not create it
208
log.debug("Checking image: "+image)
209
cmd = 'openstack image show '+image
210
log.debug(cmd)
211
cmd = cmd +' |grep "status " | tr -s " " | cut -d" " -f 4'
212
ImageExist = subprocess.check_output(cmd , shell=True).strip()
213
if ImageExist == 'active':
214
	log.info("Image ("+image+") already available")
215
else:
216
	log.info('Creating image ...')
217
	cmd = 'openstack image create --disk-format qcow2 --container-format bare --public --file ./'+image_file+ ' ' +image
218
	log.debug(cmd)
219
	cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
220
	ImageExist = subprocess.check_output(cmd , shell=True).strip()
221
	if ImageExist == 'active':
222
		log.info('Image created and active')
223
		cmd = 'openstack image set --property hw_vif_multiqueue_enabled="true" ' +image
224
#		subprocess.check_call(cmd , shell=True)
225
	else :
226
		log.exception("Failed to create image")
227
		raise Exception("Failed to create image")
228
229
# Checking if the key already exists, if not create it
230
log.debug("Checking key: "+key)
231
cmd = 'openstack keypair show '+key
232
log.debug (cmd)
233
cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
234
KeyExist = subprocess.check_output(cmd , shell=True).strip()
235
if KeyExist == key:
236
	log.info("Key ("+key+") already installed")
237
else:
238
	log.info('Creating key ...')
239
	cmd = 'openstack keypair create '+ key + '>' +key+'.pem'
240
	log.debug(cmd)
241
	subprocess.check_call(cmd , shell=True)
242
	cmd = 'chmod 600 ' +key+'.pem'
243
	subprocess.check_call(cmd , shell=True)
244
	cmd = 'openstack keypair show '+key
245
	log.debug(cmd)
246
	cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
247
	KeyExist = subprocess.check_output(cmd , shell=True).strip()
248
	if KeyExist == key:
249
		log.info("Key created")
250
	else :
251
		log.exception("Failed to create key: " + key)
252
		raise Exception("Failed to create key: " + key)
253
254
# Checking if the flavor already exists, if not create it
255
log.debug("Checking flavor: "+flavor)
256
cmd = 'openstack flavor show '+flavor
257
log.debug (cmd)
258
cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
259
FlavorExist = subprocess.check_output(cmd , shell=True).strip()
260
if FlavorExist == flavor:
261
	log.info("Flavor ("+flavor+") already installed")
262
else:
263
	log.info('Creating flavor ...')
264
	cmd = 'openstack flavor create '+flavor+' --ram 8192 --disk 20 --vcpus 4'
265
	log.debug(cmd)
266
	cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
267
	FlavorExist = subprocess.check_output(cmd , shell=True).strip()
268
	if FlavorExist == flavor:
269
		cmd = 'openstack flavor set '+ flavor +' --property hw:mem_page_size="large" --property hw:cpu_policy="dedicated" --property hw:cpu_threads_policy="isolate"'
270
		log.debug(cmd)
271
		subprocess.check_call(cmd , shell=True)
272
		log.info("Flavor created")
273
	else :
274
		log.exception("Failed to create flavor: " + flavor)
275
		raise Exception("Failed to create flavor: " + flavor)
276
277
# Checking if the dataplane network already exists, if not create it
278
log.debug("Checking dataplane network: "+dataplane_network)
279
cmd = 'openstack network show '+dataplane_network
280
log.debug (cmd)
281
cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
282
NetworkExist = subprocess.check_output(cmd , shell=True).strip()
283
if NetworkExist == 'ACTIVE':
284
	log.info("Dataplane network ("+dataplane_network+") already active")
285
else:
286
	log.info('Creating dataplane network ...')
287
	cmd = 'openstack network create '+dataplane_network
288
	log.debug(cmd)
289
	cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
290
	NetworkExist = subprocess.check_output(cmd , shell=True).strip()
291
	if NetworkExist == 'ACTIVE':
292
		log.info("Dataplane network created")
293
	else :
294
		log.exception("Failed to create dataplane network: " + dataplane_network)
295
		raise Exception("Failed to create dataplane network: " + dataplane_network)
296
297
# Checking if the dataplane subnet already exists, if not create it
298
log.debug("Checking subnet: "+subnet)
299
cmd = 'openstack subnet show '+ subnet
300
log.debug (cmd)
301
cmd = cmd +' |grep "name " | tr -s " " | cut -d"|" -f 3'
302
SubnetExist = subprocess.check_output(cmd , shell=True).strip()
303
if SubnetExist == subnet:
304
	log.info("Subnet (" +subnet+ ") already exists")
305
else:
306
	log.info('Creating subnet ...')
307
	cmd = 'openstack subnet create --network ' + dataplane_network + ' --subnet-range ' + subnet_cidr +' --gateway none ' + subnet
308
	log.debug(cmd)
309
	cmd = cmd + ' |grep "name " | tr -s " " | cut -d"|" -f 3'
310
	SubnetExist = subprocess.check_output(cmd , shell=True).strip()
311
	if SubnetExist == subnet:
312
		log.info("Subnet created")
313
	else :
314
		log.exception("Failed to create subnet: " + subnet)
315
		raise Exception("Failed to create subnet: " + subnet)
316
317
# Checking if the stack already exists, if not create it
318
log.debug("Checking Stack: "+stack)
319
cmd = 'openstack stack show '+stack
320
log.debug (cmd)
321
cmd = cmd+' |grep "stack_status " | tr -s " " | cut -d"|" -f 3'
322
StackRunning = subprocess.check_output(cmd , shell=True).strip()
323
if StackRunning == '':
324
	log.info('Creating Stack ...')
325
	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␣
326
	log.debug(cmd)
327
	cmd = cmd + ' |grep "stack_status " | tr -s " " | cut -d"|" -f 3'
328
	StackRunning = subprocess.check_output(cmd , shell=True).strip()
329
if StackRunning != 'CREATE_COMPLETE':
330
	log.exception("Failed to create stack")
331
	raise Exception("Failed to create stack")
332
333
# Obtaining IP & MAC addresses for the VMs created in the stack
334
log.info("Stack ("+stack+") running")
335
cmd='openstack stack show -f yaml -c outputs ' + stack
336
log.debug(cmd)
337
output = subprocess.check_output(cmd , shell=True).strip()
338
matchObj = re.search('.*gen_dataplane_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)', output, re.DOTALL)
339
genDPIP = matchObj.group(1)
340
matchObj = re.search('.*gen_public_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)', output, re.DOTALL)
341
genAdminIP = matchObj.group(1)
342
matchObj = re.search('.*gen_dataplane_mac.*?([a-fA-F0-9:]{17})', output, re.DOTALL)
343
genDPmac = matchObj.group(1)
344
matchObj = re.search('.*sut_dataplane_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)', output, re.DOTALL)
345
sutDPIP = matchObj.group(1)
346
matchObj = re.search('.*sut_public_ip.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)', output, re.DOTALL)
347
sutAdminIP = matchObj.group(1)
348
matchObj = re.search('.*sut_dataplane_mac.*?([a-fA-F0-9:]{17})', output, re.DOTALL)
349
sutDPmac = matchObj.group(1)
350
log.info('Generator: (admin IP: '+ genAdminIP + '), (dataplane IP: ' + genDPIP+'), (dataplane MAC: ' +genDPmac+')')
351
log.info('SUT:       (admin IP: '+ sutAdminIP + '), (dataplane IP: ' + sutDPIP+'), (dataplane MAC: ' +sutDPmac+')')
352
config = ConfigParser.RawConfigParser()
353
config.add_section('Generator')
354
config.set('Generator', 'admin_ip', genAdminIP)
355
config.set('Generator', 'dp_ip', genDPIP)
356
config.set('Generator', 'dp_mac', genDPmac)
357
config.add_section('SUT')
358
config.set('SUT', 'admin_ip', sutAdminIP)
359
config.set('SUT', 'dp_ip', sutDPIP)
360
config.set('SUT', 'dp_mac', sutDPmac)
361
config.add_section('OpenStack')
362
config.set('OpenStack', 'stack', stack)
363
config.set('OpenStack', 'yaml', yaml)
364
config.set('OpenStack', 'key', key)
365
config.set('OpenStack', 'flavor', flavor)
366
config.set('OpenStack', 'image', image)
367
config.set('OpenStack', 'image_file', image_file)
368
config.set('OpenStack', 'dataplane_network', dataplane_network)
369
config.set('OpenStack', 'subnet', subnet)
370
config.set('OpenStack', 'subnet_cidr', subnet_cidr)
371
config.set('OpenStack', 'admin_network', admin_network)
372
config.add_section('rapid')
373
config.set('rapid', 'loglevel', loglevel)
374
config.set('rapid', 'version', version)
375
config.add_section('DEFAULT')
376
config.set('DEFAULT', 'admin_ip', 'none')
377
# Writing our configuration file
378
with open(stack+'.cfg', 'wb') as configfile:
379
    config.write(configfile)