Initial commit for phase 2, Add some simple validation.

Change-Id: I5b1d5600cdef4b05cc7c2f1cddb60aed2cc49ac2
Signed-off-by: John DeNisco <jdenisco@cisco.com>
This commit is contained in:
John DeNisco
2017-10-17 11:07:22 -04:00
committed by Dave Barach
parent cdeb7f2ae0
commit a3db0782d4
4 changed files with 235 additions and 8 deletions

View File

@ -1,7 +1,7 @@
from setuptools import setup
setup(name="vpp_config",
version="17.10.1",
version="17.10.3",
author="John DeNisco",
author_email="jdenisco@cisco.com",
description="VPP Configuration Utility",

View File

@ -440,6 +440,16 @@ def autoconfig_patch_qemu():
acfg.patch_qemu(node)
def autoconfig_ipv4_setup():
"""
Setup IPv4 interfaces
"""
acfg = AutoConfig(rootdir, VPP_AUTO_CONFIGURATION_FILE)
acfg.ipv4_interface_setup()
def autoconfig_not_implemented():
"""
This feature is not implemented
@ -449,6 +459,59 @@ def autoconfig_not_implemented():
print "\nThis Feature is not implemented yet...."
def autoconfig_basic_test_menu():
"""
The auto configuration basic test menu
"""
basic_menu_text = '\nWhat would you like to do?\n\n\
1) List/Create Simple IPv4 Setup\n\
9 or q) Back to main menu.'
print "{}".format(basic_menu_text)
input_valid = False
answer = ''
while not input_valid:
answer = raw_input("\nCommand: ")
if len(answer) > 1:
print "Please enter only 1 character."
continue
if re.findall(r'[Qq1-29]', answer):
input_valid = True
answer = answer[0].lower()
else:
print "Please enter a character between 1 and 2 or 9."
if answer == '9':
answer = 'q'
return answer
def autoconfig_basic_test():
"""
The auto configuration basic test menu
"""
vutil = VPPUtil()
pkgs = vutil.get_installed_vpp_pkgs()
if len(pkgs) == 0:
print "\nVPP is not installed, install VPP with option 4."
return
answer = ''
while answer != 'q':
answer = autoconfig_basic_test_menu()
if answer == '1':
autoconfig_ipv4_setup()
elif answer == '9' or answer == 'q':
return
else:
autoconfig_not_implemented()
def autoconfig_main_menu():
"""
The auto configuration main menu
@ -461,6 +524,7 @@ def autoconfig_main_menu():
and user input in {}/vpp/vpp-config/configs/auto-config.yaml\n\
3) Full configuration (WARNING: This will change the system configuration)\n\
4) List/Install/Uninstall VPP.\n\
5) Execute some basic tests.\n\
9 or q) Quit'.format(rootdir, rootdir)
# 5) Dry Run from {}/vpp/vpp-config/auto-config.yaml (will not ask questions).\n\
@ -479,7 +543,7 @@ def autoconfig_main_menu():
input_valid = True
answer = answer[0].lower()
else:
print "Please enter a character between 1 and 7 or 9."
print "Please enter a character between 1 and 5 or 9."
if answer == '9':
answer = 'q'
@ -503,6 +567,8 @@ def autoconfig_main():
autoconfig_apply()
elif answer == '4':
autoconfig_install()
elif answer == '5':
autoconfig_basic_test()
elif answer == '9' or answer == 'q':
return
else:

View File

