blob: 1f792014074ca9a1192d414606c1fb23abcb0275 [file] [log] [blame]
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -08001#!/usr/bin/env python
John DeNisco68b0ee32017-09-27 16:35:23 -04002
3# Copyright (c) 2016 Cisco and/or its affiliates.
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -08004# Copyright (c) 2018 Vinci Consulting Corp. All rights reserved.
John DeNisco68b0ee32017-09-27 16:35:23 -04005# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at:
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""VPP Configuration Main Entry"""
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -080018from __future__ import absolute_import, division, print_function
John DeNisco68b0ee32017-09-27 16:35:23 -040019
20import re
21import os
22import sys
23import logging
John DeNiscoddecfb32017-11-15 08:50:57 -050024import argparse
John DeNisco68b0ee32017-09-27 16:35:23 -040025
26from vpplib.AutoConfig import AutoConfig
27from vpplib.VPPUtil import VPPUtil
28
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -080029# Python2/3 compatible
30try:
31 input = raw_input # noqa
32except NameError:
33 pass
34
John DeNisco68b0ee32017-09-27 16:35:23 -040035VPP_DRYRUNDIR = '/vpp/vpp-config/dryrun'
36VPP_AUTO_CONFIGURATION_FILE = '/vpp/vpp-config/configs/auto-config.yaml'
37VPP_HUGE_PAGE_FILE = '/vpp/vpp-config/dryrun/sysctl.d/80-vpp.conf'
38VPP_STARTUP_FILE = '/vpp/vpp-config/dryrun/vpp/startup.conf'
39VPP_GRUB_FILE = '/vpp/vpp-config/dryrun/default/grub'
40VPP_REAL_HUGE_PAGE_FILE = '/etc/sysctl.d/80-vpp.conf'
41VPP_REAL_STARTUP_FILE = '/etc/vpp/startup.conf'
42VPP_REAL_GRUB_FILE = '/etc/default/grub'
43
44rootdir = ''
45
46
47def autoconfig_yn(question, default):
48 """
49 Ask the user a yes or no question.
50
51 :param question: The text of the question
52 :param default: Value to be returned if '\n' is entered
53 :type question: string
54 :type default: string
55 :returns: The Answer
56 :rtype: string
57 """
58 input_valid = False
59 default = default.lower()
60 answer = ''
61 while not input_valid:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -080062 answer = input(question)
John DeNisco68b0ee32017-09-27 16:35:23 -040063 if len(answer) == 0:
64 answer = default
65 if re.findall(r'[YyNn]', answer):
66 input_valid = True
67 answer = answer[0].lower()
68 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -080069 print ("Please answer Y, N or Return.")
John DeNisco68b0ee32017-09-27 16:35:23 -040070
71 return answer
72
73
74def autoconfig_cp(node, src, dst):
75 """
76 Copies a file, saving the original if needed.
77
78 :param node: Node dictionary with cpuinfo.
79 :param src: Source File
80 :param dst: Destination file
81 :type node: dict
82 :type src: string
83 :type dst: string
84 :raises RuntimeError: If command fails
85 """
86
87 # If the destination file exist, create a copy if one does not already
88 # exist
89 ofile = dst + '.orig'
90 (ret, stdout, stderr) = VPPUtil.exec_command('ls {}'.format(dst))
91 if ret == 0:
92 cmd = 'cp {} {}'.format(dst, ofile)
93 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
94 if ret != 0:
95 raise RuntimeError('{} failed on node {} {} {}'.
96 format(cmd,
97 node['host'],
98 stdout,
99 stderr))
100
101 # Copy the source file
102 cmd = 'cp {} {}'.format(src, os.path.dirname(dst))
103 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
104 if ret != 0:
105 raise RuntimeError('{} failed on node {} {}'.
106 format(cmd, node['host'], stderr))
107
108
109def autoconfig_diff(node, src, dst):
110 """
111 Returns the diffs of 2 files.
112
113 :param node: Node dictionary with cpuinfo.
114 :param src: Source File
115 :param dst: Destination file
116 :type node: dict
117 :type src: string
118 :type dst: string
119 :returns: The Answer
120 :rtype: string
121 :raises RuntimeError: If command fails
122 """
123
124 # Diff the files and return the output
125 cmd = "diff {} {}".format(src, dst)
126 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
127 if stderr != '':
128 raise RuntimeError('{} failed on node {} {} {}'.
129 format(cmd,
130 node['host'],
131 ret,
132 stderr))
133
134 return stdout
135
136
137def autoconfig_show_system():
138 """
139 Shows the system information.
140
141 """
142
143 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
144
145 acfg.discover()
146
147 acfg.sys_info()
148
149
John DeNiscoddecfb32017-11-15 08:50:57 -0500150def autoconfig_hugepage_apply(node, ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400151 """
152 Apply the huge page configuration.
153 :param node: The node structure
154 :type node: dict
John DeNiscoddecfb32017-11-15 08:50:57 -0500155 :param ask_questions: When True ask the user questions
156 :type ask_questions: bool
John DeNisco68b0ee32017-09-27 16:35:23 -0400157 :returns: -1 if the caller should return, 0 if not
158 :rtype: int
159
160 """
161
162 diffs = autoconfig_diff(node, VPP_REAL_HUGE_PAGE_FILE, rootdir + VPP_HUGE_PAGE_FILE)
163 if diffs != '':
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800164 print ("These are the changes we will apply to")
165 print ("the huge page file ({}).\n".format(VPP_REAL_HUGE_PAGE_FILE))
166 print (diffs)
John DeNiscoddecfb32017-11-15 08:50:57 -0500167 if ask_questions:
168 answer = autoconfig_yn("\nAre you sure you want to apply these changes [Y/n]? ", 'y')
169 if answer == 'n':
170 return -1
John DeNisco68b0ee32017-09-27 16:35:23 -0400171
172 # Copy and sysctl
173 autoconfig_cp(node, rootdir + VPP_HUGE_PAGE_FILE, VPP_REAL_HUGE_PAGE_FILE)
174 cmd = "sysctl -p {}".format(VPP_REAL_HUGE_PAGE_FILE)
175 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
176 if ret != 0:
177 raise RuntimeError('{} failed on node {} {} {}'.
178 format(cmd, node['host'], stdout, stderr))
179 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800180 print ('\nThere are no changes to the huge page configuration.')
John DeNisco68b0ee32017-09-27 16:35:23 -0400181
182 return 0
183
184
John DeNiscoddecfb32017-11-15 08:50:57 -0500185def autoconfig_vpp_apply(node, ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400186 """
187 Apply the vpp configuration.
188
189 :param node: The node structure
190 :type node: dict
John DeNiscoddecfb32017-11-15 08:50:57 -0500191 :param ask_questions: When True ask the user questions
192 :type ask_questions: bool
John DeNisco68b0ee32017-09-27 16:35:23 -0400193 :returns: -1 if the caller should return, 0 if not
194 :rtype: int
195
196 """
197
John DeNisco68b0ee32017-09-27 16:35:23 -0400198 diffs = autoconfig_diff(node, VPP_REAL_STARTUP_FILE, rootdir + VPP_STARTUP_FILE)
199 if diffs != '':
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800200 print ("These are the changes we will apply to")
201 print ("the VPP startup file ({}).\n".format(VPP_REAL_STARTUP_FILE))
202 print (diffs)
John DeNiscoddecfb32017-11-15 08:50:57 -0500203 if ask_questions:
204 answer = autoconfig_yn("\nAre you sure you want to apply these changes [Y/n]? ", 'y')
205 if answer == 'n':
206 return -1
John DeNisco68b0ee32017-09-27 16:35:23 -0400207
208 # Copy the VPP startup
209 autoconfig_cp(node, rootdir + VPP_STARTUP_FILE, VPP_REAL_STARTUP_FILE)
210 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800211 print ('\nThere are no changes to VPP startup.')
John DeNisco68b0ee32017-09-27 16:35:23 -0400212
213 return 0
214
215
John DeNiscoddecfb32017-11-15 08:50:57 -0500216def autoconfig_grub_apply(node, ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400217 """
218 Apply the grub configuration.
219
220 :param node: The node structure
221 :type node: dict
John DeNiscoddecfb32017-11-15 08:50:57 -0500222 :param ask_questions: When True ask the user questions
223 :type ask_questions: bool
John DeNisco68b0ee32017-09-27 16:35:23 -0400224 :returns: -1 if the caller should return, 0 if not
225 :rtype: int
226
227 """
John DeNiscoddecfb32017-11-15 08:50:57 -0500228
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800229 print ("\nThe configured grub cmdline looks like this:")
John DeNisco68b0ee32017-09-27 16:35:23 -0400230 configured_cmdline = node['grub']['default_cmdline']
231 current_cmdline = node['grub']['current_cmdline']
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800232 print (configured_cmdline)
233 print ("\nThe current boot cmdline looks like this:")
234 print (current_cmdline)
John DeNiscoddecfb32017-11-15 08:50:57 -0500235 if ask_questions:
236 question = "\nDo you want to keep the current boot cmdline [Y/n]? "
237 answer = autoconfig_yn(question, 'y')
238 if answer == 'y':
239 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400240
John DeNiscoddecfb32017-11-15 08:50:57 -0500241 node['grub']['keep_cmdline'] = False
242
243 # Diff the file
244 diffs = autoconfig_diff(node, VPP_REAL_GRUB_FILE, rootdir + VPP_GRUB_FILE)
245 if diffs != '':
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800246 print ("These are the changes we will apply to")
247 print ("the GRUB file ({}).\n".format(VPP_REAL_GRUB_FILE))
248 print (diffs)
John DeNiscoddecfb32017-11-15 08:50:57 -0500249 if ask_questions:
250 answer = autoconfig_yn("\nAre you sure you want to apply these changes [y/N]? ", 'n')
John DeNisco68b0ee32017-09-27 16:35:23 -0400251 if answer == 'n':
252 return -1
253
John DeNiscoddecfb32017-11-15 08:50:57 -0500254 # Copy and update grub
255 autoconfig_cp(node, rootdir + VPP_GRUB_FILE, VPP_REAL_GRUB_FILE)
256 distro = VPPUtil.get_linux_distro()
257 if distro[0] == 'Ubuntu':
258 cmd = "update-grub"
John DeNisco68b0ee32017-09-27 16:35:23 -0400259 else:
John DeNiscoddecfb32017-11-15 08:50:57 -0500260 cmd = "grub2-mkconfig -o /boot/grub2/grub.cfg"
261
262 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
263 if ret != 0:
264 raise RuntimeError('{} failed on node {} {} {}'.
265 format(cmd, node['host'], stdout, stderr))
266
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800267 print ("There have been changes to the GRUB config a", end=' ')
268 print ("reboot will be required.")
John DeNiscoddecfb32017-11-15 08:50:57 -0500269 return -1
270 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800271 print ('\nThere are no changes to the GRUB config.')
John DeNisco68b0ee32017-09-27 16:35:23 -0400272
273 return 0
274
275
John DeNiscoddecfb32017-11-15 08:50:57 -0500276def autoconfig_apply(ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400277 """
278 Apply the configuration.
279
280 Show the diff of the dryrun file and the actual configuration file
281 Copy the files from the dryrun directory to the actual file.
282 Peform the system function
283
John DeNiscoddecfb32017-11-15 08:50:57 -0500284 :param ask_questions: When true ask the user questions
285 :type ask_questions: bool
286
John DeNisco68b0ee32017-09-27 16:35:23 -0400287 """
288
289 vutil = VPPUtil()
290 pkgs = vutil.get_installed_vpp_pkgs()
291 if len(pkgs) == 0:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800292 print ("\nVPP is not installed, Install VPP with option 4.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400293 return
294
295 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
296
John DeNiscoddecfb32017-11-15 08:50:57 -0500297 if ask_questions:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800298 print ("\nWe are now going to configure your system(s).\n")
John DeNiscoddecfb32017-11-15 08:50:57 -0500299 answer = autoconfig_yn("Are you sure you want to do this [Y/n]? ", 'y')
300 if answer == 'n':
301 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400302
303 nodes = acfg.get_nodes()
304 for i in nodes.items():
305 node = i[1]
306
307 # Check the system resources
308 if not acfg.min_system_resources(node):
309 return
310
John DeNiscoddecfb32017-11-15 08:50:57 -0500311 # Stop VPP
312 VPPUtil.stop(node)
313
John DeNisco68b0ee32017-09-27 16:35:23 -0400314 # Huge Pages
John DeNiscoddecfb32017-11-15 08:50:57 -0500315 ret = autoconfig_hugepage_apply(node, ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400316 if ret != 0:
317 return
318
319 # VPP
John DeNiscoddecfb32017-11-15 08:50:57 -0500320 ret = autoconfig_vpp_apply(node, ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400321 if ret != 0:
322 return
323
324 # Grub
John DeNiscoddecfb32017-11-15 08:50:57 -0500325 ret = autoconfig_grub_apply(node, ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400326 if ret != 0:
John DeNiscoddecfb32017-11-15 08:50:57 -0500327 # We can still start VPP, even if we haven't configured grub
328 VPPUtil.start(node)
John DeNisco68b0ee32017-09-27 16:35:23 -0400329 return
330
331 # Everything is configured start vpp
John DeNiscoddecfb32017-11-15 08:50:57 -0500332 VPPUtil.start(node)
John DeNisco68b0ee32017-09-27 16:35:23 -0400333
John DeNiscoa7da67f2018-01-26 14:55:33 -0500334
John DeNiscoddecfb32017-11-15 08:50:57 -0500335def autoconfig_dryrun(ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400336 """
337 Execute the dryrun function.
338
John DeNiscoddecfb32017-11-15 08:50:57 -0500339 :param ask_questions: When true ask the user for paraameters
340 :type ask_questions: bool
341
John DeNisco68b0ee32017-09-27 16:35:23 -0400342 """
343
344 vutil = VPPUtil()
345 pkgs = vutil.get_installed_vpp_pkgs()
346 if len(pkgs) == 0:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800347 print ("\nVPP is not installed, please install VPP.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400348 return
349
John DeNiscoddecfb32017-11-15 08:50:57 -0500350 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE, clean=True)
John DeNisco68b0ee32017-09-27 16:35:23 -0400351
352 # Stop VPP on each node
353 nodes = acfg.get_nodes()
354 for i in nodes.items():
355 node = i[1]
356 VPPUtil.stop(node)
357
358 # Discover
359 acfg.discover()
360
361 # Check the system resources
362 nodes = acfg.get_nodes()
363 for i in nodes.items():
364 node = i[1]
365 if not acfg.min_system_resources(node):
366 return
367
368 # Modify the devices
John DeNiscoddecfb32017-11-15 08:50:57 -0500369 if ask_questions:
370 acfg.modify_devices()
371 else:
372 acfg.update_interfaces_config()
John DeNisco68b0ee32017-09-27 16:35:23 -0400373
374 # Modify CPU
John DeNiscoddecfb32017-11-15 08:50:57 -0500375 acfg.modify_cpu(ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400376
377 # Calculate the cpu parameters
378 acfg.calculate_cpu_parameters()
379
380 # Acquire TCP stack parameters
John DeNiscoddecfb32017-11-15 08:50:57 -0500381 if ask_questions:
382 acfg.acquire_tcp_params()
John DeNisco68b0ee32017-09-27 16:35:23 -0400383
384 # Apply the startup
385 acfg.apply_vpp_startup()
386
387 # Apply the grub configuration
388 acfg.apply_grub_cmdline()
389
390 # Huge Pages
John DeNiscoddecfb32017-11-15 08:50:57 -0500391 if ask_questions:
392 acfg.modify_huge_pages()
John DeNisco68b0ee32017-09-27 16:35:23 -0400393 acfg.apply_huge_pages()
394
395
396def autoconfig_install():
397 """
398 Install or Uninstall VPP.
399
400 """
401
402 # Since these commands will take a while, we
403 # want to see the progress
404 logger = logging.getLogger()
405
406 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
407 vutil = VPPUtil()
408
409 nodes = acfg.get_nodes()
410 for i in nodes.items():
411 node = i[1]
412
413 pkgs = vutil.get_installed_vpp_pkgs()
414
415 if len(pkgs) > 0:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800416 print ("\nThese packages are installed on node {}"
417 .format(node['host']))
418 print ("{:25} {}".format("Name", "Version"))
John DeNisco68b0ee32017-09-27 16:35:23 -0400419 for pkg in pkgs:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800420 try:
421 print ("{:25} {}".format(
422 pkg['name'], pkg['version']))
423 except KeyError:
424 print ("{}".format(pkg['name']))
John DeNisco68b0ee32017-09-27 16:35:23 -0400425
426 question = "\nDo you want to uninstall these "
427 question += "packages [y/N]? "
428 answer = autoconfig_yn(question, 'n')
429 if answer == 'y':
430 logger.setLevel(logging.INFO)
431 vutil.uninstall_vpp(node)
432 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800433 print ("\nThere are no VPP packages on node {}."
434 .format(node['host']))
John DeNisco68b0ee32017-09-27 16:35:23 -0400435 question = "Do you want to install VPP [Y/n]? "
436 answer = autoconfig_yn(question, 'y')
437 if answer == 'y':
jdeniscob0b9dad2018-12-18 15:29:45 -0500438 question = "Do you want to install the release version [Y/n]? "
439 answer = autoconfig_yn(question, 'y')
440 if answer == 'y':
441 branch = 'release'
442 else:
443 branch = 'master'
John DeNisco68b0ee32017-09-27 16:35:23 -0400444 logger.setLevel(logging.INFO)
jdeniscob0b9dad2018-12-18 15:29:45 -0500445 vutil.install_vpp(node, branch)
John DeNisco68b0ee32017-09-27 16:35:23 -0400446
447 # Set the logging level back
448 logger.setLevel(logging.ERROR)
449
450
451def autoconfig_patch_qemu():
452 """
453 Patch the correct qemu version that is needed for openstack
454
455 """
456
457 # Since these commands will take a while, we
458 # want to see the progress
459 logger = logging.getLogger()
460
461 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
462
463 nodes = acfg.get_nodes()
464 for i in nodes.items():
465 node = i[1]
466
467 logger.setLevel(logging.INFO)
468 acfg.patch_qemu(node)
469
470
John DeNiscoa3db0782017-10-17 11:07:22 -0400471def autoconfig_ipv4_setup():
472 """
473 Setup IPv4 interfaces
474
475 """
476
477 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
478 acfg.ipv4_interface_setup()
479
480
John DeNisco9fa5cf42018-02-06 15:23:05 -0500481def autoconfig_create_iperf_vm():
John DeNiscoc6b2a202017-11-01 12:37:47 -0400482 """
483 Setup IPv4 interfaces
484
485 """
486
487 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
John DeNisco9fa5cf42018-02-06 15:23:05 -0500488 acfg.destroy_iperf_vm('iperf-server')
489 acfg.create_and_bridge_iperf_virtual_interface()
490 acfg.create_iperf_vm('iperf-server')
John DeNiscoc6b2a202017-11-01 12:37:47 -0400491
492
John DeNisco68b0ee32017-09-27 16:35:23 -0400493def autoconfig_not_implemented():
494 """
495 This feature is not implemented
496
497 """
498
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800499 print ("\nThis Feature is not implemented yet....")
John DeNisco68b0ee32017-09-27 16:35:23 -0400500
501
John DeNiscoa3db0782017-10-17 11:07:22 -0400502def autoconfig_basic_test_menu():
503 """
504 The auto configuration basic test menu
505
506 """
507
508 basic_menu_text = '\nWhat would you like to do?\n\n\
5091) List/Create Simple IPv4 Setup\n\
John DeNisco9fa5cf42018-02-06 15:23:05 -05005102) Create an iperf VM and Connect to VPP an interface\n\
John DeNiscoa3db0782017-10-17 11:07:22 -04005119 or q) Back to main menu.'
John DeNiscoddecfb32017-11-15 08:50:57 -0500512
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800513 print ("{}".format(basic_menu_text))
John DeNiscoa3db0782017-10-17 11:07:22 -0400514
515 input_valid = False
516 answer = ''
517 while not input_valid:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800518 answer = input("\nCommand: ")
John DeNiscoa3db0782017-10-17 11:07:22 -0400519 if len(answer) > 1:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800520 print ("Please enter only 1 character.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400521 continue
522 if re.findall(r'[Qq1-29]', answer):
523 input_valid = True
524 answer = answer[0].lower()
525 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800526 print ("Please enter a character between 1 and 2 or 9.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400527
528 if answer == '9':
529 answer = 'q'
530
531 return answer
532
533
534def autoconfig_basic_test():
535 """
536 The auto configuration basic test menu
537
538 """
539 vutil = VPPUtil()
540 pkgs = vutil.get_installed_vpp_pkgs()
541 if len(pkgs) == 0:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800542 print ("\nVPP is not installed, install VPP with option 4.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400543 return
544
545 answer = ''
546 while answer != 'q':
547 answer = autoconfig_basic_test_menu()
548 if answer == '1':
549 autoconfig_ipv4_setup()
John DeNisco9fa5cf42018-02-06 15:23:05 -0500550 elif answer == '2':
551 autoconfig_create_iperf_vm()
John DeNiscoa3db0782017-10-17 11:07:22 -0400552 elif answer == '9' or answer == 'q':
553 return
554 else:
555 autoconfig_not_implemented()
556
557
John DeNisco68b0ee32017-09-27 16:35:23 -0400558def autoconfig_main_menu():
559 """
560 The auto configuration main menu
561
562 """
563
564 main_menu_text = '\nWhat would you like to do?\n\n\
5651) Show basic system information\n\
jdenisco7c37a672018-11-20 11:25:17 -05005662) Dry Run (Saves the configuration files in {}/vpp/vpp-config/dryrun.\n\
John DeNisco68b0ee32017-09-27 16:35:23 -04005673) Full configuration (WARNING: This will change the system configuration)\n\
5684) List/Install/Uninstall VPP.\n\
jdeniscob9875092018-11-06 16:10:04 -0500569q) Quit'.format(rootdir, rootdir)
John DeNisco68b0ee32017-09-27 16:35:23 -0400570
571 # 5) Dry Run from {}/vpp/vpp-config/auto-config.yaml (will not ask questions).\n\
572 # 6) Install QEMU patch (Needed when running openstack).\n\
573
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800574 print ("{}".format(main_menu_text))
John DeNisco68b0ee32017-09-27 16:35:23 -0400575
576 input_valid = False
577 answer = ''
578 while not input_valid:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800579 answer = input("\nCommand: ")
John DeNisco68b0ee32017-09-27 16:35:23 -0400580 if len(answer) > 1:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800581 print ("Please enter only 1 character.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400582 continue
jdeniscob9875092018-11-06 16:10:04 -0500583 if re.findall(r'[Qq1-4]', answer):
John DeNisco68b0ee32017-09-27 16:35:23 -0400584 input_valid = True
585 answer = answer[0].lower()
586 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800587 print ("Please enter a character between 1 and 4 or q.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400588
John DeNisco68b0ee32017-09-27 16:35:23 -0400589 return answer
590
591
592def autoconfig_main():
593 """
594 The auto configuration main entry point
595
596 """
597
John DeNiscoddecfb32017-11-15 08:50:57 -0500598 # Setup
599 autoconfig_setup()
600
John DeNisco68b0ee32017-09-27 16:35:23 -0400601 answer = ''
602 while answer != 'q':
603 answer = autoconfig_main_menu()
604 if answer == '1':
605 autoconfig_show_system()
606 elif answer == '2':
607 autoconfig_dryrun()
608 elif answer == '3':
609 autoconfig_apply()
610 elif answer == '4':
611 autoconfig_install()
jdeniscob9875092018-11-06 16:10:04 -0500612 elif answer == 'q':
John DeNisco68b0ee32017-09-27 16:35:23 -0400613 return
614 else:
615 autoconfig_not_implemented()
616
617
John DeNiscoddecfb32017-11-15 08:50:57 -0500618def autoconfig_setup(ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400619 """
620 The auto configuration setup function.
621
622 We will copy the configuration files to the dryrun directory.
623
624 """
625
626 global rootdir
627
John DeNisco68b0ee32017-09-27 16:35:23 -0400628 distro = VPPUtil.get_linux_distro()
629 if distro[0] == 'Ubuntu':
630 rootdir = '/usr/local'
631 else:
632 rootdir = '/usr'
633
634 # If there is a system configuration file use that, if not use the initial auto-config file
635 filename = rootdir + VPP_AUTO_CONFIGURATION_FILE
636 if os.path.isfile(filename) is True:
637 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
638 else:
639 raise RuntimeError('The Auto configuration file does not exist {}'.
640 format(filename))
641
John DeNiscoddecfb32017-11-15 08:50:57 -0500642 if ask_questions:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800643 print ("\nWelcome to the VPP system configuration utility")
John DeNisco68b0ee32017-09-27 16:35:23 -0400644
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800645 print ("\nThese are the files we will modify:")
646 print (" /etc/vpp/startup.conf")
647 print (" /etc/sysctl.d/80-vpp.conf")
648 print (" /etc/default/grub")
John DeNisco68b0ee32017-09-27 16:35:23 -0400649
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800650 print (
651 "\nBefore we change them, we'll create working copies in "
652 "{}".format(rootdir + VPP_DRYRUNDIR))
653 print (
654 "Please inspect them carefully before applying the actual "
655 "configuration (option 3)!")
John DeNisco68b0ee32017-09-27 16:35:23 -0400656
657 nodes = acfg.get_nodes()
658 for i in nodes.items():
659 node = i[1]
660
661 if (os.path.isfile(rootdir + VPP_STARTUP_FILE) is not True) and \
662 (os.path.isfile(VPP_REAL_STARTUP_FILE) is True):
663 autoconfig_cp(node, VPP_REAL_STARTUP_FILE, '{}'.format(rootdir + VPP_STARTUP_FILE))
664 if (os.path.isfile(rootdir + VPP_HUGE_PAGE_FILE) is not True) and \
665 (os.path.isfile(VPP_REAL_HUGE_PAGE_FILE) is True):
666 autoconfig_cp(node, VPP_REAL_HUGE_PAGE_FILE, '{}'.format(rootdir + VPP_HUGE_PAGE_FILE))
667 if (os.path.isfile(rootdir + VPP_GRUB_FILE) is not True) and \
668 (os.path.isfile(VPP_REAL_GRUB_FILE) is True):
669 autoconfig_cp(node, VPP_REAL_GRUB_FILE, '{}'.format(rootdir + VPP_GRUB_FILE))
670
John DeNiscoa7da67f2018-01-26 14:55:33 -0500671 # Be sure the uio_pci_generic driver is installed
672 cmd = 'modprobe uio_pci_generic'
673 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
674 if ret != 0:
John DeNisco4dc83972018-03-30 10:50:19 -0400675 logging.warning('{} failed on node {} {}'. format(cmd, node['host'], stderr))
John DeNiscoa7da67f2018-01-26 14:55:33 -0500676
John DeNisco68b0ee32017-09-27 16:35:23 -0400677
John DeNisco9fa5cf42018-02-06 15:23:05 -0500678# noinspection PyUnresolvedReferences
John DeNiscoddecfb32017-11-15 08:50:57 -0500679def execute_with_args(args):
680 """
681 Execute the configuration utility with agruments.
682
683 :param args: The Command line arguments
684 :type args: tuple
685 """
686
687 # Setup
688 autoconfig_setup(ask_questions=False)
689
690 # Execute the command
691 if args.show:
692 autoconfig_show_system()
693 elif args.dry_run:
694 autoconfig_dryrun(ask_questions=False)
695 elif args.apply:
696 autoconfig_apply(ask_questions=False)
697 else:
698 autoconfig_not_implemented()
699
700
701def config_main():
702 """
703 The vpp configuration utility main entry point.
704
705 """
John DeNisco68b0ee32017-09-27 16:35:23 -0400706
707 # Check for root
708 if not os.geteuid() == 0:
709 sys.exit('\nPlease run the VPP Configuration Utility as root.')
710
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800711 if len(sys.argv) > 1 and ((sys.argv[1] == '-d') or (
712 sys.argv[1] == '--debug')):
John DeNiscoa7da67f2018-01-26 14:55:33 -0500713 logging.basicConfig(level=logging.DEBUG)
714 else:
715 logging.basicConfig(level=logging.ERROR)
716
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800717 # If no arguments were entered, ask the user questions to
718 # get the main parameters
John DeNiscoddecfb32017-11-15 08:50:57 -0500719 if len(sys.argv) == 1:
John DeNiscoa7da67f2018-01-26 14:55:33 -0500720 autoconfig_main()
721 return
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800722 elif len(sys.argv) == 2 and ((sys.argv[1] == '-d') or (
723 sys.argv[1] == '--debug')):
John DeNiscoddecfb32017-11-15 08:50:57 -0500724 autoconfig_main()
725 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400726
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800727 # There were arguments specified, so execute the utility using
728 # command line arguments
729 description = 'The VPP configuration utility allows the user to '
730 'configure VPP in a simple and safe manner. The utility takes input '
731 'from the user or the specified .yaml file. The user should then '
732 'examine these files to be sure they are correct and then actually '
733 'apply the configuration. When run without arguments the utility run '
734 'in an interactive mode'
John DeNiscoddecfb32017-11-15 08:50:57 -0500735
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800736 main_parser = argparse.ArgumentParser(
737 prog='arg-test',
738 description=description,
739 epilog='See "%(prog)s help COMMAND" for help on a specific command.')
740 main_parser.add_argument('--apply', '-a', action='store_true',
741 help='Apply the cofiguration.')
742 main_parser.add_argument('--dry-run', '-dr', action='store_true',
743 help='Create the dryrun configuration files.')
744 main_parser.add_argument('--show', '-s', action='store_true',
745 help='Shows basic system information')
746 main_parser.add_argument('--debug', '-d', action='count',
747 help='Print debug output (multiple levels)')
John DeNiscoddecfb32017-11-15 08:50:57 -0500748
749 args = main_parser.parse_args()
750
751 return execute_with_args(args)
752
753
754if __name__ == '__main__':
John DeNiscoddecfb32017-11-15 08:50:57 -0500755 config_main()