blob: 0ff40f161b579730d4fd641d2734b5176294223b [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
John DeNiscoddecfb32017-11-15 08:50:57 -0500344 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE, clean=True)
John DeNisco68b0ee32017-09-27 16:35:23 -0400345
346 # Stop VPP on each node
347 nodes = acfg.get_nodes()
348 for i in nodes.items():
349 node = i[1]
350 VPPUtil.stop(node)
351
352 # Discover
353 acfg.discover()
354
355 # Check the system resources
356 nodes = acfg.get_nodes()
357 for i in nodes.items():
358 node = i[1]
359 if not acfg.min_system_resources(node):
360 return
361
362 # Modify the devices
John DeNiscoddecfb32017-11-15 08:50:57 -0500363 if ask_questions:
364 acfg.modify_devices()
365 else:
366 acfg.update_interfaces_config()
John DeNisco68b0ee32017-09-27 16:35:23 -0400367
jdeniscoaf86c632019-04-05 12:25:50 -0400368 # If there are no interfaces, just return
369 for i in nodes.items():
370 node = i[1]
371 if not acfg.has_interfaces(node):
372 print("\nThere are no VPP interfaces configured, please configure at least 1.")
373 return
374
John DeNisco68b0ee32017-09-27 16:35:23 -0400375 # Modify CPU
John DeNiscoddecfb32017-11-15 08:50:57 -0500376 acfg.modify_cpu(ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400377
378 # Calculate the cpu parameters
379 acfg.calculate_cpu_parameters()
380
381 # Acquire TCP stack parameters
John DeNiscoddecfb32017-11-15 08:50:57 -0500382 if ask_questions:
383 acfg.acquire_tcp_params()
John DeNisco68b0ee32017-09-27 16:35:23 -0400384
385 # Apply the startup
386 acfg.apply_vpp_startup()
387
388 # Apply the grub configuration
389 acfg.apply_grub_cmdline()
390
391 # Huge Pages
John DeNiscoddecfb32017-11-15 08:50:57 -0500392 if ask_questions:
393 acfg.modify_huge_pages()
John DeNisco68b0ee32017-09-27 16:35:23 -0400394 acfg.apply_huge_pages()
395
396
397def autoconfig_install():
398 """
399 Install or Uninstall VPP.
400
401 """
402
403 # Since these commands will take a while, we
404 # want to see the progress
405 logger = logging.getLogger()
406
407 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
408 vutil = VPPUtil()
409
410 nodes = acfg.get_nodes()
411 for i in nodes.items():
412 node = i[1]
413
414 pkgs = vutil.get_installed_vpp_pkgs()
415
416 if len(pkgs) > 0:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800417 print ("\nThese packages are installed on node {}"
418 .format(node['host']))
419 print ("{:25} {}".format("Name", "Version"))
John DeNisco68b0ee32017-09-27 16:35:23 -0400420 for pkg in pkgs:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800421 try:
422 print ("{:25} {}".format(
423 pkg['name'], pkg['version']))
424 except KeyError:
425 print ("{}".format(pkg['name']))
John DeNisco68b0ee32017-09-27 16:35:23 -0400426
427 question = "\nDo you want to uninstall these "
428 question += "packages [y/N]? "
429 answer = autoconfig_yn(question, 'n')
430 if answer == 'y':
431 logger.setLevel(logging.INFO)
432 vutil.uninstall_vpp(node)
433 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800434 print ("\nThere are no VPP packages on node {}."
435 .format(node['host']))
John DeNisco68b0ee32017-09-27 16:35:23 -0400436 question = "Do you want to install VPP [Y/n]? "
437 answer = autoconfig_yn(question, 'y')
438 if answer == 'y':
jdeniscob0b9dad2018-12-18 15:29:45 -0500439 question = "Do you want to install the release version [Y/n]? "
440 answer = autoconfig_yn(question, 'y')
441 if answer == 'y':
442 branch = 'release'
443 else:
444 branch = 'master'
John DeNisco68b0ee32017-09-27 16:35:23 -0400445 logger.setLevel(logging.INFO)
jdeniscob0b9dad2018-12-18 15:29:45 -0500446 vutil.install_vpp(node, branch)
John DeNisco68b0ee32017-09-27 16:35:23 -0400447
448 # Set the logging level back
449 logger.setLevel(logging.ERROR)
450
451
452def autoconfig_patch_qemu():
453 """
454 Patch the correct qemu version that is needed for openstack
455
456 """
457
458 # Since these commands will take a while, we
459 # want to see the progress
460 logger = logging.getLogger()
461
462 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
463
464 nodes = acfg.get_nodes()
465 for i in nodes.items():
466 node = i[1]
467
468 logger.setLevel(logging.INFO)
469 acfg.patch_qemu(node)
470
471
John DeNiscoa3db0782017-10-17 11:07:22 -0400472def autoconfig_ipv4_setup():
473 """
474 Setup IPv4 interfaces
475
476 """
477
478 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
479 acfg.ipv4_interface_setup()
480
481
John DeNisco9fa5cf42018-02-06 15:23:05 -0500482def autoconfig_create_iperf_vm():
John DeNiscoc6b2a202017-11-01 12:37:47 -0400483 """
484 Setup IPv4 interfaces
485
486 """
487
488 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
John DeNisco9fa5cf42018-02-06 15:23:05 -0500489 acfg.destroy_iperf_vm('iperf-server')
490 acfg.create_and_bridge_iperf_virtual_interface()
491 acfg.create_iperf_vm('iperf-server')
John DeNiscoc6b2a202017-11-01 12:37:47 -0400492
493
John DeNisco68b0ee32017-09-27 16:35:23 -0400494def autoconfig_not_implemented():
495 """
496 This feature is not implemented
497
498 """
499
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800500 print ("\nThis Feature is not implemented yet....")
John DeNisco68b0ee32017-09-27 16:35:23 -0400501
502
John DeNiscoa3db0782017-10-17 11:07:22 -0400503def autoconfig_basic_test_menu():
504 """
505 The auto configuration basic test menu
506
507 """
508
509 basic_menu_text = '\nWhat would you like to do?\n\n\
5101) List/Create Simple IPv4 Setup\n\
John DeNisco9fa5cf42018-02-06 15:23:05 -05005112) Create an iperf VM and Connect to VPP an interface\n\
John DeNiscoa3db0782017-10-17 11:07:22 -04005129 or q) Back to main menu.'
John DeNiscoddecfb32017-11-15 08:50:57 -0500513
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800514 print ("{}".format(basic_menu_text))
John DeNiscoa3db0782017-10-17 11:07:22 -0400515
516 input_valid = False
517 answer = ''
518 while not input_valid:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800519 answer = input("\nCommand: ")
John DeNiscoa3db0782017-10-17 11:07:22 -0400520 if len(answer) > 1:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800521 print ("Please enter only 1 character.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400522 continue
523 if re.findall(r'[Qq1-29]', answer):
524 input_valid = True
525 answer = answer[0].lower()
526 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800527 print ("Please enter a character between 1 and 2 or 9.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400528
529 if answer == '9':
530 answer = 'q'
531
532 return answer
533
534
535def autoconfig_basic_test():
536 """
537 The auto configuration basic test menu
538
539 """
540 vutil = VPPUtil()
541 pkgs = vutil.get_installed_vpp_pkgs()
542 if len(pkgs) == 0:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800543 print ("\nVPP is not installed, install VPP with option 4.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400544 return
545
546 answer = ''
547 while answer != 'q':
548 answer = autoconfig_basic_test_menu()
549 if answer == '1':
550 autoconfig_ipv4_setup()
John DeNisco9fa5cf42018-02-06 15:23:05 -0500551 elif answer == '2':
552 autoconfig_create_iperf_vm()
John DeNiscoa3db0782017-10-17 11:07:22 -0400553 elif answer == '9' or answer == 'q':
554 return
555 else:
556 autoconfig_not_implemented()
557
558
John DeNisco68b0ee32017-09-27 16:35:23 -0400559def autoconfig_main_menu():
560 """
561 The auto configuration main menu
562
563 """
564
565 main_menu_text = '\nWhat would you like to do?\n\n\
5661) Show basic system information\n\
jdenisco7c37a672018-11-20 11:25:17 -05005672) Dry Run (Saves the configuration files in {}/vpp/vpp-config/dryrun.\n\
John DeNisco68b0ee32017-09-27 16:35:23 -04005683) Full configuration (WARNING: This will change the system configuration)\n\
5694) List/Install/Uninstall VPP.\n\
jdeniscob9875092018-11-06 16:10:04 -0500570q) Quit'.format(rootdir, rootdir)
John DeNisco68b0ee32017-09-27 16:35:23 -0400571
572 # 5) Dry Run from {}/vpp/vpp-config/auto-config.yaml (will not ask questions).\n\
573 # 6) Install QEMU patch (Needed when running openstack).\n\
574
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800575 print ("{}".format(main_menu_text))
John DeNisco68b0ee32017-09-27 16:35:23 -0400576
577 input_valid = False
578 answer = ''
579 while not input_valid:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800580 answer = input("\nCommand: ")
John DeNisco68b0ee32017-09-27 16:35:23 -0400581 if len(answer) > 1:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800582 print ("Please enter only 1 character.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400583 continue
jdeniscob9875092018-11-06 16:10:04 -0500584 if re.findall(r'[Qq1-4]', answer):
John DeNisco68b0ee32017-09-27 16:35:23 -0400585 input_valid = True
586 answer = answer[0].lower()
587 else:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800588 print ("Please enter a character between 1 and 4 or q.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400589
John DeNisco68b0ee32017-09-27 16:35:23 -0400590 return answer
591
592
593def autoconfig_main():
594 """
595 The auto configuration main entry point
596
597 """
598
John DeNiscoddecfb32017-11-15 08:50:57 -0500599 # Setup
600 autoconfig_setup()
601
John DeNisco68b0ee32017-09-27 16:35:23 -0400602 answer = ''
603 while answer != 'q':
604 answer = autoconfig_main_menu()
605 if answer == '1':
606 autoconfig_show_system()
607 elif answer == '2':
608 autoconfig_dryrun()
609 elif answer == '3':
610 autoconfig_apply()
611 elif answer == '4':
612 autoconfig_install()
jdeniscob9875092018-11-06 16:10:04 -0500613 elif answer == 'q':
John DeNisco68b0ee32017-09-27 16:35:23 -0400614 return
615 else:
616 autoconfig_not_implemented()
617
618
John DeNiscoddecfb32017-11-15 08:50:57 -0500619def autoconfig_setup(ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400620 """
621 The auto configuration setup function.
622
623 We will copy the configuration files to the dryrun directory.
624
625 """
626
627 global rootdir
628
John DeNisco68b0ee32017-09-27 16:35:23 -0400629 distro = VPPUtil.get_linux_distro()
630 if distro[0] == 'Ubuntu':
631 rootdir = '/usr/local'
632 else:
633 rootdir = '/usr'
634
635 # If there is a system configuration file use that, if not use the initial auto-config file
636 filename = rootdir + VPP_AUTO_CONFIGURATION_FILE
637 if os.path.isfile(filename) is True:
638 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
639 else:
640 raise RuntimeError('The Auto configuration file does not exist {}'.
641 format(filename))
642
John DeNiscoddecfb32017-11-15 08:50:57 -0500643 if ask_questions:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800644 print ("\nWelcome to the VPP system configuration utility")
John DeNisco68b0ee32017-09-27 16:35:23 -0400645
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800646 print ("\nThese are the files we will modify:")
647 print (" /etc/vpp/startup.conf")
648 print (" /etc/sysctl.d/80-vpp.conf")
649 print (" /etc/default/grub")
John DeNisco68b0ee32017-09-27 16:35:23 -0400650
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800651 print (
652 "\nBefore we change them, we'll create working copies in "
653 "{}".format(rootdir + VPP_DRYRUNDIR))
654 print (
655 "Please inspect them carefully before applying the actual "
656 "configuration (option 3)!")
John DeNisco68b0ee32017-09-27 16:35:23 -0400657
658 nodes = acfg.get_nodes()
659 for i in nodes.items():
660 node = i[1]
661
662 if (os.path.isfile(rootdir + VPP_STARTUP_FILE) is not True) and \
663 (os.path.isfile(VPP_REAL_STARTUP_FILE) is True):
664 autoconfig_cp(node, VPP_REAL_STARTUP_FILE, '{}'.format(rootdir + VPP_STARTUP_FILE))
665 if (os.path.isfile(rootdir + VPP_HUGE_PAGE_FILE) is not True) and \
666 (os.path.isfile(VPP_REAL_HUGE_PAGE_FILE) is True):
667 autoconfig_cp(node, VPP_REAL_HUGE_PAGE_FILE, '{}'.format(rootdir + VPP_HUGE_PAGE_FILE))
668 if (os.path.isfile(rootdir + VPP_GRUB_FILE) is not True) and \
669 (os.path.isfile(VPP_REAL_GRUB_FILE) is True):
670 autoconfig_cp(node, VPP_REAL_GRUB_FILE, '{}'.format(rootdir + VPP_GRUB_FILE))
671
John DeNiscoa7da67f2018-01-26 14:55:33 -0500672 # Be sure the uio_pci_generic driver is installed
673 cmd = 'modprobe uio_pci_generic'
674 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
675 if ret != 0:
John DeNisco4dc83972018-03-30 10:50:19 -0400676 logging.warning('{} failed on node {} {}'. format(cmd, node['host'], stderr))
John DeNiscoa7da67f2018-01-26 14:55:33 -0500677
John DeNisco68b0ee32017-09-27 16:35:23 -0400678
John DeNisco9fa5cf42018-02-06 15:23:05 -0500679# noinspection PyUnresolvedReferences
John DeNiscoddecfb32017-11-15 08:50:57 -0500680def execute_with_args(args):
681 """
682 Execute the configuration utility with agruments.
683
684 :param args: The Command line arguments
685 :type args: tuple
686 """
687
688 # Setup
689 autoconfig_setup(ask_questions=False)
690
691 # Execute the command
692 if args.show:
693 autoconfig_show_system()
694 elif args.dry_run:
695 autoconfig_dryrun(ask_questions=False)
696 elif args.apply:
697 autoconfig_apply(ask_questions=False)
698 else:
699 autoconfig_not_implemented()
700
701
702def config_main():
703 """
704 The vpp configuration utility main entry point.
705
706 """
John DeNisco68b0ee32017-09-27 16:35:23 -0400707
708 # Check for root
709 if not os.geteuid() == 0:
710 sys.exit('\nPlease run the VPP Configuration Utility as root.')
711
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800712 if len(sys.argv) > 1 and ((sys.argv[1] == '-d') or (
713 sys.argv[1] == '--debug')):
John DeNiscoa7da67f2018-01-26 14:55:33 -0500714 logging.basicConfig(level=logging.DEBUG)
715 else:
716 logging.basicConfig(level=logging.ERROR)
717
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800718 # If no arguments were entered, ask the user questions to
719 # get the main parameters
John DeNiscoddecfb32017-11-15 08:50:57 -0500720 if len(sys.argv) == 1:
John DeNiscoa7da67f2018-01-26 14:55:33 -0500721 autoconfig_main()
722 return
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800723 elif len(sys.argv) == 2 and ((sys.argv[1] == '-d') or (
724 sys.argv[1] == '--debug')):
John DeNiscoddecfb32017-11-15 08:50:57 -0500725 autoconfig_main()
726 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400727
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800728 # There were arguments specified, so execute the utility using
729 # command line arguments
730 description = 'The VPP configuration utility allows the user to '
731 'configure VPP in a simple and safe manner. The utility takes input '
732 'from the user or the specified .yaml file. The user should then '
733 'examine these files to be sure they are correct and then actually '
734 'apply the configuration. When run without arguments the utility run '
735 'in an interactive mode'
John DeNiscoddecfb32017-11-15 08:50:57 -0500736
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800737 main_parser = argparse.ArgumentParser(
738 prog='arg-test',
739 description=description,
740 epilog='See "%(prog)s help COMMAND" for help on a specific command.')
741 main_parser.add_argument('--apply', '-a', action='store_true',
742 help='Apply the cofiguration.')
743 main_parser.add_argument('--dry-run', '-dr', action='store_true',
744 help='Create the dryrun configuration files.')
745 main_parser.add_argument('--show', '-s', action='store_true',
746 help='Shows basic system information')
747 main_parser.add_argument('--debug', '-d', action='count',
748 help='Print debug output (multiple levels)')
John DeNiscoddecfb32017-11-15 08:50:57 -0500749
750 args = main_parser.parse_args()
751
752 return execute_with_args(args)
753
754
755if __name__ == '__main__':
John DeNiscoddecfb32017-11-15 08:50:57 -0500756 config_main()