Merge "Enable PXEBoot address range options in config_controller"
This commit is contained in:
commit
d009a5335a
|
@ -10,7 +10,7 @@ from configobjects import DEFAULT_NAMES, NETWORK_PREFIX_NAMES, OAM_TYPE, \
|
|||
from netaddr import IPRange
|
||||
from utils import lag_mode_to_str, validate_network_str, \
|
||||
check_network_overlap, is_mtu_valid, is_speed_valid, get_service, \
|
||||
get_optional
|
||||
get_optional, validate_address_str
|
||||
|
||||
from exceptions import ConfigFail, ValidateFail
|
||||
|
||||
|
@ -359,6 +359,8 @@ class ConfigValidator(object):
|
|||
|
||||
def validate_pxeboot(self):
|
||||
# PXEBoot network configuration
|
||||
start_end_in_config = False
|
||||
|
||||
if self.config_type in [REGION_CONFIG, SUBCLOUD_CONFIG]:
|
||||
self.pxeboot_section_name = 'REGION2_PXEBOOT_NETWORK'
|
||||
else:
|
||||
|
@ -373,6 +375,51 @@ class ConfigValidator(object):
|
|||
raise ValidateFail("Invalid PXEBOOT_NETWORK IP version - "
|
||||
"only IPv4 supported")
|
||||
self.configured_networks.append(pxeboot_subnet)
|
||||
pxeboot_start_address = None
|
||||
pxeboot_end_address = None
|
||||
if self.conf.has_option(self.pxeboot_section_name,
|
||||
"IP_START_ADDRESS"):
|
||||
start_addr_str = self.conf.get(self.pxeboot_section_name,
|
||||
"IP_START_ADDRESS")
|
||||
pxeboot_start_address = validate_address_str(
|
||||
start_addr_str, pxeboot_subnet
|
||||
)
|
||||
|
||||
if self.conf.has_option(self.pxeboot_section_name,
|
||||
"IP_END_ADDRESS"):
|
||||
end_addr_str = self.conf.get(self.pxeboot_section_name,
|
||||
"IP_END_ADDRESS")
|
||||
pxeboot_end_address = validate_address_str(
|
||||
end_addr_str, pxeboot_subnet
|
||||
)
|
||||
|
||||
if pxeboot_start_address or pxeboot_end_address:
|
||||
if not pxeboot_end_address:
|
||||
raise ConfigFail("Missing attribute %s for %s" %
|
||||
('IP_END_ADDRESS',
|
||||
self.pxeboot_section_name))
|
||||
|
||||
if not pxeboot_start_address:
|
||||
raise ConfigFail("Missing attribute %s for %s" %
|
||||
('IP_START_ADDRESS',
|
||||
self.pxeboot_section_name))
|
||||
|
||||
if not pxeboot_start_address < pxeboot_end_address:
|
||||
raise ConfigFail("Start address %s not "
|
||||
"less than end address %s for %s."
|
||||
% (start_addr_str,
|
||||
end_addr_str,
|
||||
self.pxeboot_section_name))
|
||||
|
||||
min_addresses = 8
|
||||
if not IPRange(start_addr_str, end_addr_str).size >= \
|
||||
min_addresses:
|
||||
raise ConfigFail("Address range for %s must contain "
|
||||
"at least %d addresses." %
|
||||
(self.pxeboot_section_name,
|
||||
min_addresses))
|
||||
start_end_in_config = True
|
||||
|
||||
self.pxeboot_network_configured = True
|
||||
except ValidateFail as e:
|
||||
raise ConfigFail("Invalid PXEBOOT_CIDR value of %s for %s."
|
||||
|
@ -385,13 +432,28 @@ class ConfigValidator(object):
|
|||
if self.pxeboot_network_configured:
|
||||
self.cgcs_conf.set('cPXEBOOT', 'PXEBOOT_SUBNET',
|
||||
str(pxeboot_subnet))
|
||||
if start_end_in_config:
|
||||
self.cgcs_conf.set("cPXEBOOT",
|
||||
"PXEBOOT_START_ADDRESS",
|
||||
start_addr_str)
|
||||
self.cgcs_conf.set("cPXEBOOT",
|
||||
"PXEBOOT_END_ADDRESS",
|
||||
end_addr_str)
|
||||
|
||||
pxeboot_floating_addr = pxeboot_start_address
|
||||
pxeboot_controller_addr_0 = pxeboot_start_address + 1
|
||||
pxeboot_controller_addr_1 = pxeboot_controller_addr_0 + 1
|
||||
else:
|
||||
pxeboot_floating_addr = pxeboot_subnet[2]
|
||||
pxeboot_controller_addr_0 = pxeboot_subnet[3]
|
||||
pxeboot_controller_addr_1 = pxeboot_subnet[4]
|
||||
self.cgcs_conf.set('cPXEBOOT',
|
||||
'CONTROLLER_PXEBOOT_FLOATING_ADDRESS',
|
||||
str(pxeboot_subnet[2]))
|
||||
str(pxeboot_floating_addr))
|
||||
self.cgcs_conf.set('cPXEBOOT', 'CONTROLLER_PXEBOOT_ADDRESS_0',
|
||||
str(pxeboot_subnet[3]))
|
||||
str(pxeboot_controller_addr_0))
|
||||
self.cgcs_conf.set('cPXEBOOT', 'CONTROLLER_PXEBOOT_ADDRESS_1',
|
||||
str(pxeboot_subnet[4]))
|
||||
str(pxeboot_controller_addr_1))
|
||||
self.cgcs_conf.set('cPXEBOOT', 'PXECONTROLLER_FLOATING_HOSTNAME',
|
||||
'pxecontroller')
|
||||
|
||||
|
|
|
@ -58,8 +58,16 @@ def timestamped(dname, fmt='{dname}_%Y-%m-%d-%H-%M-%S'):
|
|||
|
||||
|
||||
def prompt_for(prompt_text, default_input, validator):
|
||||
valid = False
|
||||
while not valid:
|
||||
"""
|
||||
:param prompt_text: text for the prompt
|
||||
:param default_input: default input if user hit enter directly
|
||||
:param validator: validator function to validate user input,
|
||||
validator should return error message in case
|
||||
of invalid input, or None if input is valid.
|
||||
:return: return a valid user input
|
||||
"""
|
||||
error_msg = None
|
||||
while True:
|
||||
user_input = input(prompt_text)
|
||||
if user_input.lower() == 'q':
|
||||
raise UserQuit
|
||||
|
@ -67,12 +75,12 @@ def prompt_for(prompt_text, default_input, validator):
|
|||
user_input = default_input
|
||||
|
||||
if validator:
|
||||
valid = validator(user_input)
|
||||
else:
|
||||
valid = True
|
||||
error_msg = validator(user_input)
|
||||
|
||||
if not valid:
|
||||
print("Invalid choice")
|
||||
if error_msg is not None:
|
||||
print(error_msg)
|
||||
else:
|
||||
break
|
||||
|
||||
return user_input
|
||||
|
||||
|
@ -345,6 +353,9 @@ class ConfigAssistant():
|
|||
self.controller_pxeboot_hostname_suffix = "-pxeboot"
|
||||
self.private_pxeboot_subnet = IPNetwork("169.254.202.0/24")
|
||||
self.pxecontroller_floating_hostname = "pxecontroller"
|
||||
self.pxeboot_start_address = None
|
||||
self.pxeboot_end_address = None
|
||||
self.use_entire_pxeboot_subnet = True
|
||||
|
||||
# Management network config
|
||||
self.management_interface_configured = False
|
||||
|
@ -668,7 +679,8 @@ class ConfigAssistant():
|
|||
}
|
||||
user_input = prompt_for(
|
||||
"System mode [duplex-direct]: ", '1',
|
||||
lambda text: text in value_mapping
|
||||
lambda text: "Invalid choice" if text not in value_mapping
|
||||
else None
|
||||
)
|
||||
self.system_mode = value_mapping[user_input.lower()]
|
||||
|
||||
|
@ -683,7 +695,8 @@ class ConfigAssistant():
|
|||
}
|
||||
user_input = prompt_for(
|
||||
"Configure Distributed Cloud System Controller [y/N]: ", 'n',
|
||||
lambda text: text in value_mapping
|
||||
lambda text: "Invalid choice" if text not in value_mapping
|
||||
else None
|
||||
)
|
||||
self.system_dc_role = value_mapping[user_input.lower()]
|
||||
|
||||
|
@ -781,6 +794,9 @@ class ConfigAssistant():
|
|||
self.controller_pxeboot_address_1 = \
|
||||
IPAddress(self.pxeboot_subnet[4])
|
||||
|
||||
self.pxeboot_start_address = self.pxeboot_subnet[2]
|
||||
self.pxeboot_end_address = self.pxeboot_subnet[-2]
|
||||
|
||||
def input_pxeboot_config(self):
|
||||
"""Allow user to input pxeboot config and perform validation."""
|
||||
|
||||
|
@ -846,12 +862,77 @@ class ConfigAssistant():
|
|||
break
|
||||
except AddrFormatError:
|
||||
print("Invalid subnet - please enter a valid IPv4 subnet")
|
||||
|
||||
value_mapping = {
|
||||
"y": True,
|
||||
"n": False,
|
||||
}
|
||||
|
||||
user_input = prompt_for(
|
||||
"Use entire PXEBoot subnet [Y/n]: ", 'Y',
|
||||
lambda text: "Invalid choice"
|
||||
if text.lower() not in value_mapping
|
||||
else None
|
||||
)
|
||||
self.use_entire_pxeboot_subnet = value_mapping[user_input.lower()]
|
||||
|
||||
if not self.use_entire_pxeboot_subnet:
|
||||
def validate_input_address(text, error_header):
|
||||
try:
|
||||
validate_address_str(text, self.pxeboot_subnet)
|
||||
return None
|
||||
except ValidateFail as e:
|
||||
return "%s\n Reason: %s" % (error_header, e)
|
||||
|
||||
while True:
|
||||
self.pxeboot_start_address = self.pxeboot_subnet[2]
|
||||
self.pxeboot_end_address = self.pxeboot_subnet[-2]
|
||||
input_str = prompt_for(
|
||||
"PXEBoot network start address [" +
|
||||
str(self.pxeboot_start_address) +
|
||||
"]: ", str(self.pxeboot_start_address),
|
||||
lambda text: validate_input_address(
|
||||
text, "Invalid start address.")
|
||||
)
|
||||
self.pxeboot_start_address = IPAddress(input_str)
|
||||
|
||||
input_str = prompt_for(
|
||||
"PXEBoot network end address [" +
|
||||
str(self.pxeboot_end_address) +
|
||||
"]: ", str(self.pxeboot_end_address),
|
||||
lambda text: validate_input_address(
|
||||
text, "Invalid end address.")
|
||||
)
|
||||
self.pxeboot_end_address = IPAddress(input_str)
|
||||
|
||||
if not self.pxeboot_start_address < \
|
||||
self.pxeboot_end_address:
|
||||
print("Start address not less than end address. ")
|
||||
continue
|
||||
|
||||
address_range = IPRange(
|
||||
str(self.pxeboot_start_address),
|
||||
str(self.pxeboot_end_address))
|
||||
|
||||
min_addresses = 8
|
||||
if not address_range.size >= min_addresses:
|
||||
print(
|
||||
"Address range must contain at least "
|
||||
"%d addresses." % min_addresses)
|
||||
continue
|
||||
|
||||
print('')
|
||||
break
|
||||
else:
|
||||
self.pxeboot_start_address = self.pxeboot_subnet[2]
|
||||
self.pxeboot_end_address = self.pxeboot_subnet[-2]
|
||||
else:
|
||||
# Use private subnet for pxe booting
|
||||
self.pxeboot_subnet = self.private_pxeboot_subnet
|
||||
self.pxeboot_start_address = self.pxeboot_subnet[2]
|
||||
self.pxeboot_end_address = self.pxeboot_subnet[-2]
|
||||
|
||||
default_controller_pxeboot_float_ip = self.pxeboot_subnet[2]
|
||||
ip_input = IPAddress(default_controller_pxeboot_float_ip)
|
||||
ip_input = self.pxeboot_start_address
|
||||
if not self.is_valid_pxeboot_address(ip_input):
|
||||
raise ConfigFail("Unable to create controller PXEBoot "
|
||||
"floating address")
|
||||
|
@ -2443,6 +2524,19 @@ class ConfigAssistant():
|
|||
self.separate_pxeboot_network = True
|
||||
self.pxeboot_subnet = IPNetwork(config.get(
|
||||
'cPXEBOOT', 'PXEBOOT_SUBNET'))
|
||||
if config.has_option('cPXEBOOT', 'PXEBOOT_START_ADDRESS'):
|
||||
self.pxeboot_start_address = IPAddress(config.get(
|
||||
'cPXEBOOT', 'PXEBOOT_START_ADDRESS'))
|
||||
if config.has_option('cPXEBOOT', 'PXEBOOT_END_ADDRESS'):
|
||||
self.pxeboot_end_address = IPAddress(config.get(
|
||||
'cPXEBOOT', 'PXEBOOT_END_ADDRESS'))
|
||||
if not self.pxeboot_start_address and \
|
||||
not self.pxeboot_end_address:
|
||||
self.pxeboot_start_address = self.pxeboot_subnet[2]
|
||||
self.pxeboot_end_address = self.pxeboot_subnet[-2]
|
||||
self.use_entire_pxeboot_subnet = True
|
||||
else:
|
||||
self.use_entire_pxeboot_subnet = False
|
||||
self.controller_pxeboot_address_0 = IPAddress(config.get(
|
||||
'cPXEBOOT', 'CONTROLLER_PXEBOOT_ADDRESS_0'))
|
||||
self.controller_pxeboot_address_1 = IPAddress(config.get(
|
||||
|
@ -2955,6 +3049,10 @@ class ConfigAssistant():
|
|||
str(self.controller_pxeboot_address_0))
|
||||
print("Controller 1 PXEBoot address: " +
|
||||
str(self.controller_pxeboot_address_1))
|
||||
if not self.use_entire_pxeboot_subnet:
|
||||
print("PXEBoot start address: " +
|
||||
str(self.pxeboot_start_address))
|
||||
print("PXEBoot end address: " + str(self.pxeboot_end_address))
|
||||
print("PXEBoot Controller floating hostname: " +
|
||||
str(self.pxecontroller_floating_hostname))
|
||||
|
||||
|
@ -4103,8 +4201,8 @@ class ConfigAssistant():
|
|||
'name': 'pxeboot',
|
||||
'network': str(self.pxeboot_subnet.network),
|
||||
'prefix': self.pxeboot_subnet.prefixlen,
|
||||
'ranges': [(str(self.pxeboot_subnet[2]),
|
||||
str(self.pxeboot_subnet[-2]))],
|
||||
'ranges': [(str(self.pxeboot_start_address),
|
||||
str(self.pxeboot_end_address))],
|
||||
}
|
||||
pool = client.sysinv.address_pool.create(**values)
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
[LOGICAL_INTERFACE_1]
|
||||
LAG_INTERFACE=N
|
||||
INTERFACE_MTU=1500
|
||||
INTERFACE_LINK_CAPACITY=1000
|
||||
INTERFACE_PORTS=eth1
|
||||
|
||||
[LOGICAL_INTERFACE_2]
|
||||
LAG_INTERFACE=N
|
||||
;LAG_MODE=
|
||||
INTERFACE_MTU=1500
|
||||
;INTERFACE_LINK_CAPACITY=
|
||||
INTERFACE_PORTS=eth0
|
||||
|
||||
[PXEBOOT_NETWORK]
|
||||
PXEBOOT_CIDR=192.168.102.0/24
|
||||
IP_START_ADDRESS=192.168.102.32
|
||||
IP_END_ADDRESS=192.168.102.54
|
||||
|
||||
[MGMT_NETWORK]
|
||||
VLAN=123
|
||||
CIDR=192.168.204.0/24
|
||||
MULTICAST_CIDR=239.1.1.0/28
|
||||
DYNAMIC_ALLOCATION=Y
|
||||
LOGICAL_INTERFACE=LOGICAL_INTERFACE_1
|
||||
|
||||
;[INFRA_NETWORK]
|
||||
;VLAN=124
|
||||
;IP_START_ADDRESS=192.168.205.102
|
||||
;IP_END_ADDRESS=192.168.205.199
|
||||
;DYNAMIC_ALLOCATION=Y
|
||||
;CIDR=192.168.205.0/24
|
||||
;LOGICAL_INTERFACE=LOGICAL_INTERFACE_1
|
||||
|
||||
[OAM_NETWORK]
|
||||
;VLAN=
|
||||
;IP_START_ADDRESS=10.10.10.2
|
||||
;IP_END_ADDRESS=10.10.10.4
|
||||
IP_FLOATING_ADDRESS=10.10.10.20
|
||||
IP_UNIT_0_ADDRESS=10.10.10.30
|
||||
IP_UNIT_1_ADDRESS=10.10.10.40
|
||||
CIDR=10.10.10.0/24
|
||||
GATEWAY=10.10.10.1
|
||||
LOGICAL_INTERFACE=LOGICAL_INTERFACE_2
|
||||
|
||||
;[PXEBOOT_NETWORK]
|
||||
;PXEBOOT_CIDR=192.168.203.0/24
|
||||
|
||||
;[BOARD_MANAGEMENT_NETWORK]
|
||||
;VLAN=1
|
||||
;MTU=1496
|
||||
;SUBNET=192.168.203.0/24
|
||||
|
||||
[AUTHENTICATION]
|
||||
ADMIN_PASSWORD=Li69nux*
|
||||
|
||||
[VERSION]
|
||||
RELEASE = TEST.SW.VERSION
|
|
@ -528,3 +528,38 @@ def test_system_config_validation():
|
|||
validate_only=True)
|
||||
with pytest.raises(exceptions.ConfigFail):
|
||||
validate(system_config, DEFAULT_CONFIG, None, False)
|
||||
|
||||
|
||||
def test_pxeboot_range():
|
||||
""" Test import of system_config file for PXEBoot network address """
|
||||
|
||||
# Create the path to the system_config file
|
||||
systemfile = os.path.join(
|
||||
os.getcwd(), "controllerconfig/tests/files/", "system_config.pxeboot")
|
||||
|
||||
# Test import and generation of answer file
|
||||
_test_system_config(systemfile)
|
||||
|
||||
# Test detection of invalid PXEBoot network start address
|
||||
system_config = cr.parse_system_config(systemfile)
|
||||
system_config.set('PXEBOOT_NETWORK', 'IP_START_ADDRESS', '8.123.122.345')
|
||||
with pytest.raises(exceptions.ConfigFail):
|
||||
validate(system_config, DEFAULT_CONFIG, None, False)
|
||||
|
||||
# Test detection of invalid PXEBoot network end address
|
||||
system_config = cr.parse_system_config(systemfile)
|
||||
system_config.set('PXEBOOT_NETWORK', 'IP_END_ADDRESS', '128.123.122.345')
|
||||
with pytest.raises(exceptions.ConfigFail):
|
||||
validate(system_config, DEFAULT_CONFIG, None, False)
|
||||
|
||||
# Test detection of smaller PXEBoot network end address
|
||||
system_config = cr.parse_system_config(systemfile)
|
||||
system_config.set('PXEBOOT_NETWORK', 'IP_END_ADDRESS', '192.168.102.30')
|
||||
with pytest.raises(exceptions.ConfigFail):
|
||||
validate(system_config, DEFAULT_CONFIG, None, False)
|
||||
|
||||
# Test detection of PXEBoot network range less than min required (8)
|
||||
system_config = cr.parse_system_config(systemfile)
|
||||
system_config.set('PXEBOOT_NETWORK', 'IP_END_ADDRESS', '128.123.122.34')
|
||||
with pytest.raises(exceptions.ConfigFail):
|
||||
validate(system_config, DEFAULT_CONFIG, None, False)
|
||||
|
|
Loading…
Reference in New Issue