f21b91d71412e9945ee7ecd020c4d8d0eafc82eb
[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.6.15"
35 stack = "rapid" #Default string for stack. This is not an OpenStack Heat stack, just a group of VMs
36 vms = "rapidVMs" #Default string for vms file
37 key = "prox" # default name for kay
38 image = "rapidVM" # default name for the image
39 image_file = "rapidVM.qcow2"
40 dataplane_network = "dataplane-network" # default name for the dataplane network
41 subnet = "dpdk-subnet" #subnet for dataplane
42 subnet_cidr="10.10.10.0/24" # cidr for dataplane
43 internal_network="admin_internal_net"
44 floating_network="admin_floating_net"
45 loglevel="DEBUG" # sets log level for writing to file
46 runtime=10 # time in seconds for 1 test run
47
48 def usage():
49         print("usage: createrapid [--version] [-v]")
50         print("                   [--stack STACK_NAME]")
51         print("                   [--vms VMS_FILE]")
52         print("                   [--key KEY_NAME]")
53         print("                   [--image IMAGE_NAME]")
54         print("                   [--image_file IMAGE_FILE]")
55         print("                   [--dataplane_network DP_NETWORK]")
56         print("                   [--subnet DP_SUBNET]")
57         print("                   [--subnet_cidr SUBNET_CIDR]")
58         print("                   [--internal_network ADMIN_NETWORK]")
59         print("                   [--floating_network ADMIN_NETWORK]")
60         print("                   [--log DEBUG|INFO|WARNING|ERROR|CRITICAL]")
61         print("                   [-h] [--help]")
62         print("")
63         print("Command-line interface to createrapid")
64         print("")
65         print("optional arguments:")
66         print("  -v,  --version                 Show program's version number and exit")
67         print("  --stack STACK_NAME             Specify a name for the stack. Default is %s."%stack)
68         print("  --vms VMS_FILE                 Specify the vms file to be used. Default is %s.vms."%vms)
69         print("  --key KEY_NAME                 Specify the key to be used. Default is %s."%key)
70         print("  --image IMAGE_NAME             Specify the image to be used. Default is %s."%image)
71         print("  --image_file IMAGE_FILE        Specify the image qcow2 file to be used. Default is %s."%image_file)
72         print("  --dataplane_network NETWORK    Specify the network name to be used for the dataplane. Default is %s."%dataplane_network)
73         print("  --subnet DP_SUBNET             Specify the subnet name to be used for the dataplane. Default is %s."%subnet)
74         print("  --subnet_cidr SUBNET_CIDR      Specify the subnet CIDR to be used for the dataplane. Default is %s."%subnet_cidr)
75         print("  --internal_network NETWORK     Specify the network name to be used for the control plane. Default is %s."%internal_network)
76         print("  --floating_network NETWORK     Specify the external floating ip network name. Default is %s. NO if no floating ip used."%floating_network)
77         print("  --log                          Specify logging level for log file output, screen output level is hard coded")
78         print("  -h, --help                     Show help message and exit.")
79         print("")
80
81 try:
82         opts, args = getopt.getopt(sys.argv[1:], "vh", ["version","help", "vms=","stack=","key=","image=","image_file=","dataplane_network=","subnet=","subnet_cidr=","internal_network=","floating_network=","log="])
83 except getopt.GetoptError as err:
84         print("===========================================")
85         print(str(err))
86         print("===========================================")
87         usage()
88         sys.exit(2)
89 if args:
90         usage()
91         sys.exit(2)
92 for opt, arg in opts:
93         if opt in ("-h", "--help"):
94                 usage()
95                 sys.exit()
96         if opt in ("-v", "--version"):
97                 print("Rapid Automated Performance Indication for Dataplane "+version)
98                 sys.exit()
99         if opt in ("--stack"):
100                 stack = arg
101                 print ("Using '"+stack+"' as name for the stack")
102         elif opt in ("--vms"):
103                 vms = arg
104                 print ("Using Virtual Machines Description: "+vms)
105         elif opt in ("--key"):
106                 key = arg
107                 print ("Using key: "+key)
108         elif opt in ("--image"):
109                 image = arg
110                 print ("Using image: "+image)
111         elif opt in ("--image_file"):
112                 image_file = arg
113                 print ("Using qcow2 file: "+image_file)
114         elif opt in ("--dataplane_network"):
115                 dataplane_network = arg
116                 print ("Using dataplane network: "+ dataplane_network)
117         elif opt in ("--subnet"):
118                 subnet = arg
119                 print ("Using dataplane subnet: "+ subnet)
120         elif opt in ("--subnet_cidr"):
121                 subnet_cidr = arg
122                 print ("Using dataplane subnet: "+ subnet_cidr)
123         elif opt in ("--internal_network"):
124                 internal_network = arg
125                 print ("Using control plane network: "+ internal_network)
126         elif opt in ("--floating_network"):
127                 floating_network = arg
128                 print ("Using floating ip network: "+ floating_network)
129         elif opt in ("--log"):
130                 loglevel = arg
131                 print ("Log level: "+ loglevel)
132
133
134 # create formatters
135 screen_formatter = logging.Formatter("%(message)s")
136 file_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
137
138 # get a top-level logger,
139 # set its log level,
140 # BUT PREVENT IT from propagating messages to the root logger
141 #
142 log = logging.getLogger()
143 numeric_level = getattr(logging, loglevel.upper(), None)
144 if not isinstance(numeric_level, int):
145     raise ValueError('Invalid log level: %s' % loglevel)
146 log.setLevel(numeric_level)
147 log.propagate = 0
148
149 # create a console handler
150 # and set its log level to the command-line option 
151
152 console_handler = logging.StreamHandler(sys.stdout)
153 console_handler.setLevel(logging.INFO)
154 console_handler.setFormatter(screen_formatter)
155
156 # create a file handler
157 # and set its log level to DEBUG
158 #
159 log_file = 'CREATE' +stack +'.log'
160 file_handler = logging.handlers.RotatingFileHandler(log_file, backupCount=10)
161 #file_handler = log.handlers.TimedRotatingFileHandler(log_file, 'D', 1, 5)
162 file_handler.setLevel(numeric_level)
163 file_handler.setFormatter(file_formatter)
164
165 # add handlers to the logger
166 #
167 log.addHandler(file_handler)
168 log.addHandler(console_handler)
169
170 # Check if log exists and should therefore be rolled
171 needRoll = os.path.isfile(log_file)
172
173
174 # This is a stale log, so roll it
175 if needRoll:    
176     # Add timestamp
177     log.debug('\n---------\nLog closed on %s.\n---------\n' % time.asctime())
178
179     # Roll over on application start
180     log.handlers[0].doRollover()
181
182 # Add timestamp
183 log.debug('\n---------\nLog started on %s.\n---------\n' % time.asctime())
184
185 log.debug("createrapid.py version: "+version)
186 # Checking if the control network already exists, if not, stop the script
187 log.debug("Checking control plane network: "+internal_network)
188 cmd = 'openstack network show '+internal_network
189 log.debug (cmd)
190 cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
191 NetworkExist = subprocess.check_output(cmd , shell=True).strip()
192 if NetworkExist == 'ACTIVE':
193         log.info("Control plane network ("+internal_network+")  already active")
194 else:
195         log.exception("Control plane network " + internal_network + " not existing")
196         raise Exception("Control plane network " + internal_network + " not existing")
197
198 # Checking if the floating ip network already exists, if not, stop the script
199 if floating_network <>'NO':
200         log.debug("Checking floating ip network: "+floating_network)
201         cmd = 'openstack network show '+floating_network
202         log.debug (cmd)
203         cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
204         NetworkExist = subprocess.check_output(cmd , shell=True).strip()
205         if NetworkExist == 'ACTIVE':
206                 log.info("Floating ip network ("+floating_network+")  already active")
207         else:
208                 log.exception("Floating ip network " + floating_network + " not existing")
209                 raise Exception("Floating ip network " + floating_network + " not existing")
210
211 # Checking if the image already exists, if not create it
212 log.debug("Checking image: "+image)
213 cmd = 'openstack image show '+image
214 log.debug(cmd)
215 cmd = cmd +' |grep "status " | tr -s " " | cut -d" " -f 4'
216 ImageExist = subprocess.check_output(cmd , shell=True).strip()
217 if ImageExist == 'active':
218         log.info("Image ("+image+") already available")
219 else:
220         log.info('Creating image ...')
221         cmd = 'openstack image create --disk-format qcow2 --container-format bare --public --file ./'+image_file+ ' ' +image
222         log.debug(cmd)
223         cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
224         ImageExist = subprocess.check_output(cmd , shell=True).strip()
225         if ImageExist == 'active':
226                 log.info('Image created and active')
227                 cmd = 'openstack image set --property hw_vif_multiqueue_enabled="true" ' +image
228 #               subprocess.check_call(cmd , shell=True)
229         else :
230                 log.exception("Failed to create image")
231                 raise Exception("Failed to create image")
232
233 # Checking if the key already exists, if not create it
234 log.debug("Checking key: "+key)
235 cmd = 'openstack keypair show '+key
236 log.debug (cmd)
237 cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
238 KeyExist = subprocess.check_output(cmd , shell=True).strip()
239 if KeyExist == key:
240         log.info("Key ("+key+") already installed")
241 else:
242         log.info('Creating key ...')
243         cmd = 'openstack keypair create '+ key + '>' +key+'.pem'
244         log.debug(cmd)
245         subprocess.check_call(cmd , shell=True)
246         cmd = 'chmod 600 ' +key+'.pem'
247         subprocess.check_call(cmd , shell=True)
248         cmd = 'openstack keypair show '+key
249         log.debug(cmd)
250         cmd = cmd + ' |grep "name " | tr -s " " | cut -d" " -f 4'
251         KeyExist = subprocess.check_output(cmd , shell=True).strip()
252         if KeyExist == key:
253                 log.info("Key created")
254         else :
255                 log.exception("Failed to create key: " + key)
256                 raise Exception("Failed to create key: " + key)
257
258
259 # Checking if the dataplane network already exists, if not create it
260 log.debug("Checking dataplane network: "+dataplane_network)
261 cmd = 'openstack network show '+dataplane_network
262 log.debug (cmd)
263 cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
264 NetworkExist = subprocess.check_output(cmd , shell=True).strip()
265 if NetworkExist == 'ACTIVE':
266         log.info("Dataplane network ("+dataplane_network+") already active")
267 else:
268         log.info('Creating dataplane network ...')
269         cmd = 'openstack network create '+dataplane_network
270         log.debug(cmd)
271         cmd = cmd + ' |grep "status " | tr -s " " | cut -d" " -f 4'
272         NetworkExist = subprocess.check_output(cmd , shell=True).strip()
273         if NetworkExist == 'ACTIVE':
274                 log.info("Dataplane network created")
275         else :
276                 log.exception("Failed to create dataplane network: " + dataplane_network)
277                 raise Exception("Failed to create dataplane network: " + dataplane_network)
278
279 # Checking if the dataplane subnet already exists, if not create it
280 log.debug("Checking subnet: "+subnet)
281 cmd = 'openstack subnet show '+ subnet
282 log.debug (cmd)
283 cmd = cmd +' |grep "name " | tr -s " " | cut -d"|" -f 3'
284 SubnetExist = subprocess.check_output(cmd , shell=True).strip()
285 if SubnetExist == subnet:
286         log.info("Subnet (" +subnet+ ") already exists")
287 else:
288         log.info('Creating subnet ...')
289         cmd = 'openstack subnet create --network ' + dataplane_network + ' --subnet-range ' + subnet_cidr +' --gateway none ' + subnet
290         log.debug(cmd)
291         cmd = cmd + ' |grep "name " | tr -s " " | cut -d"|" -f 3'
292         SubnetExist = subprocess.check_output(cmd , shell=True).strip()
293         if SubnetExist == subnet:
294                 log.info("Subnet created")
295         else :
296                 log.exception("Failed to create subnet: " + subnet)
297                 raise Exception("Failed to create subnet: " + subnet)
298
299 ServerToBeCreated=[]
300 ServerName=[]
301 config = ConfigParser.RawConfigParser()
302 vmconfig = ConfigParser.RawConfigParser()
303 vmconfig.read(vms+'.vms')
304 total_number_of_VMs = vmconfig.get('DEFAULT', 'total_number_of_vms')
305 for vm in range(1, int(total_number_of_VMs)+1):
306         flavor_info = vmconfig.get('VM%d'%vm, 'flavor_info')
307         flavor_meta_data = vmconfig.get('VM%d'%vm, 'flavor_meta_data')
308         boot_info = vmconfig.get('VM%d'%vm, 'boot_info')
309         SRIOV_port = vmconfig.get('VM%d'%vm, 'SRIOV_port')
310         ServerName.append('%s-VM%d'%(stack,vm))
311         flavor_name = '%s-VM%d-flavor'%(stack,vm)
312         log.debug("Checking server: "+ServerName[-1])
313         cmd = 'openstack server show '+ServerName[-1]
314         log.debug (cmd)
315         cmd = cmd + ' |grep "\sname\s" | tr -s " " | cut -d" " -f 4'
316         ServerExist = subprocess.check_output(cmd , shell=True).strip()
317         if ServerExist == ServerName[-1]:
318                 log.info("Server ("+ServerName[-1]+") already active")
319                 ServerToBeCreated.append("no")
320         else:
321                 ServerToBeCreated.append("yes")
322                 # Checking if the flavor already exists, if not create it
323                 log.debug("Checking flavor: "+flavor_name)
324                 cmd = 'openstack flavor show '+flavor_name
325                 log.debug (cmd)
326                 cmd = cmd + ' |grep "\sname\s" | tr -s " " | cut -d" " -f 4'
327                 FlavorExist = subprocess.check_output(cmd , shell=True).strip()
328                 if FlavorExist == flavor_name:
329                         log.info("Flavor ("+flavor_name+") already installed")
330                 else:
331                         log.info('Creating flavor ...')
332                         cmd = 'openstack flavor create %s %s'%(flavor_name,flavor_info)
333                         log.debug(cmd)
334                         cmd = cmd + ' |grep "\sname\s" | tr -s " " | cut -d" " -f 4'
335                         FlavorExist = subprocess.check_output(cmd , shell=True).strip()
336                         if FlavorExist == flavor_name:
337                                 cmd = 'openstack flavor set %s %s'%(flavor_name, flavor_meta_data)
338                                 log.debug(cmd)
339                                 subprocess.check_call(cmd , shell=True)
340                                 log.info("Flavor created")
341                         else :
342                                 log.exception("Failed to create flavor: " + flavor_name)
343                                 raise Exception("Failed to create flavor: " + flavor_name)
344                 if SRIOV_port == 'NO':
345                         nic_info = '--nic net-id=%s --nic net-id=%s'%(internal_network,dataplane_network)
346                 else:
347                         nic_info = '--nic net-id=%s'%(internal_network)
348                         for port in SRIOV_port.split(','):
349                                 nic_info = nic_info + ' --nic port-id=%s'%(port)
350                 if vm==int(total_number_of_VMs):
351                         # For the last server, we want to wait for the server creation to complete, so the next operations will succeeed (e.g. IP allocation)
352                         # Note that this waiting is not bullet proof. Imagine, we loop through all the VMs, and the last VM was already running, while the previous
353                         # VMs still needed to be created. Or the previous server creations take much longer than the last one.
354                         # In that case, we might be to fast when we query for the IP & MAC addresses.
355                         wait = ' --wait '
356                 else:
357                         wait = ' '
358                 log.info("Creating server...")
359                 cmd = 'openstack server create --flavor %s --key-name %s --image %s %s %s%s%s'%(flavor_name,key,image,nic_info,boot_info,wait,ServerName[-1])
360                 log.debug(cmd)
361                 cmd = cmd + ' |grep "\sname\s" | tr -s " " | cut -d" " -f 4'
362                 ServerExist = subprocess.check_output(cmd , shell=True).strip()
363 if floating_network <> 'NO':
364         for vm in range(0, int(total_number_of_VMs)):
365                 if ServerToBeCreated[vm] =="yes":
366                         log.info('Creating floating IP ...')
367                         cmd = 'openstack floating ip create  ' + floating_network
368                         log.debug(cmd)
369                         cmd = cmd + ' |grep "floating_ip_address " | tr -s " " | cut -d"|" -f 3'
370                         vmAdminIP = subprocess.check_output(cmd , shell=True).strip()
371                         log.info('Associating floating IP ...')
372                         cmd = 'openstack server add floating ip %s %s'%(ServerName[vm],vmAdminIP)
373                         log.debug(cmd)
374                         output = subprocess.check_output(cmd , shell=True).strip()
375                 
376 for vm in range(1, int(total_number_of_VMs)+1):
377         cmd = 'openstack server show %s'%(ServerName[vm-1])
378         log.debug(cmd)
379         output = subprocess.check_output(cmd , shell=True).strip()
380         searchString = '.*%s.*?([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)' %(dataplane_network)
381         matchObj = re.search(searchString, output, re.DOTALL)
382         vmDPIP = matchObj.group(1)
383         searchString = '.*%s=([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+),*\s*([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)*' %(internal_network)
384         matchObj = re.search(searchString, output, re.DOTALL)
385         vmAdminIP = matchObj.group(2)
386         if vmAdminIP == None:
387                 vmAdminIP = matchObj.group(1)
388         cmd = 'openstack port list |egrep  "\\b%s\\b" | tr -s " " | cut -d"|" -f 4'%(vmDPIP)
389         log.debug(cmd)
390         vmDPmac = subprocess.check_output(cmd , shell=True).strip()
391         config.add_section('M%d'%vm)
392         config.set('M%d'%vm, 'name', ServerName[vm-1])
393         config.set('M%d'%vm, 'admin_ip', vmAdminIP)
394         config.set('M%d'%vm, 'dp_ip', vmDPIP)
395         config.set('M%d'%vm, 'dp_mac', vmDPmac)
396         log.info('%s: (admin IP: %s), (dataplane IP: %s), (dataplane MAC: %s)' % (ServerName[vm-1],vmAdminIP,vmDPIP,vmDPmac))
397
398 config.add_section('OpenStack')
399 config.set('OpenStack', 'stack', stack)
400 config.set('OpenStack', 'VMs', vms)
401 config.set('OpenStack', 'key', key)
402 config.set('OpenStack', 'image', image)
403 config.set('OpenStack', 'image_file', image_file)
404 config.set('OpenStack', 'dataplane_network', dataplane_network)
405 config.set('OpenStack', 'subnet', subnet)
406 config.set('OpenStack', 'subnet_cidr', subnet_cidr)
407 config.set('OpenStack', 'internal_network', internal_network)
408 config.set('OpenStack', 'floating_network', floating_network)
409 config.add_section('rapid')
410 config.set('rapid', 'loglevel', loglevel)
411 config.set('rapid', 'version', version)
412 config.set('rapid', 'total_number_of_machines', total_number_of_VMs)
413 config.set('DEFAULT', 'admin_ip', 'none')
414 # Writing the environment file
415 with open(stack+'.env', 'wb') as envfile:
416     config.write(envfile)