Refactored 'save_only' mode
* Use common logic for 'normal' and 'save_only' modes - call modules logic in both cases Change-Id: I4ba533c1b7e9eb9e9e4538bec33b0565a8f8f2f0 Co-Authored-By: Fedor Zhadaev <fzhadaev@mirantis.com> Baesed-On-Change-Id: Id54f1229915336b8aebdb36562e06e2596c003f1 Closes-Bug: #1502110
This commit is contained in:
parent
53c5a00f86
commit
445ee81865
|
@ -193,3 +193,7 @@ def upIface(iface):
|
|||
code, _, _ = execute(["ifconfig", iface, "up"])
|
||||
if code != 0:
|
||||
raise NetworkException("Failed to up interface {0}".format(iface))
|
||||
|
||||
|
||||
def get_iface_info(iface, address_family=netifaces.AF_INET):
|
||||
return netifaces.ifaddresses(iface)[address_family][0]
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
from __future__ import absolute_import
|
||||
|
||||
from fuelmenu.common import dialog
|
||||
from fuelmenu.common import errors
|
||||
from fuelmenu.common import network
|
||||
from fuelmenu.common import timeout
|
||||
from fuelmenu.common import urwidwrapper as widget
|
||||
|
@ -44,12 +43,13 @@ log = logging.getLogger('fuelmenu.loader')
|
|||
|
||||
class FuelSetup(object):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, save_only=False, managed_iface=None):
|
||||
self.save_only = save_only
|
||||
self.footer = None
|
||||
self.frame = None
|
||||
self.screen = None
|
||||
self.managediface = network.get_physical_ifaces()[0]
|
||||
self.dns_might_have_changed = False
|
||||
self.managediface = managed_iface or network.get_physical_ifaces()[0]
|
||||
# Set to true to move all settings to end
|
||||
self.globalsave = True
|
||||
# Tasks to be executed on Apply
|
||||
|
@ -122,6 +122,8 @@ class FuelSetup(object):
|
|||
self.draw_child_screen(self.child.screen)
|
||||
|
||||
def refreshScreen(self):
|
||||
if self.save_only:
|
||||
return
|
||||
size = self.screen.get_cols_rows()
|
||||
self.screen.draw_screen(size, self.frame.render(size))
|
||||
|
||||
|
@ -144,8 +146,8 @@ class FuelSetup(object):
|
|||
self.choices = [m.name for m in self.children]
|
||||
|
||||
if len(self.children) == 0:
|
||||
import sys
|
||||
sys.exit(1)
|
||||
|
||||
# Build list of choices excluding visible
|
||||
self.visiblechoices = []
|
||||
for child, choice in zip(self.children, self.choices):
|
||||
|
@ -221,7 +223,10 @@ class FuelSetup(object):
|
|||
widget.TextLabel("It is highly recommended to change default "
|
||||
"admin password."),
|
||||
"WARNING!")
|
||||
self.mainloop.run()
|
||||
if not self.save_only:
|
||||
self.mainloop.run()
|
||||
else:
|
||||
self._save_only()
|
||||
|
||||
def exit_program(self, button):
|
||||
# Fix /etc/hosts before quitting
|
||||
|
@ -255,7 +260,7 @@ class FuelSetup(object):
|
|||
# Run invisible modules. They may not have screen methods
|
||||
if not module.visible:
|
||||
try:
|
||||
module.apply(None)
|
||||
self._save_module(module)
|
||||
except Exception as e:
|
||||
log.error("Unable to save module %s: %s" % (modulename, e))
|
||||
continue
|
||||
|
@ -267,7 +272,7 @@ class FuelSetup(object):
|
|||
% modulename)
|
||||
self.refreshScreen()
|
||||
module.refresh()
|
||||
if module.apply(None):
|
||||
if self._save_module(module):
|
||||
log.info("Saving module: %s" % modulename)
|
||||
else:
|
||||
return False, modulename
|
||||
|
@ -284,6 +289,31 @@ class FuelSetup(object):
|
|||
|
||||
return True, None
|
||||
|
||||
def _save_module(self, module):
|
||||
if self.save_only:
|
||||
if hasattr(module, 'check') and hasattr(module, 'save'):
|
||||
resp = module.check(None)
|
||||
module.save(resp)
|
||||
return True
|
||||
|
||||
return module.apply(None)
|
||||
|
||||
def _save_only(self):
|
||||
if utils.is_post_deployment():
|
||||
print(
|
||||
"Not updating settings when invoked during post-deployment"
|
||||
".\nRun fuelmenu manually to make changes."
|
||||
)
|
||||
sys.exit(0)
|
||||
|
||||
success, module_name = self.global_save()
|
||||
if not success:
|
||||
msg = ("Problems with module '{}'."
|
||||
" Settings have not been saved.".format(module_name))
|
||||
log.error(msg)
|
||||
sys.stderr.write(msg + '\n')
|
||||
sys.exit(1)
|
||||
|
||||
def reload_modules(self):
|
||||
for child in self.children:
|
||||
if hasattr(child, 'load') and callable(child.load):
|
||||
|
@ -294,133 +324,12 @@ class FuelSetup(object):
|
|||
self.refreshScreen()
|
||||
|
||||
|
||||
def setup():
|
||||
def setup(**kwargs):
|
||||
urwid.web_display.set_preferences("Fuel Setup")
|
||||
# try to handle short web requests quickly
|
||||
if urwid.web_display.handle_short_request():
|
||||
return
|
||||
FuelSetup()
|
||||
|
||||
|
||||
def save_only(iface, settingsfile=consts.SETTINGS_FILE):
|
||||
from fuelmenu.common import pwgen
|
||||
import netifaces
|
||||
|
||||
if utils.is_post_deployment():
|
||||
print("Not updating settings when invoked during post-deployment.\n"
|
||||
"Run fuelmenu manually to make changes.")
|
||||
sys.exit(0)
|
||||
|
||||
# Calculate and set Static/DHCP pool fields
|
||||
# Max IPs = net size - 2 (master node + bcast)
|
||||
try:
|
||||
ip = netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr']
|
||||
netmask = netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['netmask']
|
||||
mac = netifaces.ifaddresses(iface)[netifaces.AF_LINK][0]['addr']
|
||||
except Exception:
|
||||
print("Interface %s is missing either IP address or netmask"
|
||||
% (iface))
|
||||
sys.exit(1)
|
||||
net_ip_list = network.getNetwork(ip, netmask)
|
||||
try:
|
||||
dhcp_pool = net_ip_list[1:]
|
||||
dynamic_start = str(dhcp_pool[0])
|
||||
dynamic_end = str(dhcp_pool[-1])
|
||||
except Exception:
|
||||
print("Unable to define DHCP pools")
|
||||
sys.exit(1)
|
||||
try:
|
||||
hostname, sep, domain = os.uname()[1].partition('.')
|
||||
except Exception:
|
||||
print("Unable to calculate hostname and domain")
|
||||
sys.exit(1)
|
||||
try:
|
||||
dhcptimeout = 5
|
||||
dhcp_server_data = network.search_external_dhcp(iface, dhcptimeout)
|
||||
except errors.NetworkException:
|
||||
log.error("DHCP scan failed")
|
||||
dhcp_server_data = []
|
||||
|
||||
num_dhcp = len(dhcp_server_data)
|
||||
if num_dhcp == 0:
|
||||
log.debug("No DHCP servers found")
|
||||
else:
|
||||
# Problem exists, but permit user to continue
|
||||
log.error("%s foreign DHCP server(s) found: %s" %
|
||||
(num_dhcp, dhcp_server_data))
|
||||
print("ERROR: %s foreign DHCP server(s) found: %s" %
|
||||
(num_dhcp, dhcp_server_data))
|
||||
if network.duplicateIPExists(ip, iface):
|
||||
log.error("Duplicate host found with IP {0}".format(ip))
|
||||
print("ERROR: Duplicate host found with IP {0}".format(ip))
|
||||
|
||||
default_settings_file = os.path.join(os.path.dirname(__file__),
|
||||
"settings.yaml")
|
||||
mos_version = utils.get_fuel_version()
|
||||
|
||||
settings = settings_module.Settings()
|
||||
|
||||
settings.load(
|
||||
default_settings_file,
|
||||
template_kwargs={"mos_version": mos_version})
|
||||
|
||||
settings.load(settingsfile, template_kwargs={"mos_version": mos_version})
|
||||
|
||||
settings_upd = \
|
||||
{
|
||||
"ADMIN_NETWORK/interface": iface,
|
||||
"ADMIN_NETWORK/ipaddress": ip,
|
||||
"ADMIN_NETWORK/netmask": netmask,
|
||||
"ADMIN_NETWORK/mac": mac,
|
||||
"ADMIN_NETWORK/dhcp_pool_start": dynamic_start,
|
||||
"ADMIN_NETWORK/dhcp_pool_end": dynamic_end,
|
||||
"ADMIN_NETWORK/dhcp_gateway": ip,
|
||||
"ADMIN_NETWORK/ssh_network": network.getCidr(ip, netmask),
|
||||
"HOSTNAME": hostname,
|
||||
"DNS_DOMAIN": domain,
|
||||
"DNS_SEARCH": domain,
|
||||
"astute/user": "naily",
|
||||
"astute/password": pwgen.password(),
|
||||
"cobbler/user": "cobbler",
|
||||
"cobbler/password": pwgen.password(),
|
||||
"keystone/admin_token": pwgen.password(),
|
||||
"keystone/ostf_user": "ostf",
|
||||
"keystone/ostf_password": pwgen.password(),
|
||||
"keystone/nailgun_user": "nailgun",
|
||||
"keystone/nailgun_password": pwgen.password(),
|
||||
"keystone/monitord_user": "monitord",
|
||||
"keystone/monitord_password": pwgen.password(),
|
||||
"mcollective/user": "mcollective",
|
||||
"mcollective/password": pwgen.password(),
|
||||
"postgres/keystone_dbname": "keystone",
|
||||
"postgres/keystone_user": "keystone",
|
||||
"postgres/keystone_password": pwgen.password(),
|
||||
"postgres/nailgun_dbname": "nailgun",
|
||||
"postgres/nailgun_user": "nailgun",
|
||||
"postgres/nailgun_password": pwgen.password(),
|
||||
"postgres/ostf_dbname": "ostf",
|
||||
"postgres/ostf_user": "ostf",
|
||||
"postgres/ostf_password": pwgen.password(),
|
||||
"FUEL_ACCESS/user": "admin",
|
||||
"FUEL_ACCESS/password": "admin",
|
||||
}
|
||||
for setting in settings_upd.keys():
|
||||
if "/" in setting:
|
||||
part1, part2 = setting.split("/")
|
||||
settings.setdefault(part1, {})
|
||||
# Keep old values for passwords if already set
|
||||
if "password" in setting:
|
||||
settings[part1].setdefault(part2, settings_upd[setting])
|
||||
else:
|
||||
settings[part1][part2] = settings_upd[setting]
|
||||
else:
|
||||
if "password" in setting:
|
||||
settings.setdefault(setting, settings_upd[setting])
|
||||
else:
|
||||
settings[setting] = settings_upd[setting]
|
||||
|
||||
# Write astute.yaml
|
||||
settings.write(outfn=settingsfile)
|
||||
FuelSetup(**kwargs)
|
||||
|
||||
|
||||
def main(*args, **kwargs):
|
||||
|
@ -458,7 +367,8 @@ def main(*args, **kwargs):
|
|||
sys.exit(1)
|
||||
|
||||
if options.save_only:
|
||||
save_only(options.iface)
|
||||
setup(save_only=True,
|
||||
managed_iface=options.iface)
|
||||
else:
|
||||
setup()
|
||||
|
||||
|
|
|
@ -138,6 +138,9 @@ class BootstrapImage(urwid.WidgetWrap):
|
|||
self.parent.refreshScreen()
|
||||
responses = self.responses
|
||||
|
||||
if self.parent.save_only:
|
||||
return responses
|
||||
|
||||
errors = []
|
||||
if not responses.get(BOOTSTRAP_SKIP_BUILD_KEY):
|
||||
errors.extend(self.check_apt_repos(responses))
|
||||
|
|
|
@ -37,8 +37,7 @@ class CobblerConfig(urwid.WidgetWrap):
|
|||
self.parent = parent
|
||||
self.getNetwork()
|
||||
self.gateway = self.get_default_gateway_linux()
|
||||
self.activeiface = sorted(self.netsettings.keys())[0]
|
||||
self.parent.managediface = self.activeiface
|
||||
self.activeiface = self.parent.managediface
|
||||
|
||||
# UI text
|
||||
text1 = "Settings for PXE booting of slave nodes."
|
||||
|
@ -289,7 +288,7 @@ interface first.")
|
|||
settings = self.parent.settings
|
||||
ModuleHelper.load_to_defaults(settings, self.defaults)
|
||||
|
||||
iface = settings["ADMIN_NETWORK"]["interface"]
|
||||
iface = settings.get("ADMIN_NETWORK", {}).get("interface")
|
||||
if iface in self.netsettings.keys():
|
||||
self.activeiface = iface
|
||||
|
||||
|
|
|
@ -109,6 +109,9 @@ is accessible"}
|
|||
else:
|
||||
responses[fieldname] = self.edits[index].get_edit_text()
|
||||
|
||||
if self.parent.save_only:
|
||||
return responses
|
||||
|
||||
# Validate each field
|
||||
errors = []
|
||||
|
||||
|
@ -305,7 +308,8 @@ is accessible"}
|
|||
except Exception:
|
||||
log.warning("Unable to look up system hostname")
|
||||
|
||||
oldsettings.update(self.resolv_conf_settings())
|
||||
if not self.parent.save_only:
|
||||
oldsettings.update(self.resolv_conf_settings())
|
||||
|
||||
ModuleHelper.load_to_defaults(oldsettings,
|
||||
self.defaults,
|
||||
|
|
|
@ -65,13 +65,17 @@ class FuelUser(urwid.WidgetWrap):
|
|||
responses[fieldname] = self.edits[index].get_edit_text()
|
||||
|
||||
password = responses["FUEL_ACCESS/password"]
|
||||
confirm_password = responses.pop("CONFIRM_PASSWORD")
|
||||
|
||||
if self.parent.save_only:
|
||||
return responses
|
||||
|
||||
# Validate each field
|
||||
errors = []
|
||||
warnings = []
|
||||
|
||||
# Passwords must match
|
||||
if password != responses["CONFIRM_PASSWORD"] and \
|
||||
if password != confirm_password and \
|
||||
password != self.defaults['FUEL_ACCESS/password']['value']:
|
||||
errors.append("Passwords do not match.")
|
||||
|
||||
|
@ -115,8 +119,6 @@ class FuelUser(urwid.WidgetWrap):
|
|||
else:
|
||||
self.parent.footer.set_text("No errors found.")
|
||||
|
||||
# Remove confirm from responses so it isn't saved
|
||||
del responses["CONFIRM_PASSWORD"]
|
||||
return responses
|
||||
|
||||
def apply(self, args):
|
||||
|
@ -126,7 +128,7 @@ class FuelUser(urwid.WidgetWrap):
|
|||
log.error("%s" % (responses))
|
||||
for index, fieldname in enumerate(self.fields):
|
||||
if fieldname == "FUEL_ACCESS/password":
|
||||
return (self.edits[index].get_edit_text() == "")
|
||||
return self.edits[index].get_edit_text() == ""
|
||||
return False
|
||||
self.save(responses)
|
||||
return True
|
||||
|
|
|
@ -302,6 +302,7 @@ class Interfaces(urwid.WidgetWrap):
|
|||
l3ifconfig['params'] = params
|
||||
puppetclasses.append(l3ifconfig)
|
||||
self.log.info("Puppet data: %s" % (puppetclasses))
|
||||
|
||||
try:
|
||||
self.parent.refreshScreen()
|
||||
result = puppet.puppetApply(puppetclasses)
|
||||
|
|
|
@ -70,6 +70,7 @@ class NtpSetup(urwid.WidgetWrap):
|
|||
self.parent.refreshScreen()
|
||||
# Get field information
|
||||
responses = dict()
|
||||
ntp_enabled = False
|
||||
|
||||
for index, fieldname in enumerate(self.fields):
|
||||
if fieldname == "blank":
|
||||
|
@ -77,16 +78,17 @@ class NtpSetup(urwid.WidgetWrap):
|
|||
elif fieldname == "ntpenabled":
|
||||
rb_group = self.edits[index].rb_group
|
||||
if rb_group[0].state:
|
||||
responses["ntpenabled"] = "Yes"
|
||||
else:
|
||||
responses["ntpenabled"] = "No"
|
||||
ntp_enabled = True
|
||||
else:
|
||||
responses[fieldname] = self.edits[index].get_edit_text()
|
||||
|
||||
if self.parent.save_only:
|
||||
return responses
|
||||
|
||||
# Validate each field
|
||||
errors = []
|
||||
warnings = []
|
||||
if responses['ntpenabled'] == "No":
|
||||
if not ntp_enabled:
|
||||
# Disabled NTP means passing no NTP servers to save method
|
||||
# Even though nodes will use Fuel Master, NTP[1,2,3] are empty so
|
||||
# Fuel Master can initialize itself as a time source.
|
||||
|
@ -97,17 +99,7 @@ class NtpSetup(urwid.WidgetWrap):
|
|||
self.parent.footer.set_text("No errors found.")
|
||||
log.info("No errors found")
|
||||
return responses
|
||||
if all(map(lambda f: (len(responses[f]) == 0), self.fields)):
|
||||
pass
|
||||
# We will allow empty if user doesn't need external networking
|
||||
# and present a strongly worded warning
|
||||
# msg = "If you continue without NTP, you may have issues with "\
|
||||
# + "deployment due to time synchronization issues. These "\
|
||||
# + "problems are exacerbated in virtualized deployments."
|
||||
|
||||
# dialog.display_dialog(
|
||||
# self, widget.TextLabel(msg), "Empty NTP Warning")
|
||||
del responses['ntpenabled']
|
||||
for ntpfield, ntpvalue in responses.iteritems():
|
||||
# NTP must be under 255 chars
|
||||
if len(ntpvalue) >= 255:
|
||||
|
|
|
@ -183,6 +183,9 @@ class Restore(urwid.WidgetWrap):
|
|||
self.parent.settings, self.defaults, ignoredparams=('PATH',))
|
||||
|
||||
def save(self, responses):
|
||||
if self.parent.save_only:
|
||||
return
|
||||
|
||||
self.parent.settings.merge(responses)
|
||||
|
||||
def screenUI(self):
|
||||
|
|
|
@ -97,6 +97,10 @@ class RootPassword(urwid.WidgetWrap):
|
|||
return True
|
||||
|
||||
def save(self, password):
|
||||
if self.parent.save_only:
|
||||
# We shouldn't change root password in save_only mode
|
||||
return True
|
||||
|
||||
hashed = crypt.crypt(password, utils.gensalt())
|
||||
log.info("Changing root password")
|
||||
# clear any locks first
|
||||
|
|
|
@ -100,16 +100,15 @@ class Security(urwid.WidgetWrap):
|
|||
self.parent.settings.merge(newsettings)
|
||||
|
||||
def load(self):
|
||||
admin_network = network.get_iface_info(self.parent.managediface)
|
||||
self.defaults[SSH_NETWORK]['value'] = network.getCidr(
|
||||
admin_network["addr"],
|
||||
admin_network["netmask"])
|
||||
|
||||
helper.ModuleHelper.load_to_defaults(
|
||||
self.parent.settings,
|
||||
self.defaults,
|
||||
ignoredparams=[SSH_NETWORK])
|
||||
admin_network = self.parent.settings["ADMIN_NETWORK"]
|
||||
self.defaults[SSH_NETWORK]['value'] = network.getCidr(
|
||||
admin_network["ipaddress"],
|
||||
admin_network["netmask"])
|
||||
if 'ssh_network' in admin_network:
|
||||
self.defaults[SSH_NETWORK]['value'] = admin_network["ssh_network"]
|
||||
)
|
||||
|
||||
def refresh(self):
|
||||
pass
|
||||
|
|
|
@ -5,15 +5,6 @@ DNS_UPSTREAM: "8.8.8.8"
|
|||
NTP1: "0.fuel.pool.ntp.org"
|
||||
NTP2: "1.fuel.pool.ntp.org"
|
||||
NTP3: "2.fuel.pool.ntp.org"
|
||||
ADMIN_NETWORK:
|
||||
interface: "eth0"
|
||||
ipaddress: "10.20.0.2"
|
||||
netmask: "255.255.255.0"
|
||||
cidr: "10.20.0.0/24"
|
||||
size: "256"
|
||||
dhcp_gateway: "10.20.0.2"
|
||||
dhcp_pool_start: "10.20.0.3"
|
||||
dhcp_pool_end: "10.20.0.254"
|
||||
FUEL_ACCESS:
|
||||
user: "admin"
|
||||
password: "admin"
|
||||
|
|
Loading…
Reference in New Issue