@ -17,6 +17,7 @@ import logging
import os
import re
import yaml
import ipaddress
from vpplib.VPPUtil import VPPUtil
from vpplib.VppPCIUtil import VppPCIUtil
@ -83,6 +84,36 @@ class AutoConfig(object):
if ret != 0:
logging.debug(stderr)
@staticmethod
def _ask_user_ipv4():
"""
Asks the user for a number within a range.
default is returned if return is entered.
:returns: IP address and prefix len
:rtype: tuple
"""
while True:
answer = raw_input("Please enter the IPv4 Address [n.n.n.n]: ")
try:
ipaddr = ipaddress.ip_address(u'{}'.format(answer))
except:
print "Please enter a valid IPv4 address."
continue
answer = raw_input("Please enter the netmask [n.n.n.n]: ")
try:
netmask = ipaddress.ip_address(u'{}'.format(answer))
pl = ipaddress.ip_network(u'0.0.0.0/{}'.format(netmask))
plen = pl.exploded.split('/')[1]
break
except:
print "Please enter a valid IPv4 address and netmask."
continue
return ipaddr, plen
@staticmethod
def _ask_user_range(question, first, last, default):
"""
@ -1150,7 +1181,7 @@ other than VPP? [0-{}][0]? '.format(str(max_other_cores))
print "\nThere currently a total of {} huge pages.". \
format(total)
question = \
"How many huge pages do you want [{} - {}][{}]? ".\
"How many huge pages do you want [{} - {}][{}]? ". \
format(MIN_TOTAL_HUGE_PAGES, maxpages, MIN_TOTAL_HUGE_PAGES)
answer = self._ask_user_range(question, 1024, maxpages, 1024)
node['hugepages']['total'] = str(answer)
@ -1363,10 +1394,10 @@ other than VPP? [0-{}][0]? '.format(str(max_other_cores))
# System Memory
if 'free' in node['hugepages'] and \
'memfree' in node['hugepages'] and \
'size' in node['hugepages']:
free = node['hugepages']['free']
memfree = float(node['hugepages']['memfree'].split(' ')[0])
'memfree' in node['hugepages'] and \
'size' in node['hugepages']:
free = node['hugepages']['free']
memfree = float(node['hugepages']['memfree'].split(' ')[0])
hugesize = float(node['hugepages']['size'].split(' ')[0])
memhugepages = MIN_TOTAL_HUGE_PAGES * hugesize
@ -1425,3 +1456,94 @@ other than VPP? [0-{}][0]? '.format(str(max_other_cores))
self.min_system_resources(node)
print "\n=============================="
def _ipv4_interface_setup_questions(self, node):
"""
Ask the user some questions and get a list of interfaces
and IPv4 addresses associated with those interfaces
:param node: Node dictionary.
:type node: dict
:returns: A list or interfaces with ip addresses
:rtype: dict
"""
vpputl = VPPUtil()
interfaces = vpputl.get_hardware(node)
if interfaces == {}:
return
interfaces_with_ip = []
for intf in sorted(interfaces.items()):
name = intf[0]
if name == 'local0':
continue
question = "Would you like an address to interface {} [Y/n]? ".format(name)
answer = self._ask_user_yn(question, 'y')
if answer == 'y':
address = {}
addr, plen = self._ask_user_ipv4()
address['name'] = name
address['addr'] = addr
address['plen'] = plen
interfaces_with_ip.append(address)
return interfaces_with_ip
def ipv4_interface_setup(self):
"""
After asking the user some questions, get a list of interfaces
and IPv4 addresses associated with those interfaces
"""
for i in self._nodes.items():
node = i[1]
# Show the current interfaces with IP addresses
current_ints = VPPUtil.get_int_ip(node)
if current_ints is not {}:
print ("\nThese are the current interfaces with IP addresses:")
for items in sorted(current_ints.items()):
name = items[0]
value = items[1]
if 'address' not in value:
address = 'Not Set'
else:
address = value['address']
print ("{:30} {:20} {:10}".format(name, address, value['state']))
question = "\nWould you like to keep this configuration [Y/n]? "
answer = self._ask_user_yn(question, 'y')
if answer == 'y':
continue
else:
print ("\nThere are currently no interfaces with IP addresses.")
# Create a script that add the ip addresses to the interfaces
# and brings the interfaces up
ints_with_addrs = self._ipv4_interface_setup_questions(node)
content = ''
for ints in ints_with_addrs:
name = ints['name']
addr = ints['addr']
plen = ints['plen']
setipstr = 'set int ip address {} {}/{}\n'.format(name, addr, plen)
setintupstr = 'set int state {} up\n'.format(name)
content += setipstr + setintupstr
# Write the content to the script
rootdir = node['rootdir']
filename = rootdir + '/vpp/vpp-config/scripts/set_int_ipv4_and_up'
with open(filename, 'w+') as sfile:
sfile.write(content)
# Execute the script
cmd = 'vppctl exec {}'.format(filename)
(ret, stdout, stderr) = VPPUtil.exec_command(cmd)
if ret != 0:
logging.debug(stderr)
print("\nA script as been created at {}".format(filename))
print("This script can be run using the following:")
print("vppctl exec {}\n".format(filename))

View File

@ -372,6 +372,45 @@ class VPPUtil(object):
for _, value in def_setting_tb_displayed.items():
self.exec_command('vppctl sh {}'.format(value))
@staticmethod
def get_int_ip(node):
"""
Get the VPP interfaces and IP addresses
:param node: VPP node.
:type node: dict
:returns: Dictionary containing VPP interfaces and IP addresses
:rtype: dictionary
"""
interfaces = {}
cmd = 'vppctl show int addr'
(ret, stdout, stderr) = VPPUtil.exec_command(cmd)
if ret != 0:
return interfaces
lines = stdout.split('\n')
if len(lines[0]) is not 0:
if lines[0].split(' ')[0] == 'FileNotFoundError':
return interfaces
for line in lines:
if len(line) is 0:
continue
# If the first character is not whitespace
# create a new interface
if len(re.findall(r'\s', line[0])) is 0:
spl = line.split()
name = spl[0]
if name == 'local0':
continue
interfaces[name] = {}
interfaces[name]['state'] = spl[1].lstrip('(').rstrip('):\r')
else:
interfaces[name]['address'] = line.lstrip(' ').rstrip('\r')
return interfaces
@staticmethod
def get_hardware(node):
"""
@ -380,7 +419,7 @@ class VPPUtil(object):
:param node: VPP node.
:type node: dict
:returns: Dictionary containing improtant VPP information
:returns: Dictionary containing VPP hardware information
:rtype: dictionary
"""