blob: 74051300677f22c9a818331357669e677c2c2f43 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
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
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020035VPP_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"
John DeNisco68b0ee32017-09-27 16:35:23 -040043
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020044rootdir = ""
John DeNisco68b0ee32017-09-27 16:35:23 -040045
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()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020060 answer = ""
John DeNisco68b0ee32017-09-27 16:35:23 -040061 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
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020065 if re.findall(r"[YyNn]", answer):
John DeNisco68b0ee32017-09-27 16:35:23 -040066 input_valid = True
67 answer = answer[0].lower()
68 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020069 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
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020089 ofile = dst + ".orig"
90 (ret, stdout, stderr) = VPPUtil.exec_command("ls {}".format(dst))
John DeNisco68b0ee32017-09-27 16:35:23 -040091 if ret == 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020092 cmd = "cp {} {}".format(dst, ofile)
John DeNisco68b0ee32017-09-27 16:35:23 -040093 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
94 if ret != 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020095 raise RuntimeError(
96 "{} failed on node {} {} {}".format(cmd, node["host"], stdout, stderr)
97 )
John DeNisco68b0ee32017-09-27 16:35:23 -040098
99 # Copy the source file
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200100 cmd = "cp {} {}".format(src, os.path.dirname(dst))
John DeNisco68b0ee32017-09-27 16:35:23 -0400101 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
102 if ret != 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200103 raise RuntimeError("{} failed on node {} {}".format(cmd, node["host"], stderr))
John DeNisco68b0ee32017-09-27 16:35:23 -0400104
105
106def autoconfig_diff(node, src, dst):
107 """
108 Returns the diffs of 2 files.
109
110 :param node: Node dictionary with cpuinfo.
111 :param src: Source File
112 :param dst: Destination file
113 :type node: dict
114 :type src: string
115 :type dst: string
116 :returns: The Answer
117 :rtype: string
118 :raises RuntimeError: If command fails
119 """
120
121 # Diff the files and return the output
122 cmd = "diff {} {}".format(src, dst)
123 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200124 if stderr != "":
125 raise RuntimeError(
126 "{} failed on node {} {} {}".format(cmd, node["host"], ret, stderr)
127 )
John DeNisco68b0ee32017-09-27 16:35:23 -0400128
129 return stdout
130
131
132def autoconfig_show_system():
133 """
134 Shows the system information.
135
136 """
137
138 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
139
140 acfg.discover()
141
142 acfg.sys_info()
143
144
John DeNiscoddecfb32017-11-15 08:50:57 -0500145def autoconfig_hugepage_apply(node, ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400146 """
147 Apply the huge page configuration.
148 :param node: The node structure
149 :type node: dict
John DeNiscoddecfb32017-11-15 08:50:57 -0500150 :param ask_questions: When True ask the user questions
151 :type ask_questions: bool
John DeNisco68b0ee32017-09-27 16:35:23 -0400152 :returns: -1 if the caller should return, 0 if not
153 :rtype: int
154
155 """
156
157 diffs = autoconfig_diff(node, VPP_REAL_HUGE_PAGE_FILE, rootdir + VPP_HUGE_PAGE_FILE)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200158 if diffs != "":
159 print("These are the changes we will apply to")
160 print("the huge page file ({}).\n".format(VPP_REAL_HUGE_PAGE_FILE))
161 print(diffs)
John DeNiscoddecfb32017-11-15 08:50:57 -0500162 if ask_questions:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200163 answer = autoconfig_yn(
164 "\nAre you sure you want to apply these changes [Y/n]? ", "y"
165 )
166 if answer == "n":
John DeNiscoddecfb32017-11-15 08:50:57 -0500167 return -1
John DeNisco68b0ee32017-09-27 16:35:23 -0400168
169 # Copy and sysctl
170 autoconfig_cp(node, rootdir + VPP_HUGE_PAGE_FILE, VPP_REAL_HUGE_PAGE_FILE)
171 cmd = "sysctl -p {}".format(VPP_REAL_HUGE_PAGE_FILE)
172 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
173 if ret != 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200174 raise RuntimeError(
175 "{} failed on node {} {} {}".format(cmd, node["host"], stdout, stderr)
176 )
John DeNisco68b0ee32017-09-27 16:35:23 -0400177 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200178 print("\nThere are no changes to the huge page configuration.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400179
180 return 0
181
182
John DeNiscoddecfb32017-11-15 08:50:57 -0500183def autoconfig_vpp_apply(node, ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400184 """
185 Apply the vpp configuration.
186
187 :param node: The node structure
188 :type node: dict
John DeNiscoddecfb32017-11-15 08:50:57 -0500189 :param ask_questions: When True ask the user questions
190 :type ask_questions: bool
John DeNisco68b0ee32017-09-27 16:35:23 -0400191 :returns: -1 if the caller should return, 0 if not
192 :rtype: int
193
194 """
195
John DeNisco68b0ee32017-09-27 16:35:23 -0400196 diffs = autoconfig_diff(node, VPP_REAL_STARTUP_FILE, rootdir + VPP_STARTUP_FILE)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200197 if diffs != "":
198 print("These are the changes we will apply to")
199 print("the VPP startup file ({}).\n".format(VPP_REAL_STARTUP_FILE))
200 print(diffs)
John DeNiscoddecfb32017-11-15 08:50:57 -0500201 if ask_questions:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200202 answer = autoconfig_yn(
203 "\nAre you sure you want to apply these changes [Y/n]? ", "y"
204 )
205 if answer == "n":
John DeNiscoddecfb32017-11-15 08:50:57 -0500206 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:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200211 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
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200229 print("\nThe configured grub cmdline looks like this:")
230 configured_cmdline = node["grub"]["default_cmdline"]
231 current_cmdline = node["grub"]["current_cmdline"]
232 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]? "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200237 answer = autoconfig_yn(question, "y")
238 if answer == "y":
John DeNiscoddecfb32017-11-15 08:50:57 -0500239 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400240
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200241 node["grub"]["keep_cmdline"] = False
John DeNiscoddecfb32017-11-15 08:50:57 -0500242
243 # Diff the file
244 diffs = autoconfig_diff(node, VPP_REAL_GRUB_FILE, rootdir + VPP_GRUB_FILE)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200245 if diffs != "":
246 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:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200250 answer = autoconfig_yn(
251 "\nAre you sure you want to apply these changes [y/N]? ", "n"
252 )
253 if answer == "n":
John DeNisco68b0ee32017-09-27 16:35:23 -0400254 return -1
255
John DeNiscoddecfb32017-11-15 08:50:57 -0500256 # Copy and update grub
257 autoconfig_cp(node, rootdir + VPP_GRUB_FILE, VPP_REAL_GRUB_FILE)
258 distro = VPPUtil.get_linux_distro()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200259 if distro[0] == "Ubuntu":
John DeNiscoddecfb32017-11-15 08:50:57 -0500260 cmd = "update-grub"
John DeNisco68b0ee32017-09-27 16:35:23 -0400261 else:
John DeNiscoddecfb32017-11-15 08:50:57 -0500262 cmd = "grub2-mkconfig -o /boot/grub2/grub.cfg"
263
264 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
265 if ret != 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200266 raise RuntimeError(
267 "{} failed on node {} {} {}".format(cmd, node["host"], stdout, stderr)
268 )
John DeNiscoddecfb32017-11-15 08:50:57 -0500269
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200270 print("There have been changes to the GRUB config a", end=" ")
271 print("reboot will be required.")
John DeNiscoddecfb32017-11-15 08:50:57 -0500272 return -1
273 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200274 print("\nThere are no changes to the GRUB config.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400275
276 return 0
277
278
John DeNiscoddecfb32017-11-15 08:50:57 -0500279def autoconfig_apply(ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400280 """
281 Apply the configuration.
282
283 Show the diff of the dryrun file and the actual configuration file
284 Copy the files from the dryrun directory to the actual file.
285 Peform the system function
286
John DeNiscoddecfb32017-11-15 08:50:57 -0500287 :param ask_questions: When true ask the user questions
288 :type ask_questions: bool
289
John DeNisco68b0ee32017-09-27 16:35:23 -0400290 """
291
292 vutil = VPPUtil()
293 pkgs = vutil.get_installed_vpp_pkgs()
294 if len(pkgs) == 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200295 print("\nVPP is not installed, Install VPP with option 4.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400296 return
297
298 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
299
John DeNiscoddecfb32017-11-15 08:50:57 -0500300 if ask_questions:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200301 print("\nWe are now going to configure your system(s).\n")
302 answer = autoconfig_yn("Are you sure you want to do this [Y/n]? ", "y")
303 if answer == "n":
John DeNiscoddecfb32017-11-15 08:50:57 -0500304 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400305
306 nodes = acfg.get_nodes()
307 for i in nodes.items():
308 node = i[1]
309
310 # Check the system resources
311 if not acfg.min_system_resources(node):
312 return
313
John DeNiscoddecfb32017-11-15 08:50:57 -0500314 # Stop VPP
315 VPPUtil.stop(node)
316
John DeNisco68b0ee32017-09-27 16:35:23 -0400317 # Huge Pages
John DeNiscoddecfb32017-11-15 08:50:57 -0500318 ret = autoconfig_hugepage_apply(node, ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400319 if ret != 0:
320 return
321
322 # VPP
John DeNiscoddecfb32017-11-15 08:50:57 -0500323 ret = autoconfig_vpp_apply(node, ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400324 if ret != 0:
325 return
326
327 # Grub
John DeNiscoddecfb32017-11-15 08:50:57 -0500328 ret = autoconfig_grub_apply(node, ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400329 if ret != 0:
John DeNiscoddecfb32017-11-15 08:50:57 -0500330 # We can still start VPP, even if we haven't configured grub
331 VPPUtil.start(node)
John DeNisco68b0ee32017-09-27 16:35:23 -0400332 return
333
334 # Everything is configured start vpp
John DeNiscoddecfb32017-11-15 08:50:57 -0500335 VPPUtil.start(node)
John DeNisco68b0ee32017-09-27 16:35:23 -0400336
John DeNiscoa7da67f2018-01-26 14:55:33 -0500337
John DeNiscoddecfb32017-11-15 08:50:57 -0500338def autoconfig_dryrun(ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400339 """
340 Execute the dryrun function.
341
John DeNiscoddecfb32017-11-15 08:50:57 -0500342 :param ask_questions: When true ask the user for paraameters
343 :type ask_questions: bool
344
John DeNisco68b0ee32017-09-27 16:35:23 -0400345 """
346
John DeNiscoddecfb32017-11-15 08:50:57 -0500347 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE, clean=True)
John DeNisco68b0ee32017-09-27 16:35:23 -0400348
349 # Stop VPP on each node
350 nodes = acfg.get_nodes()
351 for i in nodes.items():
352 node = i[1]
353 VPPUtil.stop(node)
354
355 # Discover
356 acfg.discover()
357
358 # Check the system resources
359 nodes = acfg.get_nodes()
360 for i in nodes.items():
361 node = i[1]
362 if not acfg.min_system_resources(node):
363 return
364
365 # Modify the devices
John DeNiscoddecfb32017-11-15 08:50:57 -0500366 if ask_questions:
367 acfg.modify_devices()
368 else:
369 acfg.update_interfaces_config()
John DeNisco68b0ee32017-09-27 16:35:23 -0400370
jdeniscoaf86c632019-04-05 12:25:50 -0400371 # If there are no interfaces, just return
372 for i in nodes.items():
373 node = i[1]
374 if not acfg.has_interfaces(node):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200375 print(
376 "\nThere are no VPP interfaces configured, please configure at least 1."
377 )
jdeniscoaf86c632019-04-05 12:25:50 -0400378 return
379
John DeNisco68b0ee32017-09-27 16:35:23 -0400380 # Modify CPU
John DeNiscoddecfb32017-11-15 08:50:57 -0500381 acfg.modify_cpu(ask_questions)
John DeNisco68b0ee32017-09-27 16:35:23 -0400382
383 # Calculate the cpu parameters
384 acfg.calculate_cpu_parameters()
385
386 # Acquire TCP stack parameters
John DeNiscoddecfb32017-11-15 08:50:57 -0500387 if ask_questions:
388 acfg.acquire_tcp_params()
John DeNisco68b0ee32017-09-27 16:35:23 -0400389
390 # Apply the startup
391 acfg.apply_vpp_startup()
392
393 # Apply the grub configuration
394 acfg.apply_grub_cmdline()
395
396 # Huge Pages
John DeNiscoddecfb32017-11-15 08:50:57 -0500397 if ask_questions:
398 acfg.modify_huge_pages()
John DeNisco68b0ee32017-09-27 16:35:23 -0400399 acfg.apply_huge_pages()
400
401
402def autoconfig_install():
403 """
404 Install or Uninstall VPP.
405
406 """
407
408 # Since these commands will take a while, we
409 # want to see the progress
410 logger = logging.getLogger()
411
412 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
413 vutil = VPPUtil()
414
415 nodes = acfg.get_nodes()
416 for i in nodes.items():
417 node = i[1]
418
419 pkgs = vutil.get_installed_vpp_pkgs()
420
421 if len(pkgs) > 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200422 print("\nThese packages are installed on node {}".format(node["host"]))
423 print("{:25} {}".format("Name", "Version"))
John DeNisco68b0ee32017-09-27 16:35:23 -0400424 for pkg in pkgs:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800425 try:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200426 print("{:25} {}".format(pkg["name"], pkg["version"]))
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800427 except KeyError:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200428 print("{}".format(pkg["name"]))
John DeNisco68b0ee32017-09-27 16:35:23 -0400429
430 question = "\nDo you want to uninstall these "
431 question += "packages [y/N]? "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200432 answer = autoconfig_yn(question, "n")
433 if answer == "y":
John DeNisco68b0ee32017-09-27 16:35:23 -0400434 logger.setLevel(logging.INFO)
435 vutil.uninstall_vpp(node)
436 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200437 print("\nThere are no VPP packages on node {}.".format(node["host"]))
John DeNisco68b0ee32017-09-27 16:35:23 -0400438 question = "Do you want to install VPP [Y/n]? "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200439 answer = autoconfig_yn(question, "y")
440 if answer == "y":
jdeniscob0b9dad2018-12-18 15:29:45 -0500441 question = "Do you want to install the release version [Y/n]? "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200442 answer = autoconfig_yn(question, "y")
443 if answer == "y":
444 branch = "release"
jdeniscob0b9dad2018-12-18 15:29:45 -0500445 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200446 branch = "master"
John DeNisco68b0ee32017-09-27 16:35:23 -0400447 logger.setLevel(logging.INFO)
jdeniscob0b9dad2018-12-18 15:29:45 -0500448 vutil.install_vpp(node, branch)
John DeNisco68b0ee32017-09-27 16:35:23 -0400449
450 # Set the logging level back
451 logger.setLevel(logging.ERROR)
452
453
454def autoconfig_patch_qemu():
455 """
456 Patch the correct qemu version that is needed for openstack
457
458 """
459
460 # Since these commands will take a while, we
461 # want to see the progress
462 logger = logging.getLogger()
463
464 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
465
466 nodes = acfg.get_nodes()
467 for i in nodes.items():
468 node = i[1]
469
470 logger.setLevel(logging.INFO)
471 acfg.patch_qemu(node)
472
473
John DeNiscoa3db0782017-10-17 11:07:22 -0400474def autoconfig_ipv4_setup():
475 """
476 Setup IPv4 interfaces
477
478 """
479
480 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
481 acfg.ipv4_interface_setup()
482
483
John DeNisco9fa5cf42018-02-06 15:23:05 -0500484def autoconfig_create_iperf_vm():
John DeNiscoc6b2a202017-11-01 12:37:47 -0400485 """
486 Setup IPv4 interfaces
487
488 """
489
490 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200491 acfg.destroy_iperf_vm("iperf-server")
John DeNisco9fa5cf42018-02-06 15:23:05 -0500492 acfg.create_and_bridge_iperf_virtual_interface()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200493 acfg.create_iperf_vm("iperf-server")
John DeNiscoc6b2a202017-11-01 12:37:47 -0400494
495
John DeNisco68b0ee32017-09-27 16:35:23 -0400496def autoconfig_not_implemented():
497 """
498 This feature is not implemented
499
500 """
501
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200502 print("\nThis Feature is not implemented yet....")
John DeNisco68b0ee32017-09-27 16:35:23 -0400503
504
John DeNiscoa3db0782017-10-17 11:07:22 -0400505def autoconfig_basic_test_menu():
506 """
507 The auto configuration basic test menu
508
509 """
510
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200511 basic_menu_text = "\nWhat would you like to do?\n\n\
John DeNiscoa3db0782017-10-17 11:07:22 -04005121) List/Create Simple IPv4 Setup\n\
John DeNisco9fa5cf42018-02-06 15:23:05 -05005132) Create an iperf VM and Connect to VPP an interface\n\
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02005149 or q) Back to main menu."
John DeNiscoddecfb32017-11-15 08:50:57 -0500515
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200516 print("{}".format(basic_menu_text))
John DeNiscoa3db0782017-10-17 11:07:22 -0400517
518 input_valid = False
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200519 answer = ""
John DeNiscoa3db0782017-10-17 11:07:22 -0400520 while not input_valid:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800521 answer = input("\nCommand: ")
John DeNiscoa3db0782017-10-17 11:07:22 -0400522 if len(answer) > 1:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200523 print("Please enter only 1 character.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400524 continue
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200525 if re.findall(r"[Qq1-29]", answer):
John DeNiscoa3db0782017-10-17 11:07:22 -0400526 input_valid = True
527 answer = answer[0].lower()
528 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200529 print("Please enter a character between 1 and 2 or 9.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400530
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200531 if answer == "9":
532 answer = "q"
John DeNiscoa3db0782017-10-17 11:07:22 -0400533
534 return answer
535
536
537def autoconfig_basic_test():
538 """
539 The auto configuration basic test menu
540
541 """
542 vutil = VPPUtil()
543 pkgs = vutil.get_installed_vpp_pkgs()
544 if len(pkgs) == 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200545 print("\nVPP is not installed, install VPP with option 4.")
John DeNiscoa3db0782017-10-17 11:07:22 -0400546 return
547
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200548 answer = ""
549 while answer != "q":
John DeNiscoa3db0782017-10-17 11:07:22 -0400550 answer = autoconfig_basic_test_menu()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200551 if answer == "1":
John DeNiscoa3db0782017-10-17 11:07:22 -0400552 autoconfig_ipv4_setup()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200553 elif answer == "2":
John DeNisco9fa5cf42018-02-06 15:23:05 -0500554 autoconfig_create_iperf_vm()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200555 elif answer == "9" or answer == "q":
John DeNiscoa3db0782017-10-17 11:07:22 -0400556 return
557 else:
558 autoconfig_not_implemented()
559
560
John DeNisco68b0ee32017-09-27 16:35:23 -0400561def autoconfig_main_menu():
562 """
563 The auto configuration main menu
564
565 """
566
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200567 main_menu_text = "\nWhat would you like to do?\n\n\
John DeNisco68b0ee32017-09-27 16:35:23 -04005681) Show basic system information\n\
jdenisco7c37a672018-11-20 11:25:17 -05005692) Dry Run (Saves the configuration files in {}/vpp/vpp-config/dryrun.\n\
John DeNisco68b0ee32017-09-27 16:35:23 -04005703) Full configuration (WARNING: This will change the system configuration)\n\
5714) List/Install/Uninstall VPP.\n\
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200572q) Quit".format(
573 rootdir, rootdir
574 )
John DeNisco68b0ee32017-09-27 16:35:23 -0400575
576 # 5) Dry Run from {}/vpp/vpp-config/auto-config.yaml (will not ask questions).\n\
577 # 6) Install QEMU patch (Needed when running openstack).\n\
578
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200579 print("{}".format(main_menu_text))
John DeNisco68b0ee32017-09-27 16:35:23 -0400580
581 input_valid = False
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200582 answer = ""
John DeNisco68b0ee32017-09-27 16:35:23 -0400583 while not input_valid:
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800584 answer = input("\nCommand: ")
John DeNisco68b0ee32017-09-27 16:35:23 -0400585 if len(answer) > 1:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200586 print("Please enter only 1 character.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400587 continue
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200588 if re.findall(r"[Qq1-4]", answer):
John DeNisco68b0ee32017-09-27 16:35:23 -0400589 input_valid = True
590 answer = answer[0].lower()
591 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200592 print("Please enter a character between 1 and 4 or q.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400593
John DeNisco68b0ee32017-09-27 16:35:23 -0400594 return answer
595
596
597def autoconfig_main():
598 """
599 The auto configuration main entry point
600
601 """
602
John DeNiscoddecfb32017-11-15 08:50:57 -0500603 # Setup
604 autoconfig_setup()
605
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200606 answer = ""
607 while answer != "q":
John DeNisco68b0ee32017-09-27 16:35:23 -0400608 answer = autoconfig_main_menu()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200609 if answer == "1":
John DeNisco68b0ee32017-09-27 16:35:23 -0400610 autoconfig_show_system()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200611 elif answer == "2":
John DeNisco68b0ee32017-09-27 16:35:23 -0400612 autoconfig_dryrun()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200613 elif answer == "3":
John DeNisco68b0ee32017-09-27 16:35:23 -0400614 autoconfig_apply()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200615 elif answer == "4":
John DeNisco68b0ee32017-09-27 16:35:23 -0400616 autoconfig_install()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200617 elif answer == "q":
John DeNisco68b0ee32017-09-27 16:35:23 -0400618 return
619 else:
620 autoconfig_not_implemented()
621
622
John DeNiscoddecfb32017-11-15 08:50:57 -0500623def autoconfig_setup(ask_questions=True):
John DeNisco68b0ee32017-09-27 16:35:23 -0400624 """
625 The auto configuration setup function.
626
627 We will copy the configuration files to the dryrun directory.
628
629 """
630
631 global rootdir
632
John DeNisco68b0ee32017-09-27 16:35:23 -0400633 distro = VPPUtil.get_linux_distro()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200634 if distro[0] == "Ubuntu":
635 rootdir = "/usr/local"
John DeNisco68b0ee32017-09-27 16:35:23 -0400636 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200637 rootdir = "/usr"
John DeNisco68b0ee32017-09-27 16:35:23 -0400638
639 # If there is a system configuration file use that, if not use the initial auto-config file
640 filename = rootdir + VPP_AUTO_CONFIGURATION_FILE
641 if os.path.isfile(filename) is True:
642 acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
643 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200644 raise RuntimeError(
645 "The Auto configuration file does not exist {}".format(filename)
646 )
John DeNisco68b0ee32017-09-27 16:35:23 -0400647
John DeNiscoddecfb32017-11-15 08:50:57 -0500648 if ask_questions:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200649 print("\nWelcome to the VPP system configuration utility")
John DeNisco68b0ee32017-09-27 16:35:23 -0400650
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200651 print("\nThese are the files we will modify:")
652 print(" /etc/vpp/startup.conf")
653 print(" /etc/sysctl.d/80-vpp.conf")
654 print(" /etc/default/grub")
John DeNisco68b0ee32017-09-27 16:35:23 -0400655
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200656 print(
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800657 "\nBefore we change them, we'll create working copies in "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200658 "{}".format(rootdir + VPP_DRYRUNDIR)
659 )
660 print(
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800661 "Please inspect them carefully before applying the actual "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200662 "configuration (option 3)!"
663 )
John DeNisco68b0ee32017-09-27 16:35:23 -0400664
665 nodes = acfg.get_nodes()
666 for i in nodes.items():
667 node = i[1]
668
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200669 if (os.path.isfile(rootdir + VPP_STARTUP_FILE) is not True) and (
670 os.path.isfile(VPP_REAL_STARTUP_FILE) is True
671 ):
672 autoconfig_cp(
673 node, VPP_REAL_STARTUP_FILE, "{}".format(rootdir + VPP_STARTUP_FILE)
674 )
675 if (os.path.isfile(rootdir + VPP_HUGE_PAGE_FILE) is not True) and (
676 os.path.isfile(VPP_REAL_HUGE_PAGE_FILE) is True
677 ):
678 autoconfig_cp(
679 node, VPP_REAL_HUGE_PAGE_FILE, "{}".format(rootdir + VPP_HUGE_PAGE_FILE)
680 )
681 if (os.path.isfile(rootdir + VPP_GRUB_FILE) is not True) and (
682 os.path.isfile(VPP_REAL_GRUB_FILE) is True
683 ):
684 autoconfig_cp(
685 node, VPP_REAL_GRUB_FILE, "{}".format(rootdir + VPP_GRUB_FILE)
686 )
John DeNisco68b0ee32017-09-27 16:35:23 -0400687
John DeNiscoa7da67f2018-01-26 14:55:33 -0500688 # Be sure the uio_pci_generic driver is installed
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200689 cmd = "modprobe uio_pci_generic"
John DeNiscoa7da67f2018-01-26 14:55:33 -0500690 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
691 if ret != 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200692 logging.warning("{} failed on node {} {}".format(cmd, node["host"], stderr))
John DeNiscoa7da67f2018-01-26 14:55:33 -0500693
John DeNisco68b0ee32017-09-27 16:35:23 -0400694
John DeNisco9fa5cf42018-02-06 15:23:05 -0500695# noinspection PyUnresolvedReferences
John DeNiscoddecfb32017-11-15 08:50:57 -0500696def execute_with_args(args):
697 """
698 Execute the configuration utility with agruments.
699
700 :param args: The Command line arguments
701 :type args: tuple
702 """
703
704 # Setup
705 autoconfig_setup(ask_questions=False)
706
707 # Execute the command
708 if args.show:
709 autoconfig_show_system()
710 elif args.dry_run:
711 autoconfig_dryrun(ask_questions=False)
712 elif args.apply:
713 autoconfig_apply(ask_questions=False)
714 else:
715 autoconfig_not_implemented()
716
717
718def config_main():
719 """
720 The vpp configuration utility main entry point.
721
722 """
John DeNisco68b0ee32017-09-27 16:35:23 -0400723
724 # Check for root
725 if not os.geteuid() == 0:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200726 sys.exit("\nPlease run the VPP Configuration Utility as root.")
John DeNisco68b0ee32017-09-27 16:35:23 -0400727
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200728 if len(sys.argv) > 1 and ((sys.argv[1] == "-d") or (sys.argv[1] == "--debug")):
John DeNiscoa7da67f2018-01-26 14:55:33 -0500729 logging.basicConfig(level=logging.DEBUG)
730 else:
731 logging.basicConfig(level=logging.ERROR)
732
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800733 # If no arguments were entered, ask the user questions to
734 # get the main parameters
John DeNiscoddecfb32017-11-15 08:50:57 -0500735 if len(sys.argv) == 1:
John DeNiscoa7da67f2018-01-26 14:55:33 -0500736 autoconfig_main()
737 return
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200738 elif len(sys.argv) == 2 and ((sys.argv[1] == "-d") or (sys.argv[1] == "--debug")):
John DeNiscoddecfb32017-11-15 08:50:57 -0500739 autoconfig_main()
740 return
John DeNisco68b0ee32017-09-27 16:35:23 -0400741
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800742 # There were arguments specified, so execute the utility using
743 # command line arguments
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200744 description = "The VPP configuration utility allows the user to "
745 "configure VPP in a simple and safe manner. The utility takes input "
746 "from the user or the specified .yaml file. The user should then "
747 "examine these files to be sure they are correct and then actually "
748 "apply the configuration. When run without arguments the utility run "
749 "in an interactive mode"
John DeNiscoddecfb32017-11-15 08:50:57 -0500750
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800751 main_parser = argparse.ArgumentParser(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200752 prog="arg-test",
Paul Vinciguerra339bc6b2018-12-19 02:05:25 -0800753 description=description,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200754 epilog='See "%(prog)s help COMMAND" for help on a specific command.',
755 )
756 main_parser.add_argument(
757 "--apply", "-a", action="store_true", help="Apply the cofiguration."
758 )
759 main_parser.add_argument(
760 "--dry-run",
761 "-dr",
762 action="store_true",
763 help="Create the dryrun configuration files.",
764 )
765 main_parser.add_argument(
766 "--show", "-s", action="store_true", help="Shows basic system information"
767 )
768 main_parser.add_argument(
769 "--debug", "-d", action="count", help="Print debug output (multiple levels)"
770 )
John DeNiscoddecfb32017-11-15 08:50:57 -0500771
772 args = main_parser.parse_args()
773
774 return execute_with_args(args)
775
776
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200777if __name__ == "__main__":
John DeNiscoddecfb32017-11-15 08:50:57 -0500778 config_main()