def check(self, args): """Validate that all fields have valid values and sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() #Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname == "blank": pass else: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] if all(map(lambda f: (len(responses[f]) == 0), self.fields)): #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") for ntpfield, ntpvalue in responses.iteritems(): #NTP must be under 255 chars if len(ntpvalue) >= 255: errors.append("%s must be under 255 chars." % self.defaults[ntpfield]['label']) #NTP needs to have valid chars if re.search('[^a-zA-Z0-9-.]', ntpvalue): errors.append("%s contains illegal characters." % self.defaults[ntpfield]['label']) #ensure external NTP is valid if len(ntpvalue) > 0: #Validate first NTP address try: #Try to test NTP via ntpdate if not self.checkNTP(ntpvalue): errors.append("%s unable to perform NTP." % self.defaults[ntpfield]['label']) except Exception as e: errors.append(e) errors.append("%s unable to perform NTP: %s" % self.defaults[ntpfield]['label']) if len(errors) > 0: self.parent.footer.set_text( "Errors: %s First error: %s" % (len(errors), errors[0])) log.warning("Errors: %s %s" % (len(errors), errors)) return False else: self.parent.footer.set_text("No errors found.") log.info("No errors found") return responses
def check(self, args): """Validate that all fields have valid values and sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() #Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname == "blank": pass else: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] if all(map(lambda f: (len(responses[f]) == 0), self.fields)): #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") for ntpfield, ntpvalue in responses.iteritems(): #NTP must be under 255 chars if len(ntpvalue) >= 255: errors.append("%s must be under 255 chars." % self.defaults[ntpfield]['label']) #NTP needs to have valid chars if re.search('[^a-zA-Z0-9-.]', ntpvalue): errors.append("%s contains illegal characters." % self.defaults[ntpfield]['label']) #ensure external NTP is valid if len(ntpvalue) > 0: #Validate first NTP address try: #Try to test NTP via ntpdate if not self.checkNTP(ntpvalue): errors.append("%s unable to perform NTP." % self.defaults[ntpfield]['label']) except Exception as e: errors.append(e) errors.append("%s unable to perform NTP: %s" % self.defaults[ntpfield]['label']) if len(errors) > 0: self.parent.footer.set_text("Errors: %s First error: %s" % (len(errors), errors[0])) log.warning("Errors: %s %s" % (len(errors), errors)) return False else: self.parent.footer.set_text("No errors found.") log.info("No errors found") return responses
def save(self): results, modulename = self.parent.global_save() if results: self.parent.footer.set_text("All changes saved successfully!") return True else: #show pop up with more details msg = "ERROR: Module %s failed to save. Go back" % (modulename)\ + " and fix any mistakes or choose Quit without Saving." dialog.display_dialog(self, widget.TextLabel(msg), "Error saving changes!") return False
def test_display_dialog(self, m_pile, m_dialog): original_widget = self.object.parent.mainloop.widget self.assertEqual( m_dialog.return_value, dialog.display_dialog(self.object, self.body, self.title, self.escape_key) ) m_pile.assert_called_once_with([self.body]) m_dialog.assert_called_once_with( self.title, m_pile.return_value, self.escape_key, original_widget, self.object.parent.mainloop ) self.assertEqual(self.object.parent.mainloop.widget, m_dialog.return_value)
def check(self, args): self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() responses = dict() for index, fieldname in enumerate(self.fields): if fieldname != helper.BLANK_KEY: responses[fieldname] = self.edits[index].get_edit_text() ssh_network = responses[SSH_NETWORK] errors = [] if len(ssh_network) == 0: self.parent.footer.set_text("Address is empty, " "will be changed to 0.0.0.0/0") log.warning("Empty address, changed to 0.0.0.0/0") responses[SSH_NETWORK] = "0.0.0.0/0" msg = "If you continue without the address, you may able to"\ + " access the Fuel through SSH from any network. The"\ + " address will be changed to 0.0.0.0/0. This can lead"\ + " to the security issues." dialog.display_dialog( self, widget.TextLabel(msg), "Empty Address Warning") else: if not network.getCidrSize(ssh_network): errors.append("Incorrect network address format: {0}." .format(ssh_network)) if len(errors) > 0: log.error("Errors: %s %s", len(errors), errors) helper.ModuleHelper.display_failed_check_dialog(self, errors) return False self.parent.footer.set_text("No errors found.") return responses
def check(self, args): self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() responses = dict() for index, fieldname in enumerate(self.fields): if fieldname != helper.BLANK_KEY: responses[fieldname] = self.edits[index].get_edit_text() ssh_network = responses[SSH_NETWORK] errors = [] if len(ssh_network) == 0: self.parent.footer.set_text("Address is empty, " "will be changed to 0.0.0.0/0") log.warning("Empty address, changed to 0.0.0.0/0") responses[SSH_NETWORK] = "0.0.0.0/0" msg = "If you continue without the address, you may able to"\ + " access the Fuel through SSH from any network. The"\ + " address will be changed to 0.0.0.0/0. This can lead"\ + " to the security issues." dialog.display_dialog(self, widget.TextLabel(msg), "Empty Address Warning") else: if not network.getCidrSize(ssh_network): errors.append("Incorrect network address format: {0}.".format( ssh_network)) if len(errors) > 0: log.error("Errors: %s %s", len(errors), errors) helper.ModuleHelper.display_failed_check_dialog(self, errors) return False self.parent.footer.set_text("No errors found.") return responses
def test_display_dialog(self, m_pile, m_dialog): original_widget = self.object.parent.mainloop.widget self.assertEqual( m_dialog.return_value, dialog.display_dialog( self.object, self.body, self.title, self.escape_key) ) m_pile.assert_called_once_with([self.body]) m_dialog.assert_called_once_with( self.title, m_pile.return_value, self.escape_key, original_widget, self.object.parent.mainloop) self.assertEqual( self.object.parent.mainloop.widget, m_dialog.return_value)
def check(self, args): """Validate that all fields have valid values and sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() # Get field information responses = dict() ntp_enabled = False for index, fieldname in enumerate(self.fields): if fieldname == "blank": pass elif fieldname == "ntpenabled": rb_group = self.edits[index].rb_group if rb_group[0].state: 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 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. responses = {"NTP1": "", "NTP2": "", "NTP3": ""} self.parent.footer.set_text("No errors found.") log.info("No errors found") return responses for ntpfield, ntpvalue in responses.iteritems(): # NTP must be under 255 chars if len(ntpvalue) >= 255: errors.append("%s must be under 255 chars." % self.defaults[ntpfield]["label"]) # NTP needs to have valid chars if re.search("[^a-zA-Z0-9-.]", ntpvalue): errors.append("%s contains illegal characters." % self.defaults[ntpfield]["label"]) # ensure external NTP is valid if len(ntpvalue) > 0: # Validate first NTP address try: # Try to test NTP via ntpdate if not self.checkNTP(ntpvalue): warnings.append("%s unable to perform NTP." % self.defaults[ntpfield]["label"]) except Exception: warnings.append("%s unable to sync time with server.: %s" % self.defaults[ntpfield]["label"]) if len(errors) > 0: log.error("Errors: %s %s" % (len(errors), errors)) modulehelper.ModuleHelper.display_failed_check_dialog(self, errors) return False else: if len(warnings) > 0: msg = ["NTP configuration has the following warnings:"] msg.extend(warnings) msg.append("You may see errors during provisioning and " "in system logs. NTP errors are not fatal.") warning_msg = "\n".join(str(line) for line in msg) dialog.display_dialog(self, widget.TextLabel(warning_msg), "NTP Warnings") log.warning(warning_msg) self.parent.footer.set_text("No errors found.") log.info("No errors found") return responses
def display_dialog(cls, modobj, error_msg, title): body = widget.TextLabel(error_msg) dialog.display_dialog(modobj, body, title)
def check(self, args): """Validate that all fields have valid values and some sanity checks""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() #Get field information responses = dict() for index, fieldname in enumerate(fields): if fieldname == "blank": pass else: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] #hostname must be under 60 chars if len(responses["HOSTNAME"]) >= 60: errors.append("Hostname must be under 60 chars.") #hostname must not be empty if len(responses["HOSTNAME"]) == 0: errors.append("Hostname must not be empty.") #hostname needs to have valid chars if re.search('[^a-z0-9-]', responses["HOSTNAME"]): errors.append( "Hostname must contain only alphanumeric and hyphen.") #domain must be under 180 chars if len(responses["DNS_DOMAIN"]) >= 180: errors.append("Domain must be under 180 chars.") #domain must not be empty if len(responses["DNS_DOMAIN"]) == 0: errors.append("Domain must not be empty.") #domain needs to have valid chars if re.match('[^a-z0-9-.]', responses["DNS_DOMAIN"]): errors.append( "Domain must contain only alphanumeric, period and hyphen.") #ensure external DNS is valid if len(responses["DNS_UPSTREAM"]) == 0: #We will allow empty if user doesn't need external networking #and present a strongly worded warning msg = "If you continue without DNS, you may not be able to access"\ + " external data necessary for installation needed for " \ + "some OpenStack Releases." diag = dialog.display_dialog( self, TextLabel(msg), "Empty DNS Warning") else: #external DNS must contain only numbers, periods, and commas #TODO: More serious ip address checking if re.match('[^0-9.,]', responses["DNS_UPSTREAM"]): errors.append( "External DNS must contain only IP addresses and commas.") #ensure test DNS name isn't empty if len(responses["TEST_DNS"]) == 0: errors.append("Test DNS must not be empty.") #Validate first IP address try: if netaddr.valid_ipv4(responses["DNS_UPSTREAM"].split(",")[0]): DNS_UPSTREAM = responses["DNS_UPSTREAM"].split(",")[0] else: errors.append("Not a valid IP address for External DNS: %s" % responses["DNS_UPSTREAM"]) #Try to resolve with first address if not self.checkDNS(DNS_UPSTREAM): errors.append("IP %s unable to resolve host." % DNS_UPSTREAM) except Exception, e: errors.append(e) errors.append("Not a valid IP address for External DNS: %s" % responses["DNS_UPSTREAM"])
def check(self, args): """Validate that all fields have valid values and sanity checks.""" #Get field information responses = dict() self.parent.footer.set_text("Checking data...") for index, fieldname in enumerate(self.fields): if fieldname == "blank" or fieldname == "ifname": pass elif fieldname == "bootproto": rb_group = self.edits[index].rb_group if rb_group[0].state: responses["bootproto"] = "dhcp" else: responses["bootproto"] = "none" elif fieldname == "onboot": rb_group = self.edits[index].rb_group if rb_group[0].state: responses["onboot"] = "yes" else: responses["onboot"] = "no" else: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] if responses["onboot"] == "no": numactiveifaces = 0 for iface in self.netsettings: if self.netsettings[iface]['addr'] != "": numactiveifaces += 1 if numactiveifaces < 2 and \ self.netsettings[self.activeiface]['addr'] != "": #Block user because puppet l23network fails if all intefaces #are disabled. errors.append("Cannot disable all interfaces.") elif responses["bootproto"] == "dhcp": self.parent.footer.set_text("Scanning for DHCP servers. " "Please wait...") self.parent.refreshScreen() try: dhcptimeout = 5 with timeout.run_with_timeout(dhcp_checker.utils.IfaceState, [self.activeiface], timeout=dhcptimeout) as iface: dhcp_server_data = timeout.run_with_timeout( dhcp_checker.api.check_dhcp_on_eth, [iface, dhcptimeout], timeout=dhcptimeout) except (KeyboardInterrupt, timeout.TimeoutError): self.log.debug("DHCP scan timed out") self.log.warning(traceback.format_exc()) dhcp_server_data = [] except Exception: self.log.warning("dhcp_checker failed to check on %s" % self.activeiface) dhcp_server_data = [] responses["dhcp_nowait"] = False if len(dhcp_server_data) < 1: self.log.debug("No DHCP servers found. Warning user about " "dhcp_nowait.") #Build dialog elements dhcp_info = [] dhcp_info.append( urwid.Padding(urwid.Text(("header", "!!! WARNING !!!")), "center")) dhcp_info.append( widget.TextLabel( "Unable to detect DHCP server" + "on interface %s." % (self.activeiface) + "\nDHCP will be set up in the background, " + "but may not receive an IP address. You may " + "want to check your DHCP connection manually " + "using the Shell Login menu to the left.")) dialog.display_dialog( self, urwid.Pile(dhcp_info), "DHCP Servers Found on %s" % self.activeiface) self.parent.refreshScreen() responses["dhcp_nowait"] = True #Check ipaddr, netmask, gateway only if static elif responses["bootproto"] == "none": try: if netaddr.valid_ipv4(responses["ipaddr"]): if not netaddr.IPAddress(responses["ipaddr"]): raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except (BadIPException, Exception): errors.append("Not a valid IP address: %s" % responses["ipaddr"]) try: if netaddr.valid_ipv4(responses["netmask"]): netmask = netaddr.IPAddress(responses["netmask"]) if netmask.is_netmask is False: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except (BadIPException, Exception): errors.append("Not a valid netmask: %s" % responses["netmask"]) try: if len(responses["gateway"]) > 0: #Check if gateway is valid if netaddr.valid_ipv4(responses["gateway"]) is False: raise BadIPException("Gateway IP address is not valid") #Check if gateway is in same subnet if network.inSameSubnet(responses["ipaddr"], responses["gateway"], responses["netmask"]) is False: raise BadIPException("Gateway IP is not in same " "subnet as IP address") except (BadIPException, Exception) as e: errors.append(e) self.parent.footer.set_text("Scanning for duplicate IP address..") if len(responses["ipaddr"]) > 0: if self.netsettings[self.activeiface]['link'].upper() != "UP": try: network.upIface(self.activeiface) except NetworkException as e: errors.append("Cannot activate {0} to check for " "duplicate IP.".format(self.activeiface)) if network.duplicateIPExists(responses["ipaddr"], self.activeiface): errors.append("Duplicate host found with IP {0}.".format( responses["ipaddr"])) if len(errors) > 0: self.parent.footer.set_text("Error: %s" % (errors[0])) self.log.error("Errors: %s %s" % (len(errors), errors)) return False else: self.parent.footer.set_text("No errors found.") return responses
def check(self, args): """Validates all fields have valid values and some sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() # Refresh networking to make sure IP matches self.getNetwork() # Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname != "blank" and "label" not in fieldname: responses[fieldname] = self.edits[index].get_edit_text() # Validate each field errors = [] # Set internal_{ipaddress,netmask,interface} responses["ADMIN_NETWORK/interface"] = self.activeiface responses["ADMIN_NETWORK/netmask"] = self.netsettings[ self.activeiface]["netmask"] responses["ADMIN_NETWORK/mac"] = self.netsettings[ self.activeiface]["mac"] responses["ADMIN_NETWORK/ipaddress"] = self.netsettings[ self.activeiface]["addr"] # ensure management interface is valid if responses["ADMIN_NETWORK/interface"] not in self.netsettings.keys(): errors.append("Management interface not valid") else: self.parent.footer.set_text("Scanning for DHCP servers. \ Please wait...") self.parent.refreshScreen() try: dhcptimeout = 5 dhcp_server_data = network.search_external_dhcp( self.activeiface, dhcptimeout) except network.NetworkException: log.warning('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)) # Build dialog elements dhcp_info = [] dhcp_info.append(urwid.Padding( urwid.Text(("header", "!!! WARNING !!!")), "center")) dhcp_info.append(widget.TextLabel("You have selected an \ interface that contains one or more DHCP servers. This will impact \ provisioning. You should disable these DHCP servers before you continue, or \ else deployment will likely fail.")) dhcp_info.append(widget.TextLabel("")) for index, dhcp_server in enumerate(dhcp_server_data): dhcp_info.append(widget.TextLabel("DHCP Server #%s:" % (index + 1))) dhcp_info.append(widget.TextLabel("IP address: %-10s" % dhcp_server['server_ip'])) dhcp_info.append(widget.TextLabel("MAC address: %-10s" % dhcp_server['mac'])) dhcp_info.append(widget.TextLabel("")) dialog.display_dialog(self, urwid.Pile(dhcp_info), "DHCP Servers Found on %s" % self.activeiface) # Ensure pool start and end are on the same subnet as mgmt_if # Ensure mgmt_if has an IP first if len(self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["addr"]) == 0: errors.append("Go to Interfaces to configure management \ interface first.") else: # Ensure ADMIN_NETWORK/interface is not running DHCP if self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["bootproto"] == "dhcp": errors.append("%s is running DHCP. Change it to static " "first." % self.activeiface) # Ensure DHCP Pool Start and DHCP Pool are valid IPs try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_pool_start"]): dhcp_start = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_pool_start"]) if not dhcp_start: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Pool Start") try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_gateway"]): dhcp_gateway = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_gateway"]) if not dhcp_gateway: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Gateway") try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_pool_end"]): dhcp_end = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_pool_end"]) if not dhcp_end: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Pool end") # Ensure pool start and end are in the same # subnet of each other netmask = self.netsettings[responses[ "ADMIN_NETWORK/interface" ]]["netmask"] if not network.inSameSubnet( responses["ADMIN_NETWORK/dhcp_pool_start"], responses["ADMIN_NETWORK/dhcp_pool_end"], netmask): errors.append("DHCP Pool start and end are not in the " "same subnet.") # Ensure pool start and end are in the right netmask mgmt_if_ipaddr = self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["addr"] if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_pool_start"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Pool start does not match management" " network.") if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_pool_end"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Pool end does not match management " "network.") if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_gateway"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Gateway does not match management " "network.") self.parent.footer.set_text("Scanning for duplicate IP address" "es. Please wait...") # Bind arping to mgmt_if_ipaddr if it assigned assigned_ips = [v.get('addr') for v in self.netsettings.itervalues()] arping_bind = mgmt_if_ipaddr in assigned_ips if network.duplicateIPExists(mgmt_if_ipaddr, self.activeiface, arping_bind): errors.append("Duplicate host found with IP {0}.".format( mgmt_if_ipaddr)) # Extra checks for post-deployment changes if utils.is_post_deployment(): settings = self.parent.settings # Admin interface cannot change if self.activeiface != settings["ADMIN_NETWORK"]["interface"]: errors.append("Cannot change admin interface after deployment") # PXE network range must contain previous PXE network range old_range = network.range( settings["ADMIN_NETWORK"]["dhcp_pool_start"], settings["ADMIN_NETWORK"]["dhcp_pool_end"]) new_range = network.range( responses["ADMIN_NETWORK/dhcp_pool_start"], responses["ADMIN_NETWORK/dhcp_pool_end"]) if old_range[0] not in new_range: errors.append("DHCP range must contain previous values.") if old_range[-1] not in new_range: errors.append("DHCP range can only be increased after " "deployment.") if len(errors) > 0: log.error("Errors: %s %s" % (len(errors), errors)) ModuleHelper.display_failed_check_dialog(self, errors) return False else: self.parent.footer.set_text("No errors found.") return responses
def main(self): text_header = (u"Fuel %s setup " u"Use Up/Down/Left/Right to navigate. F8 exits. " u"Remember to save your changes." % self.version) text_footer = (u"Status messages go here.") # Top and bottom lines of frame self.header = urwid.AttrWrap(urwid.Text(text_header), 'header') self.footer = urwid.AttrWrap(urwid.Text(text_footer), 'footer') self.children = [] for clsobj in modules.__all__: modobj = clsobj(self) self.children.append(modobj) self.choices = [m.name for m in self.children] if len(self.children) == 0: sys.exit(1) # Build list of choices excluding visible self.visiblechoices = [] for child, choice in zip(self.children, self.choices): if child.visible: self.visiblechoices.append(choice) self.menuitems = self.menu(u'Menu', self.visiblechoices) menufill = urwid.Filler(self.menuitems, 'top', 40) self.menubox = urwid.BoxAdapter(menufill, 40) self.child = self.children[0] self.childpage = self.child.screenUI() self.childfill = urwid.Filler(self.childpage, 'top', 22) self.childbox = urwid.BoxAdapter(self.childfill, 22) self.cols = urwid.Columns( [ ('fixed', 20, urwid.Pile([ urwid.AttrMap(self.menubox, 'body'), urwid.Divider(" ")])), ('weight', 3, urwid.Pile([ urwid.Divider(" "), self.childbox, urwid.Divider(" ")])) ], 1) self.listwalker = urwid.SimpleListWalker([self.cols]) # self.listwalker = urwid.TreeWalker([self.cols]) self.listbox = urwid.ListBox(self.listwalker) # listbox = urwid.ListBox(urwid.SimpleListWalker(listbox_content)) self.frame = urwid.Frame(urwid.AttrWrap(self.listbox, 'body'), header=self.header, footer=self.footer) palette = \ [ ('body', 'black', 'light gray', 'standout'), ('header', 'light red', 'light gray', 'bold'), ('footer', 'light red', 'light gray', 'bold'), ('menu', 'black', 'light gray', 'bold'), ('menuf', 'white', 'dark red', 'bold'), ('important', 'light red', 'light gray', ('standout', 'underline')), ('editlbl', 'black', 'light gray'), ('editfc', 'light gray', 'black', 'bold'), ('editbx', 'light gray', 'dark gray'), ('buttn', 'white', 'dark green', 'bold'), ('buttnf', 'light gray', 'dark green', 'bold'), ] # use appropriate Screen class if urwid.web_display.is_web_request(): self.screen = urwid.web_display.Screen() else: self.screen = urwid.raw_display.Screen() def unhandled(key): if key == 'f8': raise urwid.ExitMainLoop() if key == 'shift tab': self.child.walker.tab_prev() if key == 'tab': self.child.walker.tab_next() self.mainloop = urwid.MainLoop(self.frame, palette, self.screen, unhandled_input=unhandled) # Initialize each module completely before any events are handled for child in reversed(self.children): self.setChildScreen(name=child.name) signal.signal(signal.SIGUSR1, self.sigusr1_handler) msg = "It is recommended to change default administrator password." dialog.display_dialog(self.child, widget.TextLabel(msg), "WARNING!") run_delegate = self._save_only if self.save_only else self.mainloop.run run_delegate()
def check(self, args): """Validate that all fields have valid values through sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() #Get field information responses = dict() for index, fieldname in enumerate(fields): if fieldname == "blank": pass else: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] #hostname must be under 60 chars if len(responses["HOSTNAME"]) >= 60: errors.append("Hostname must be under 60 chars.") #hostname must not be empty if len(responses["HOSTNAME"]) == 0: errors.append("Hostname must not be empty.") #hostname needs to have valid chars if re.search('[^a-z0-9-]', responses["HOSTNAME"]): errors.append( "Hostname must contain only alphanumeric and hyphen.") #domain must be under 180 chars if len(responses["DNS_DOMAIN"]) >= 180: errors.append("Domain must be under 180 chars.") #domain must not be empty if len(responses["DNS_DOMAIN"]) == 0: errors.append("Domain must not be empty.") #domain needs to have valid chars if re.match('[^a-z0-9-.]', responses["DNS_DOMAIN"]): errors.append( "Domain must contain only alphanumeric, period and hyphen.") #ensure external DNS is valid if len(responses["DNS_UPSTREAM"]) == 0: #We will allow empty if user doesn't need external networking #and present a strongly worded warning msg = "If you continue without DNS, you may not be able to access"\ + " external data necessary for installation needed for " \ + "some OpenStack Releases." dialog.display_dialog( self, widget.TextLabel(msg), "Empty DNS Warning") else: #external DNS must contain only numbers, periods, and commas #Needs more serious ip address checking if re.match('[^0-9.,]', responses["DNS_UPSTREAM"]): errors.append( "External DNS must contain only IP addresses and commas.") #ensure test DNS name isn't empty if len(responses["TEST_DNS"]) == 0: errors.append("Test DNS must not be empty.") #Validate first IP address try: if netaddr.valid_ipv4(responses["DNS_UPSTREAM"].split(",")[0]): DNS_UPSTREAM = responses["DNS_UPSTREAM"].split(",")[0] else: errors.append("Not a valid IP address for External DNS: %s" % responses["DNS_UPSTREAM"]) #Try to resolve with first address if not self.checkDNS(DNS_UPSTREAM): #Warn user that DNS resolution failed, but continue msg = "Unable to resolve %s.\n\n" % responses['TEST_DNS']\ + "Possible causes for DNS failure include:\n"\ + "* Invalid DNS server\n"\ + "* Invalid gateway\n"\ + "* Other networking issue\n\n"\ + "Fuel Setup can save this configuration, but "\ + "you may want to correct your settings." dialog.display_dialog(self, widget.TextLabel(msg), "DNS Failure Warning") self.parent.refreshScreen() except Exception: errors.append("Not a valid IP address for External DNS: %s" % responses["DNS_UPSTREAM"]) if len(errors) > 0: self.parent.footer.set_text("Error: %s" % (errors[0])) log.error("Errors: %s %s" % (len(errors), errors)) return False else: self.parent.footer.set_text("No errors found.") return responses
def check(self, args): """Validates all fields have valid values and some sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() #Refresh networking to make sure IP matches self.getNetwork() #Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname != "blank" and "label" not in fieldname: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] #Set internal_{ipaddress,netmask,interface} responses["ADMIN_NETWORK/interface"] = self.activeiface responses["ADMIN_NETWORK/netmask"] = self.netsettings[ self.activeiface]["netmask"] responses["ADMIN_NETWORK/mac"] = self.netsettings[ self.activeiface]["mac"] responses["ADMIN_NETWORK/ipaddress"] = self.netsettings[ self.activeiface]["addr"] #ensure management interface is valid if responses["ADMIN_NETWORK/interface"] not in self.netsettings.keys(): errors.append("Management interface not valid") else: self.parent.footer.set_text("Scanning for DHCP servers. \ Please wait...") self.parent.refreshScreen() ###Start DHCP check on this interface #dhcp_server_data=[{'server_id': '192.168.200.2', 'iface': 'eth2', # 'yiaddr': '192.168.200.15', 'mac': # '52:54:00:12:35:02', 'server_ip': '192.168.200.2', # 'dport': 67, 'message': 'offer', # 'gateway': '0.0.0.0'}] try: dhcptimeout = 5 default = [] with timeout.run_with_timeout(dhcp_checker.utils.IfaceState, [self.activeiface], timeout=dhcptimeout) as iface: dhcp_server_data = timeout.run_with_timeout( dhcp_checker.api.check_dhcp_on_eth, [iface, dhcptimeout], timeout=dhcptimeout, default=default) except (KeyboardInterrupt, timeout.TimeoutError): log.debug("DHCP scan timed out") log.warning(traceback.format_exc()) dhcp_server_data = default 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)) #Build dialog elements dhcp_info = [] dhcp_info.append(urwid.Padding( urwid.Text(("header", "!!! WARNING !!!")), "center")) dhcp_info.append(widget.TextLabel("You have selected an \ interface that contains one or more DHCP servers. This will impact \ provisioning. You should disable these DHCP servers before you continue, or \ else deployment will likely fail.")) dhcp_info.append(widget.TextLabel("")) for index, dhcp_server in enumerate(dhcp_server_data): dhcp_info.append(widget.TextLabel("DHCP Server #%s:" % (index + 1))) dhcp_info.append(widget.TextLabel("IP address: %-10s" % dhcp_server['server_ip'])) dhcp_info.append(widget.TextLabel("MAC address: %-10s" % dhcp_server['mac'])) dhcp_info.append(widget.TextLabel("")) dialog.display_dialog(self, urwid.Pile(dhcp_info), "DHCP Servers Found on %s" % self.activeiface) ###Ensure pool start and end are on the same subnet as mgmt_if #Ensure mgmt_if has an IP first if len(self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["addr"]) == 0: errors.append("Go to Interfaces to configure management \ interface first.") else: #Ensure ADMIN_NETWORK/interface is not running DHCP if self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["bootproto"] == "dhcp": errors.append("%s is running DHCP. Change it to static " "first." % self.activeiface) #Ensure DHCP Pool Start and DHCP Pool are valid IPs try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_pool_start"]): dhcp_start = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_pool_start"]) if not dhcp_start: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Pool Start") try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_gateway"]): dhcp_gateway = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_gateway"]) if not dhcp_gateway: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Gateway") try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_pool_end"]): dhcp_end = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_pool_end"]) if not dhcp_end: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Pool end") #Ensure pool start and end are in the same subnet of each other netmask = self.netsettings[responses[ "ADMIN_NETWORK/interface" ]]["netmask"] if not network.inSameSubnet( responses["ADMIN_NETWORK/dhcp_pool_start"], responses["ADMIN_NETWORK/dhcp_pool_end"], netmask): errors.append("DHCP Pool start and end are not in the " "same subnet.") #Ensure pool start and end are in the right netmask mgmt_if_ipaddr = self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["addr"] if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_pool_start"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Pool start does not match management" " network.") if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_pool_end"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Pool end does not match management " "network.") if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_gateway"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Gateway does not match management " "network.") self.parent.footer.set_text("Scanning for duplicate IP address" "es. Please wait...") if network.duplicateIPExists(mgmt_if_ipaddr, self.activeiface): errors.append("Duplicate host found with IP {0}.".format( mgmt_if_ipaddr)) if len(errors) > 0: self.parent.footer.set_text("Error: %s" % (errors[0])) log.error("Errors: %s %s" % (len(errors), errors)) return False else: self.parent.footer.set_text("No errors found.") return responses
def check(self, args): """Validates all fields have valid values and some sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() # Refresh networking to make sure IP matches self.getNetwork() # Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname != "blank" and "label" not in fieldname: responses[fieldname] = self.edits[index].get_edit_text() # Validate each field errors = [] # Set internal_{ipaddress,netmask,interface} responses["ADMIN_NETWORK/interface"] = self.activeiface responses["ADMIN_NETWORK/netmask"] = self.netsettings[ self.activeiface]["netmask"] responses["ADMIN_NETWORK/mac"] = self.netsettings[ self.activeiface]["mac"] responses["ADMIN_NETWORK/ipaddress"] = self.netsettings[ self.activeiface]["addr"] # ensure management interface is valid if responses["ADMIN_NETWORK/interface"] not in self.netsettings.keys(): errors.append("Management interface not valid") else: self.parent.footer.set_text("Scanning for DHCP servers. \ Please wait...") self.parent.refreshScreen() try: dhcptimeout = 5 dhcp_server_data = network.search_external_dhcp( self.activeiface, dhcptimeout) except network.NetworkException: log.warning('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)) # Build dialog elements dhcp_info = [] dhcp_info.append( urwid.Padding(urwid.Text(("header", "!!! WARNING !!!")), "center")) dhcp_info.append( widget.TextLabel("You have selected an \ interface that contains one or more DHCP servers. This will impact \ provisioning. You should disable these DHCP servers before you continue, or \ else deployment will likely fail.")) dhcp_info.append(widget.TextLabel("")) for index, dhcp_server in enumerate(dhcp_server_data): dhcp_info.append( widget.TextLabel("DHCP Server #%s:" % (index + 1))) dhcp_info.append( widget.TextLabel("IP address: %-10s" % dhcp_server['server_ip'])) dhcp_info.append( widget.TextLabel("MAC address: %-10s" % dhcp_server['mac'])) dhcp_info.append(widget.TextLabel("")) dialog.display_dialog( self, urwid.Pile(dhcp_info), "DHCP Servers Found on %s" % self.activeiface) # Ensure pool start and end are on the same subnet as mgmt_if # Ensure mgmt_if has an IP first if len(self.netsettings[responses["ADMIN_NETWORK/interface"]] ["addr"]) == 0: errors.append("Go to Interfaces to configure management \ interface first.") else: # Ensure ADMIN_NETWORK/interface is not running DHCP if self.netsettings[responses["ADMIN_NETWORK/interface"]][ "bootproto"] == "dhcp": errors.append("%s is running DHCP. Change it to static " "first." % self.activeiface) # Ensure DHCP Pool Start and DHCP Pool are valid IPs try: if netaddr.valid_ipv4( responses["ADMIN_NETWORK/dhcp_pool_start"]): dhcp_start = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_pool_start"]) if not dhcp_start: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Pool Start") try: if netaddr.valid_ipv4( responses["ADMIN_NETWORK/dhcp_gateway"]): dhcp_gateway = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_gateway"]) if not dhcp_gateway: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Gateway") try: if netaddr.valid_ipv4( responses["ADMIN_NETWORK/dhcp_pool_end"]): dhcp_end = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_pool_end"]) if not dhcp_end: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Pool end") # Ensure pool start and end are in the same # subnet of each other netmask = self.netsettings[ responses["ADMIN_NETWORK/interface"]]["netmask"] if not network.inSameSubnet( responses["ADMIN_NETWORK/dhcp_pool_start"], responses["ADMIN_NETWORK/dhcp_pool_end"], netmask): errors.append("DHCP Pool start and end are not in the " "same subnet.") # Ensure pool start and end are in the right netmask mgmt_if_ipaddr = self.netsettings[ responses["ADMIN_NETWORK/interface"]]["addr"] if network.inSameSubnet( responses["ADMIN_NETWORK/dhcp_pool_start"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Pool start does not match management" " network.") if network.inSameSubnet( responses["ADMIN_NETWORK/dhcp_pool_end"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Pool end does not match management " "network.") if network.inSameSubnet( responses["ADMIN_NETWORK/dhcp_gateway"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Gateway does not match management " "network.") self.parent.footer.set_text("Scanning for duplicate IP address" "es. Please wait...") # Bind arping to mgmt_if_ipaddr if it assigned assigned_ips = [ v.get('addr') for v in self.netsettings.itervalues() ] arping_bind = mgmt_if_ipaddr in assigned_ips if network.duplicateIPExists(mgmt_if_ipaddr, self.activeiface, arping_bind): errors.append("Duplicate host found with IP {0}.".format( mgmt_if_ipaddr)) # Extra checks for post-deployment changes if utils.is_post_deployment(): settings = self.parent.settings # Admin interface cannot change if self.activeiface != settings["ADMIN_NETWORK"]["interface"]: errors.append("Cannot change admin interface after deployment") # PXE network range must contain previous PXE network range old_range = network.range( settings["ADMIN_NETWORK"]["dhcp_pool_start"], settings["ADMIN_NETWORK"]["dhcp_pool_end"]) new_range = network.range( responses["ADMIN_NETWORK/dhcp_pool_start"], responses["ADMIN_NETWORK/dhcp_pool_end"]) if old_range[0] not in new_range: errors.append("DHCP range must contain previous values.") if old_range[-1] not in new_range: errors.append("DHCP range can only be increased after " "deployment.") if len(errors) > 0: log.error("Errors: %s %s" % (len(errors), errors)) ModuleHelper.display_failed_check_dialog(self, errors) return False else: self.parent.footer.set_text("No errors found.") return responses
def check(self, args): """Validate that all fields have valid values through sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() # Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname == "blank": pass else: responses[fieldname] = self.edits[index].get_edit_text() if self.parent.save_only: return responses # Validate each field errors = [] # hostname must be under 60 chars if len(responses["HOSTNAME"]) >= 60: errors.append("Hostname must be under 60 chars.") # hostname must not be empty if len(responses["HOSTNAME"]) == 0: errors.append("Hostname must not be empty.") # hostname needs to have valid chars if re.search('[^a-z0-9-]', responses["HOSTNAME"]): errors.append( "Hostname must contain only alphanumeric and hyphen.") # domain must be under 180 chars if len(responses["DNS_DOMAIN"]) >= 180: errors.append("Domain must be under 180 chars.") # domain must not be empty if len(responses["DNS_DOMAIN"]) == 0: errors.append("Domain must not be empty.") # domain needs to have valid chars if re.match('[^a-z0-9-.]', responses["DNS_DOMAIN"]): errors.append( "Domain must contain only alphanumeric, period and hyphen.") # ensure external DNS is valid if len(responses["DNS_UPSTREAM"]) == 0: # We will allow empty if user doesn't need external networking # and present a strongly worded warning msg = "If you continue without DNS, you may not be able to access"\ + " external data necessary for installation needed for " \ + "some OpenStack Releases." dialog.display_dialog(self, widget.TextLabel(msg), "Empty DNS Warning") else: upstream_nameservers = responses["DNS_UPSTREAM"].split(',') # external DNS must contain only numbers, periods, and commas # Needs more serious ip address checking if re.match('[^0-9.,]', responses["DNS_UPSTREAM"]): errors.append( "External DNS must contain only IP addresses and commas.") # Ensure local IPs are not in upstream list host_ips = network.list_host_ip_addresses() for nameserver in upstream_nameservers: if nameserver in host_ips: errors.append("Host IPs cannot be in upstream DNS.") break if len(upstream_nameservers) > 3: errors.append( "Unable to specify more than 3 External DNS addresses.") # ensure test DNS name isn't empty if len(responses["TEST_DNS"]) == 0: errors.append("Test DNS must not be empty.") # Validate first IP address for nameserver in upstream_nameservers: if not netaddr.valid_ipv4(nameserver): errors.append("Not a valid IP address for DNS server:" " {0}".format(nameserver)) # Try to resolve with first address if not self.checkDNS(upstream_nameservers[0]): # Warn user that DNS resolution failed, but continue msg = "Unable to resolve %s.\n\n" % responses['TEST_DNS']\ + "Possible causes for DNS failure include:\n"\ + "* Invalid DNS server\n"\ + "* Invalid gateway\n"\ + "* Other networking issue\n\n"\ + "Fuel Setup can save this configuration, but "\ + "you may want to correct your settings." dialog.display_dialog(self, widget.TextLabel(msg), "DNS Failure Warning") self.parent.refreshScreen() if len(errors) > 0: log.error("Errors: %s %s" % (len(errors), errors)) modulehelper.ModuleHelper.display_failed_check_dialog(self, errors) return False else: self.parent.footer.set_text("No errors found.") return responses
def check(self, args): """Validate that all fields have valid values and sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() # Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname == "blank": pass elif fieldname == "ntpenabled": rb_group = self.edits[index].rb_group if rb_group[0].state: responses["ntpenabled"] = "Yes" else: responses["ntpenabled"] = "No" else: responses[fieldname] = self.edits[index].get_edit_text() # Validate each field errors = [] warnings = [] if responses['ntpenabled'] == "No": # 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. responses = { 'NTP1': "", 'NTP2': "", 'NTP3': ""} 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: errors.append("%s must be under 255 chars." % self.defaults[ntpfield]['label']) # NTP needs to have valid chars if re.search('[^a-zA-Z0-9-.]', ntpvalue): errors.append("%s contains illegal characters." % self.defaults[ntpfield]['label']) # ensure external NTP is valid if len(ntpvalue) > 0: # Validate first NTP address try: # Try to test NTP via ntpdate if not self.checkNTP(ntpvalue): warnings.append("%s unable to perform NTP." % self.defaults[ntpfield]['label']) except Exception: warnings.append("%s unable to sync time with server.: %s" % self.defaults[ntpfield]['label']) if len(errors) > 0: log.error("Errors: %s %s" % (len(errors), errors)) ModuleHelper.display_failed_check_dialog(self, errors) return False else: if len(warnings) > 0: msg = ["NTP configuration has the following warnings:"] msg.extend(warnings) msg.append("You may see errors during provisioning and " "in system logs. NTP errors are not fatal.") warning_msg = '\n'.join(str(line) for line in msg) dialog.display_dialog(self, widget.TextLabel(warning_msg), "NTP Warnings") log.warning(warning_msg) self.parent.footer.set_text("No errors found.") log.info("No errors found") return responses
def main(self): text_header = (u"Fuel %s setup " u"Use Up/Down/Left/Right to navigate. F8 exits. " u"Remember to save your changes." % self.version) text_footer = (u"Status messages go here.") # Top and bottom lines of frame self.header = urwid.AttrWrap(urwid.Text(text_header), 'header') self.footer = urwid.AttrWrap(urwid.Text(text_footer), 'footer') self.children = [] for clsobj in modules.__all__: modobj = clsobj(self) self.children.append(modobj) self.choices = [m.name for m in self.children] if len(self.children) == 0: sys.exit(1) # Build list of choices excluding visible self.visiblechoices = [] for child, choice in zip(self.children, self.choices): if child.visible: self.visiblechoices.append(choice) self.menuitems = self.menu(u'Menu', self.visiblechoices) menufill = urwid.Filler(self.menuitems, 'top', 40) self.menubox = urwid.BoxAdapter(menufill, 40) self.child = self.children[0] self.childpage = self.child.screenUI() self.childfill = urwid.Filler(self.childpage, 'top', 22) self.childbox = urwid.BoxAdapter(self.childfill, 22) self.cols = urwid.Columns( [ ('fixed', 20, urwid.Pile([ urwid.AttrMap(self.menubox, 'body'), urwid.Divider(" ")])), ('weight', 3, urwid.Pile([ urwid.Divider(" "), self.childbox, urwid.Divider(" ")])) ], 1) self.listwalker = urwid.SimpleListWalker([self.cols]) # self.listwalker = urwid.TreeWalker([self.cols]) self.listbox = urwid.ListBox(self.listwalker) # listbox = urwid.ListBox(urwid.SimpleListWalker(listbox_content)) self.frame = urwid.Frame(urwid.AttrWrap(self.listbox, 'body'), header=self.header, footer=self.footer) palette = \ [ ('body', 'black', 'light gray', 'standout'), ('header', 'light red', 'light gray', 'bold'), ('footer', 'light red', 'light gray', 'bold'), ('menu', 'black', 'light gray', 'bold'), ('menuf', 'white', 'dark red', 'bold'), ('important', 'light red', 'light gray', ('standout', 'underline')), ('editlbl', 'black', 'light gray'), ('editfc', 'light gray', 'black', 'bold'), ('editbx', 'light gray', 'dark gray'), ('buttn', 'white', 'dark green', 'bold'), ('buttnf', 'light gray', 'dark green', 'bold'), ] # use appropriate Screen class if urwid.web_display.is_web_request(): self.screen = urwid.web_display.Screen() else: self.screen = urwid.raw_display.Screen() def unhandled(key): if key == 'f8': raise urwid.ExitMainLoop() if key == 'shift tab': self.child.walker.tab_prev() if key == 'tab': self.child.walker.tab_next() self.mainloop = urwid.MainLoop(self.frame, palette, self.screen, unhandled_input=unhandled) # Initialize each module completely before any events are handled for child in reversed(self.children): self.setChildScreen(name=child.name) signal.signal(signal.SIGUSR1, self.handle_sigusr1) dialog.display_dialog( self.child, widget.TextLabel("It is highly recommended to change default " "admin password."), "WARNING!") if not self.save_only: self.mainloop.run() else: self._save_only()
def check(self, args): """Validate that all fields have valid values and sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() #Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname == "blank": pass elif fieldname == "ntpenabled": rb_group = self.edits[index].rb_group if rb_group[0].state: responses["ntpenabled"] = "Yes" else: responses["ntpenabled"] = "No" else: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] warnings = [] if responses['ntpenabled'] == "No": #Disabled NTP means passing no NTP servers to save method responses = { 'NTP1': "", 'NTP2': "", 'NTP3': ""} 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: errors.append("%s must be under 255 chars." % self.defaults[ntpfield]['label']) #NTP needs to have valid chars if re.search('[^a-zA-Z0-9-.]', ntpvalue): errors.append("%s contains illegal characters." % self.defaults[ntpfield]['label']) #ensure external NTP is valid if len(ntpvalue) > 0: #Validate first NTP address try: #Try to test NTP via ntpdate if not self.checkNTP(ntpvalue): warnings.append("%s unable to perform NTP." % self.defaults[ntpfield]['label']) except Exception: warnings.append("%s unable to sync time with server.: %s" % self.defaults[ntpfield]['label']) if len(errors) > 0: self.parent.footer.set_text( "Errors: %s First error: %s" % (len(errors), errors[0])) log.error("Errors: %s %s" % (len(errors), errors)) return False else: if len(warnings) > 0: msg = ["NTP configuration has the following warnings:"] msg.extend(warnings) msg.append("You may see errors during provisioning and " "in system logs. NTP errors are not fatal.") warning_msg = '\n'.join(str(line) for line in msg) dialog.display_dialog(self, widget.TextLabel(warning_msg), "NTP Warnings") log.warning(warning_msg) self.parent.footer.set_text("No errors found.") log.info("No errors found") return responses
def check(self, args): """Validate that all fields have valid values and sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() # Get field information responses = dict() ntp_enabled = False for index, fieldname in enumerate(self.fields): if fieldname == "blank": pass elif fieldname == "ntpenabled": rb_group = self.edits[index].rb_group if rb_group[0].state: 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 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. responses = {'NTP1': "", 'NTP2': "", 'NTP3': ""} self.parent.footer.set_text("No errors found.") log.info("No errors found") return responses for ntpfield, ntpvalue in responses.iteritems(): # NTP must be under 255 chars if len(ntpvalue) >= 255: errors.append("%s must be under 255 chars." % self.defaults[ntpfield]['label']) # NTP needs to have valid chars if re.search('[^a-zA-Z0-9-.]', ntpvalue): errors.append("%s contains illegal characters." % self.defaults[ntpfield]['label']) # ensure external NTP is valid if len(ntpvalue) > 0: # Validate first NTP address try: # Try to test NTP via ntpdate if not self.checkNTP(ntpvalue): warnings.append("%s unable to perform NTP." % self.defaults[ntpfield]['label']) except Exception: warnings.append("%s unable to sync time with server.: %s" % self.defaults[ntpfield]['label']) if len(errors) > 0: log.error("Errors: %s %s" % (len(errors), errors)) modulehelper.ModuleHelper.display_failed_check_dialog(self, errors) return False else: if len(warnings) > 0: msg = ["NTP configuration has the following warnings:"] msg.extend(warnings) msg.append("You may see errors during provisioning and " "in system logs. NTP errors are not fatal.") warning_msg = '\n'.join(str(line) for line in msg) dialog.display_dialog(self, widget.TextLabel(warning_msg), "NTP Warnings") log.warning(warning_msg) self.parent.footer.set_text("No errors found.") log.info("No errors found") return responses
def check(self, args): """Validate that all fields have valid values and sanity checks.""" #Get field information responses = dict() self.parent.footer.set_text("Checking data...") for index, fieldname in enumerate(fields): if fieldname == "blank" or fieldname == "ifname": pass elif fieldname == "bootproto": rb_group = self.edits[index].rb_group if rb_group[0].state: responses["bootproto"] = "dhcp" else: responses["bootproto"] = "none" elif fieldname == "onboot": rb_group = self.edits[index].rb_group if rb_group[0].state: responses["onboot"] = "yes" else: responses["onboot"] = "no" else: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] if responses["onboot"] == "no": numactiveifaces = 0 for iface in self.netsettings: if self.netsettings[iface]['addr'] != "": numactiveifaces += 1 if numactiveifaces < 2 and \ self.netsettings[self.activeiface]['addr'] != "": #Block user because puppet l23network fails if all intefaces #are disabled. errors.append("Cannot disable all interfaces.") elif responses["bootproto"] == "dhcp": self.parent.footer.set_text("Scanning for DHCP servers. " "Please wait...") self.parent.refreshScreen() try: dhcptimeout = 5 with timeout.run_with_timeout(dhcp_checker.utils.IfaceState, [self.activeiface], timeout=dhcptimeout) as iface: dhcp_server_data = timeout.run_with_timeout( dhcp_checker.api.check_dhcp_on_eth, [iface, dhcptimeout], timeout=dhcptimeout) except (KeyboardInterrupt, timeout.TimeoutError): self.log.debug("DHCP scan timed out") self.log.warning(traceback.format_exc()) dhcp_server_data = [] except Exception: self.log.warning("dhcp_checker failed to check on %s" % self.activeiface) dhcp_server_data = [] responses["dhcp_nowait"] = False if len(dhcp_server_data) < 1: self.log.debug("No DHCP servers found. Warning user about " "dhcp_nowait.") #Build dialog elements dhcp_info = [] dhcp_info.append(urwid.Padding( urwid.Text(("header", "!!! WARNING !!!")), "center")) dhcp_info.append( widget.TextLabel( "Unable to detect DHCP server" + "on interface %s." % (self.activeiface) + "\nDHCP will be set up in the background, " + "but may not receive an IP address. You may " + "want to check your DHCP connection manually " + "using the Shell Login menu to the left.")) dialog.display_dialog(self, urwid.Pile(dhcp_info), "DHCP Servers Found on %s" % self.activeiface) self.parent.refreshScreen() responses["dhcp_nowait"] = True #Check ipaddr, netmask, gateway only if static elif responses["bootproto"] == "none": try: if netaddr.valid_ipv4(responses["ipaddr"]): if not netaddr.IPAddress(responses["ipaddr"]): raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except (BadIPException, Exception): errors.append("Not a valid IP address: %s" % responses["ipaddr"]) try: if netaddr.valid_ipv4(responses["netmask"]): netmask = netaddr.IPAddress(responses["netmask"]) if netmask.is_netmask is False: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except (BadIPException, Exception): errors.append("Not a valid netmask: %s" % responses["netmask"]) try: if len(responses["gateway"]) > 0: #Check if gateway is valid if netaddr.valid_ipv4(responses["gateway"]) is False: raise BadIPException("Gateway IP address is not valid") #Check if gateway is in same subnet if network.inSameSubnet(responses["ipaddr"], responses["gateway"], responses["netmask"]) is False: raise BadIPException("Gateway IP is not in same " "subnet as IP address") except (BadIPException, Exception) as e: errors.append(e) if len(errors) > 0: self.parent.footer.set_text("Error: %s" % (errors[0])) self.log.error("Errors: %s %s" % (len(errors), errors)) return False else: self.parent.footer.set_text("No errors found.") return responses
def check(self, args): """Validates all fields have valid values and some sanity checks.""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() #Refresh networking to make sure IP matches self.getNetwork() #Get field information responses = dict() for index, fieldname in enumerate(self.fields): if fieldname != "blank" and "label" not in fieldname: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] #Set internal_{ipaddress,netmask,interface} responses["ADMIN_NETWORK/interface"] = self.activeiface responses["ADMIN_NETWORK/netmask"] = self.netsettings[ self.activeiface]["netmask"] responses["ADMIN_NETWORK/mac"] = self.netsettings[ self.activeiface]["mac"] responses["ADMIN_NETWORK/ipaddress"] = self.netsettings[ self.activeiface]["addr"] #ensure management interface is valid if responses["ADMIN_NETWORK/interface"] not in self.netsettings.keys(): errors.append("Management interface not valid") else: self.parent.footer.set_text("Scanning for DHCP servers. \ Please wait...") self.parent.refreshScreen() ###Start DHCP check on this interface #dhcp_server_data=[{'server_id': '192.168.200.2', 'iface': 'eth2', # 'yiaddr': '192.168.200.15', 'mac': # '52:54:00:12:35:02', 'server_ip': '192.168.200.2', # 'dport': 67, 'message': 'offer', # 'gateway': '0.0.0.0'}] try: dhcptimeout = 5 default = [] with timeout.run_with_timeout(dhcp_checker.utils.IfaceState, [self.activeiface], timeout=dhcptimeout) as iface: dhcp_server_data = timeout.run_with_timeout( dhcp_checker.api.check_dhcp_on_eth, [iface, dhcptimeout], timeout=dhcptimeout, default=default) except (KeyboardInterrupt, timeout.TimeoutError): log.debug("DHCP scan timed out") log.warning(traceback.format_exc()) dhcp_server_data = default 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)) #Build dialog elements dhcp_info = [] dhcp_info.append(urwid.Padding( urwid.Text(("header", "!!! WARNING !!!")), "center")) dhcp_info.append(widget.TextLabel("You have selected an \ interface that contains one or more DHCP servers. This will impact \ provisioning. You should disable these DHCP servers before you continue, or \ else deployment will likely fail.")) dhcp_info.append(widget.TextLabel("")) for index, dhcp_server in enumerate(dhcp_server_data): dhcp_info.append(widget.TextLabel("DHCP Server #%s:" % (index + 1))) dhcp_info.append(widget.TextLabel("IP address: %-10s" % dhcp_server['server_ip'])) dhcp_info.append(widget.TextLabel("MAC address: %-10s" % dhcp_server['mac'])) dhcp_info.append(widget.TextLabel("")) dialog.display_dialog(self, urwid.Pile(dhcp_info), "DHCP Servers Found on %s" % self.activeiface) ###Ensure pool start and end are on the same subnet as mgmt_if #Ensure mgmt_if has an IP first if len(self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["addr"]) == 0: errors.append("Go to Interfaces to configure management \ interface first.") else: #Ensure ADMIN_NETWORK/interface is not running DHCP if self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["bootproto"] == "dhcp": errors.append("%s is running DHCP. Change it to static " "first." % self.activeiface) #Ensure DHCP Pool Start and DHCP Pool are valid IPs try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_pool_start"]): dhcp_start = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_pool_start"]) if not dhcp_start: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Pool Start") try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_gateway"]): dhcp_gateway = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_gateway"]) if not dhcp_gateway: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Gateway") try: if netaddr.valid_ipv4(responses[ "ADMIN_NETWORK/dhcp_pool_end"]): dhcp_end = netaddr.IPAddress( responses["ADMIN_NETWORK/dhcp_pool_end"]) if not dhcp_end: raise BadIPException("Not a valid IP address") else: raise BadIPException("Not a valid IP address") except Exception: errors.append("Invalid IP address for DHCP Pool end") #Ensure pool start and end are in the same subnet of each other netmask = self.netsettings[responses[ "ADMIN_NETWORK/interface" ]]["netmask"] if not network.inSameSubnet( responses["ADMIN_NETWORK/dhcp_pool_start"], responses["ADMIN_NETWORK/dhcp_pool_end"], netmask): errors.append("DHCP Pool start and end are not in the " "same subnet.") #Ensure pool start and end are in the right netmask mgmt_if_ipaddr = self.netsettings[responses[ "ADMIN_NETWORK/interface"]]["addr"] if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_pool_start"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Pool start does not match management" " network.") if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_pool_end"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Pool end does not match management " "network.") if network.inSameSubnet(responses[ "ADMIN_NETWORK/dhcp_gateway"], mgmt_if_ipaddr, netmask) is False: errors.append("DHCP Gateway does not match management " "network.") self.parent.footer.set_text("Scanning for duplicate IP address" "es. Please wait...") # Bind arping to mgmt_if_ipaddr if it assigned assigned_ips = [v.get('addr') for v in self.netsettings.itervalues()] arping_bind = mgmt_if_ipaddr in assigned_ips if network.duplicateIPExists(mgmt_if_ipaddr, self.activeiface, arping_bind): errors.append("Duplicate host found with IP {0}.".format( mgmt_if_ipaddr)) if len(errors) > 0: self.parent.footer.set_text("Error: %s" % (errors[0])) log.error("Errors: %s %s" % (len(errors), errors)) return False else: self.parent.footer.set_text("No errors found.") return responses
def check(self, args): """Validate that all fields have valid values and some sanity checks""" self.parent.footer.set_text("Checking data...") self.parent.refreshScreen() #Get field information responses = dict() for index, fieldname in enumerate(fields): if fieldname == "blank": pass else: responses[fieldname] = self.edits[index].get_edit_text() ###Validate each field errors = [] #hostname must be under 60 chars if len(responses["HOSTNAME"]) >= 60: errors.append("Hostname must be under 60 chars.") #hostname must not be empty if len(responses["HOSTNAME"]) == 0: errors.append("Hostname must not be empty.") #hostname needs to have valid chars if re.search('[^a-z0-9-]', responses["HOSTNAME"]): errors.append( "Hostname must contain only alphanumeric and hyphen.") #domain must be under 180 chars if len(responses["DNS_DOMAIN"]) >= 180: errors.append("Domain must be under 180 chars.") #domain must not be empty if len(responses["DNS_DOMAIN"]) == 0: errors.append("Domain must not be empty.") #domain needs to have valid chars if re.match('[^a-z0-9-.]', responses["DNS_DOMAIN"]): errors.append( "Domain must contain only alphanumeric, period and hyphen.") #ensure external DNS is valid if len(responses["DNS_UPSTREAM"]) == 0: #We will allow empty if user doesn't need external networking #and present a strongly worded warning msg = "If you continue without DNS, you may not be able to access"\ + " external data necessary for installation needed for " \ + "some OpenStack Releases." diag = dialog.display_dialog(self, TextLabel(msg), "Empty DNS Warning") else: #external DNS must contain only numbers, periods, and commas #TODO: More serious ip address checking if re.match('[^0-9.,]', responses["DNS_UPSTREAM"]): errors.append( "External DNS must contain only IP addresses and commas.") #ensure test DNS name isn't empty if len(responses["TEST_DNS"]) == 0: errors.append("Test DNS must not be empty.") #Validate first IP address try: if netaddr.valid_ipv4(responses["DNS_UPSTREAM"].split(",")[0]): DNS_UPSTREAM = responses["DNS_UPSTREAM"].split(",")[0] else: errors.append( "Not a valid IP address for External DNS: %s" % responses["DNS_UPSTREAM"]) #Try to resolve with first address if not self.checkDNS(DNS_UPSTREAM): #Warn user that DNS resolution failed, but continue msg = "Unable to resolve %s.\n\n" % responses['TEST_DNS']\ + "Possible causes for DNS failure include:\n"\ + "* Invalid DNS server\n"\ + "* Invalid gateway\n"\ + "* Other networking issue\n\n"\ + "Fuel Setup can save this configuration, but "\ + "you may want to correct your settings." diag = dialog.display_dialog(self, TextLabel(msg), "DNS Failure Warning") self.parent.refreshScreen() except Exception, e: errors.append("Not a valid IP address for External DNS: %s" % responses["DNS_UPSTREAM"])