def _show(self): super(NSLDAPProxyBindInfo, self)._show() if self.nameservice.nameservice != 'LDAP': raise SkipException if self.nameservice.ldap_proxy_bind == \ NameServiceInfo.LDAP_CHOICE_NO_PROXY_BIND: raise SkipException y_loc = self._paint_opening() y_loc += 1 # blank line self.center_win.add_text(self.title, y_loc, INDENT) y_loc += 1 # edit field on following line since it should be big cols = self.win_size_x - INDENT - 2 area = WindowArea(1, cols, y_loc, INDENT + 2, scrollable_columns=MAXDNLEN + 1) self.ldap_pb_dn = EditField(area, window=self.center_win, text=self.nameservice.ldap_pb_dn, error_win=self.main_win.error_line) # in case of error, tell user what is being validated self.ldap_pb_dn.validate_kwargs['etext'] = _('distinguished name') y_loc += 2 # blank line titlelen = textwidth(self.title2) self.center_win.add_text(self.title2, y_loc, NameService.SCROLL_SIZE) cols = self.win_size_x - titlelen - INDENT - 1 area = WindowArea(1, cols, y_loc, titlelen + INDENT + 1) self.ldap_pb_psw = EditField(area, window=self.center_win, text=self.nameservice.ldap_pb_psw, error_win=self.main_win.error_line, masked=True) self.main_win.do_update() self.center_win.activate_object(self.ldap_pb_dn)
def _show(self): # This will be used (and re-used) later. It defines a subwindow's # location at 1, 1, with width 20 and height 1 win_area = WindowArea(y_loc=1, x_loc=1, lines=1, columns=20) # Creating an empty editable field is just as simple as creating # a list item: define a location, and a parent window. field_one = EditField(win_area, window=self.center_win) # Side trick - a WindowArea can be reused. In this case, the y-coord # is updated, and then win_area is used for the next EditField. win_area.y_loc = 2 # Setting default text for a field is also simple: field_two = EditField(win_area, window=self.center_win, text="default") # For the Text Installer and SCI tool, however, an extra step must # be taken. To help with labeling and highlighting, each EditField # should be wrapped in a ListItem, like so: win_area.y_loc = 3 list_three = ListItem(win_area, window=self.center_win, text="3: ") edit_area = WindowArea(y_loc=0, x_loc=5, lines=1, columns=10) field_three = EditField(edit_area, window=list_three) # Note that the 'window' parameter for field_three is 'list_three', # and that edit_area is a position relative to list_three. win_area.y_loc = 4 list_four = ListItem(win_area, window=self.center_win, text="4: ") # Since WindowAreas are relative to their parent, edit_area can # be reused with no modifications field_four = EditField(edit_area, window=list_four, text="default") # As with lists, edit fields must be explicitly given focus. Note that # focus can be given by index, or by reference. self.center_win.activate_object(field_two)
class NSNISIP(NameService): HEADER_TEXT = _("NIS Name Server Information") HELP_DATA = (SCI_HELP + "/%s/nis.txt", HEADER_TEXT) def __init__(self, main_win): super(NSNISIP, self).__init__(main_win) def _show(self): super(NSNISIP, self)._show() LOGGER.info("self.nameservice: %s" % self.nameservice) if self.nameservice.nameservice != 'NIS': raise SkipException if self.nameservice.nis_auto == NameServiceInfo.NIS_CHOICE_AUTO: raise SkipException if self.nameservice.dns: self.intro = \ _("Enter the host name or IP address of the name server. " "A host name must have at least 2 characters and can be " "alphanumeric and can contain hyphens. IP " "addresses must contain four sets of numbers separated " "by periods (for example, 129.200.9.1).") self.title = _("Server's host name or IP address:") else: self.intro = \ _("Enter the IP address of the name server. IP " "addresses must contain four sets of numbers separated " "by periods (for example, 129.200.9.1).") self.title = _("Server's IP address:") y_loc = self._paint_opening() self.center_win.add_text(self.title, y_loc, INDENT) aligned_x_loc = textwidth(self.title) + INDENT + 1 cols = self.win_size_x - aligned_x_loc area = WindowArea(1, cols, y_loc, aligned_x_loc) self.center_win.add_text(self.title, y_loc, INDENT) area = WindowArea(1, cols, y_loc, aligned_x_loc, scrollable_columns=NameService.HOSTNAME_SCREEN_LEN + 1) # create edit field, validating for host name or IP address depending # on whether DNS was selected self.nis_ip = EditField(area, window=self.center_win, text=self.nameservice.nis_ip, error_win=self.main_win.error_line, validate=(incremental_validate_host if self.nameservice.dns else incremental_validate_ip)) self.main_win.do_update() self.center_win.activate_object(self.nis_ip) def validate(self): nis_ip = self.nis_ip.get_text() if self.nameservice.dns: validate_host_or_ip(nis_ip) else: validate_ip(nis_ip) if not nis_ip: raise UIMessage(_("The NIS server IP address cannot be blank.")) def on_change_screen(self): self.nameservice.nis_ip = self.nis_ip.get_text()
class NSLDAPProxyBindInfo(NameService): HEADER_TEXT = _("Specify LDAP Profile Proxy Bind Information") HELP_DATA = (SCI_HELP + "/%s/ldap_proxy.txt", HEADER_TEXT) def __init__(self, main_win, screen=None): super(NSLDAPProxyBindInfo, self).__init__(main_win) self.intro = \ _("Specify the LDAP proxy bind distinguished name and the " "LDAP proxy bind password. The network administrator " "can provide this information.") self.title = _("Proxy bind distinguished name:") self.title2 = _("Proxy bind password:"******"The LDAP proxy server distinguished name cannot be blank.")) validate_ldap_proxy_bind_psw(self.ldap_pb_psw.get_text()) def on_change_screen(self): self.nameservice.ldap_pb_dn = self.ldap_pb_dn.get_text() self.nameservice.ldap_pb_psw = self.ldap_pb_psw.get_text()
def _show(self): super(NSDNSServer, self)._show() # check dictionary of screens associated with name service selections if not self.nameservice.dns: raise SkipException y_loc = self._paint_opening() self.dns_server_list = [] find_1st_nonblank = None find_last_nonblank = -1 for i in range(NameServiceInfo.MAXDNSSERV): self.center_win.add_text(self.title, y_loc, INDENT) area = WindowArea(1, MAXIP, y_loc, textwidth(self.title) + INDENT + 1) y_loc += 1 if i < len(self.nameservice.dns_server) and \ self.nameservice.dns_server[i] is not None: text = self.nameservice.dns_server[i] else: text = '' # find first blank field or last non-blank field if text: find_last_nonblank = i elif find_1st_nonblank is None: find_1st_nonblank = i self.dns_server_list += [EditField(area, window=self.center_win, text=text, validate=incremental_validate_ip, error_win=self.main_win.error_line)] self.main_win.do_update() # position cursor on first blank or after last field if find_1st_nonblank is None: idx = min(find_last_nonblank + 1, NameServiceInfo.MAXDNSSERV - 1) else: idx = find_1st_nonblank self.center_win.activate_object(self.dns_server_list[idx])
def _show(self): # The _show method will not only create the four desired EditFields, # but restore saved state as well. win_area = WindowArea(lines=1, columns=40, y_loc=1, x_loc=1) edit_area = WindowArea(lines=1, columns=20, y_loc=0, x_loc=10) for field_num in range(4): win_area.y_loc += 1 field_label = "%s: " % field_num list_item = ListItem(win_area, window=self.center_win, text=field_label) # Grab the saved text for the field (assume it's been saved for # now; *how* to go about saving it is below) field_text = self.saved_text[field_num] # And then set that as the text for the field edit_field = EditField(edit_area, window=list_item, text=field_text) # Save a reference to the field so other methods can access # their data: self.fields[field_num] = edit_field # Since this series of fields also acts as a selectable list, # the current selection can be restored as well by changing which # object is active: self.center_win.activate_object(self.current_selection)
def _show(self): super(NSNISIP, self)._show() LOGGER.info("self.nameservice: %s" % self.nameservice) if self.nameservice.nameservice != 'NIS': raise SkipException if self.nameservice.nis_auto == NameServiceInfo.NIS_CHOICE_AUTO: raise SkipException if self.nameservice.dns: self.intro = \ _("Enter the host name or IP address of the name server. " "A host name must have at least 2 characters and can be " "alphanumeric and can contain hyphens. IP " "addresses must contain four sets of numbers separated " "by periods (for example, 129.200.9.1).") self.title = _("Server's host name or IP address:") else: self.intro = \ _("Enter the IP address of the name server. IP " "addresses must contain four sets of numbers separated " "by periods (for example, 129.200.9.1).") self.title = _("Server's IP address:") y_loc = self._paint_opening() self.center_win.add_text(self.title, y_loc, INDENT) aligned_x_loc = textwidth(self.title) + INDENT + 1 cols = self.win_size_x - aligned_x_loc area = WindowArea(1, cols, y_loc, aligned_x_loc) self.center_win.add_text(self.title, y_loc, INDENT) area = WindowArea(1, cols, y_loc, aligned_x_loc, scrollable_columns=NameService.HOSTNAME_SCREEN_LEN + 1) # create edit field, validating for host name or IP address depending # on whether DNS was selected self.nis_ip = EditField( area, window=self.center_win, text=self.nameservice.nis_ip, error_win=self.main_win.error_line, validate=(incremental_validate_host if self.nameservice.dns else incremental_validate_ip)) self.main_win.do_update() self.center_win.activate_object(self.nis_ip)
def _show(self): ''' show domain ''' super(NSDomain, self)._show() if not _has_name_service(): raise SkipException if not self.nameservice.nameservice: raise SkipException y_loc = self._paint_opening() cols = min(MAXDOMAINLEN + 1, self.win_size_x - textwidth(self.title) - INDENT - 1) self.center_win.add_text(self.title, y_loc, INDENT) area = WindowArea(1, cols, y_loc, textwidth(self.title) + INDENT + 1, scrollable_columns=MAXDOMAINLEN + 1) self.domain = EditField(area, window=self.center_win, text=self.nameservice.domain, validate=incremental_validate_domain, error_win=self.main_win.error_line) self.main_win.do_update() self.center_win.activate_object(self.domain)
def create_list_item(self, next_part, win, list_area): '''Add an entry for next_part (a Partition or Slice) to the DiskWindow ''' list_item = ListItem(list_area, window=win, data_obj=next_part) list_item.key_dict.update(DiskWindow.ADD_KEYS) edit_field = EditField(self.edit_area, window=list_item, numeric_pad=" ", validate=decimal_valid, on_exit=on_exit_edit, error_win=self.error_win, add_obj=False, data_obj=next_part) edit_field.right_justify = True edit_field.validate_kwargs["disk_win"] = self edit_field.on_exit_kwargs["disk_win"] = self edit_field.key_dict.update(DiskWindow.ADD_KEYS) self.update_part(part_field=list_item) return list_item
def _show(self): super(NSLDAPProfile, self)._show() if self.nameservice.nameservice != 'LDAP': raise SkipException if self.nameservice.dns: self.intro = \ _("Specify the name of the LDAP profile to be used to " "configure this system and the host name or IP address of " "the server that contains the profile.") self.title2 = _("Profile server host name or IP address:") else: self.intro = \ _("Specify the name of the LDAP profile to be used to " "configure this system and the IP address of the " "server that contains the profile.") self.title2 = _("Profile server IP address:") self.intro += _(" Enter the LDAP search base.") y_loc = self._paint_opening() maxtitlelen = max(textwidth(self.title), textwidth(self.title2), textwidth(self.title3)) aligned_x_loc = maxtitlelen + INDENT + 1 cols = self.win_size_x - aligned_x_loc self.center_win.add_text(self.title.rjust(maxtitlelen), y_loc, INDENT) area = WindowArea(1, cols, y_loc, aligned_x_loc) self.ldap_profile = EditField(area, window=self.center_win, text=self.nameservice.ldap_profile, error_win=self.main_win.error_line, validate=inc_validate_nowhite_nospecial) # in case of error, tell user what is being validated self.ldap_profile.validate_kwargs['etext'] = _('profile name') y_loc += 1 area = WindowArea(1, cols, y_loc, aligned_x_loc, scrollable_columns=NameService.HOSTNAME_SCREEN_LEN + 1) self.center_win.add_text(self.title2.rjust(maxtitlelen), y_loc, INDENT) # create edit field, validating for host name or IP address depending # on whether DNS was selected self.ldap_ip = EditField(area, window=self.center_win, text=self.nameservice.ldap_ip, error_win=self.main_win.error_line, validate=(incremental_validate_host if self.nameservice.dns else incremental_validate_ip)) # search base y_loc += 1 self.center_win.add_text(self.title3.rjust(maxtitlelen), y_loc, INDENT) area = WindowArea(1, cols, y_loc, aligned_x_loc, scrollable_columns=MAXDNLEN + 1) self.ldap_search_base = EditField(area, window=self.center_win, text=self.nameservice.ldap_search_base, error_win=self.main_win.error_line) self.main_win.do_update() self.center_win.activate_object(self.ldap_ip)
def _show(self): ''' show DNS search list ''' super(NSDNSSearch, self)._show() # check dictionary of screens associated with name service selections if not self.nameservice.dns: raise SkipException y_loc = self._paint_opening() cols = min(MAXDOMAINLEN + 1, self.win_size_x - textwidth(self.title) - INDENT - 1) self.dns_search_list = [] find_1st_nonblank = None find_last_nonblank = -1 LOGGER.info(self.nameservice.dns_search) for i in range(MAXDNSSEARCH): self.center_win.add_text(text=self.title, start_y=y_loc, start_x=INDENT) area = WindowArea(1, cols, y_loc, textwidth(self.title) + INDENT + 1) y_loc += 1 if i < len(self.nameservice.dns_search) and \ self.nameservice.dns_search[i] is not None: text = self.nameservice.dns_search[i] else: text = '' # find first blank field or last non-blank field if text: find_last_nonblank = i elif find_1st_nonblank is None: find_1st_nonblank = i edf = EditField(area, window=self.center_win, text=text, validate=incremental_validate_domain, error_win=self.main_win.error_line) self.dns_search_list += [edf] self.main_win.do_update() # position cursor on first blank or after last field if find_1st_nonblank is None: idx = min(find_last_nonblank + 1, MAXDNSSEARCH - 1) else: idx = find_1st_nonblank self.center_win.activate_object(self.dns_search_list[idx])
def make_field(self, label, description, y_loc, max_y, max_x, description_start, default_val, is_ip=True, selectable=True): '''Create a list item with 'label', add an editable field with 'default_val', and add additional 'description' text following it ''' self.list_area.y_loc = y_loc list_item = ListItem(self.list_area, text=label, data_obj=label, window=self.center_win, add_obj=selectable) if is_ip: validate = incremental_validate_ip else: validate = None edit_field = EditField(self.edit_area, window=list_item, text=default_val, validate=validate, error_win=self.main_win.error_line, data_obj=label.rstrip(":")) self.center_win.add_paragraph(description, y_loc, description_start, max_y=(y_loc + max_y), max_x=max_x) return edit_field
class NetworkTypeScreen(BaseScreen): ''' Let the user: - Choose the hostname - Select network type (Automatic, Manual, or None) ''' HEADER_TEXT = _("Network") PARAGRAPH = _("Enter a name for this computer that identifies it on " "the network. It must be at least two characters. It " "can contain letters, numbers, and minus signs (-).") HOSTNAME_TEXT = _("Computer Name: ") NET_TYPE_TEXT = _("Select how the wired ethernet network " "connection is configured.") AUTO_TEXT = _("Automatically") AUTO_DETAIL = _("Automatically configure the connection") MANUAL_TEXT = _("Manually") MANUAL_DETAIL = _("Enter the information on the following screen") NONE_TEXT = _("None") NONE_DETAIL = _("Do not configure the network at this time") NO_NICS_FOUND = _("No wired network interfaces found. Additional " "device drivers may be needed.") ALL_NICS_FROMGZ = _("No configurable network interfaces found. They are " "all controlled from global zone.") ITEM_OFFSET = 2 ITEM_MAX_WIDTH = 17 ITEM_DESC_OFFSET = ITEM_MAX_WIDTH + ITEM_OFFSET + 1 HOSTNAME_SCREEN_LEN = 25 HELP_DATA = (SCI_HELP + "/%s/network.txt", _("Network")) def __init__(self, main_win, configure_network=False): global LOGGER if LOGGER is None: LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig") super(NetworkTypeScreen, self).__init__(main_win) self.hostfield_offset = textwidth(NetworkTypeScreen.HOSTNAME_TEXT) self.menu_item_desc_max = (self.win_size_x - NetworkTypeScreen.ITEM_DESC_OFFSET) self.net_type_dict = {} self.sys_info = None self.automatic = None self.manual = None self.none_option = None self.hostname = None self.nic_info = NetworkInfo() # find_links() returns tuple containing # * dictionary of configurable NICs # * number of NICs mandated from global zone. # # Taking that information into account, initialize type # of network configuration: # * FROMGZ - One or more link found, but all found links are # controlled from global zone. # * None - otherwise # # Set 'have_nic' flag to True if there is at least one configurable # link, otherwise set the flag to False. # self.ether_nics, self.fromgz_num = NetworkInfo.find_links() self.nic_info.type = NetworkInfo.NONE self.have_nic = True if len(self.ether_nics) == 0: self.have_nic = False if self.fromgz_num > 0: self.nic_info.type = NetworkInfo.FROMGZ self.configure_network = configure_network def _show(self): '''Create an EditField for entering hostname, and list items for each of the network types ''' sc_profile = solaris_install.sysconfig.profile.from_engine() if sc_profile.system is None: sc_profile.system = SystemInfo() self.sys_info = sc_profile.system if sc_profile.nic is None: sc_profile.nic = self.nic_info y_loc = 1 y_loc += self.center_win.add_paragraph(NetworkTypeScreen.PARAGRAPH, y_loc) y_loc += 1 self.center_win.add_text(NetworkTypeScreen.HOSTNAME_TEXT, y_loc) max_cols = self.win_size_x - self.hostfield_offset cols = min(max_cols, NetworkTypeScreen.HOSTNAME_SCREEN_LEN) scrollable_columns = SystemInfo.MAX_HOSTNAME_LEN + 1 hostname_area = WindowArea(1, cols, y_loc, self.hostfield_offset, scrollable_columns=scrollable_columns) self.hostname = EditField(hostname_area, window=self.center_win, text=self.sys_info.hostname, validate=hostname_is_valid, error_win=self.main_win.error_line) self.hostname.item_key = None # Display network configuration part of screen only if applicable. if self.configure_network: y_loc += 3 # If there are no configurable links, there is no point to let # user select type of network configuration. if not self.have_nic: # Inform user that no network interfaces were found # on the system. # If this is the case of non-global zone with all links # mandated from global zone, be more specific. if self.nic_info.type == NetworkInfo.FROMGZ: self.center_win.add_paragraph( NetworkTypeScreen.ALL_NICS_FROMGZ, y_loc, 1) else: self.center_win.add_paragraph( NetworkTypeScreen.NO_NICS_FOUND, y_loc, 1) self.main_win.do_update() activate = self.net_type_dict.get(self.nic_info.type, self.hostname) self.center_win.activate_object(activate) return self.main_win.do_update() activate = self.net_type_dict.get(self.nic_info.type, self.hostname) self.center_win.activate_object(activate) def on_change_screen(self): '''Save hostname and selected network type on change screen''' if self.configure_network and self.have_nic: self.nic_info.type = self.center_win.get_active_object().item_key if self.nic_info.type is None: self.nic_info.type = NetworkInfo.NONE LOGGER.info("Configuring NIC as: %s", self.nic_info.type) self.sys_info.hostname = self.hostname.get_text() def validate(self): '''Ensure hostname is set and a network type is chosen (unless no NICs are present) ''' hostname_text = self.hostname.get_text() if not hostname_text: raise UIMessage(_("A Hostname is required.")) if len(hostname_text) < 2: raise UIMessage(_("A Hostname must be at least two characters.")) if self.configure_network and self.have_nic and self.nic_info.type is None: item_key = self.center_win.get_active_object().item_key if item_key not in self.net_type_dict: raise UIMessage(_("Select the wired network configuration: " "Automatically, Manually, or None."))
def _show(self): '''Create an EditField for entering hostname, and list items for each of the network types ''' sc_profile = solaris_install.sysconfig.profile.from_engine() if sc_profile.system is None: sc_profile.system = SystemInfo() self.sys_info = sc_profile.system if sc_profile.nic is None: sc_profile.nic = self.nic_info y_loc = 1 y_loc += self.center_win.add_paragraph(NetworkTypeScreen.PARAGRAPH, y_loc) y_loc += 1 self.center_win.add_text(NetworkTypeScreen.HOSTNAME_TEXT, y_loc) max_cols = self.win_size_x - self.hostfield_offset cols = min(max_cols, NetworkTypeScreen.HOSTNAME_SCREEN_LEN) scrollable_columns = SystemInfo.MAX_HOSTNAME_LEN + 1 hostname_area = WindowArea(1, cols, y_loc, self.hostfield_offset, scrollable_columns=scrollable_columns) self.hostname = EditField(hostname_area, window=self.center_win, text=self.sys_info.hostname, validate=hostname_is_valid, error_win=self.main_win.error_line) self.hostname.item_key = None # Display network configuration part of screen only if applicable. if self.configure_network: y_loc += 3 # If there are no configurable links, there is no point to let # user select type of network configuration. if not self.have_nic: # Inform user that no network interfaces were found # on the system. # If this is the case of non-global zone with all links # mandated from global zone, be more specific. if self.nic_info.type == NetworkInfo.FROMGZ: self.center_win.add_paragraph( NetworkTypeScreen.ALL_NICS_FROMGZ, y_loc, 1) else: self.center_win.add_paragraph( NetworkTypeScreen.NO_NICS_FOUND, y_loc, 1) self.main_win.do_update() activate = self.net_type_dict.get(self.nic_info.type, self.hostname) self.center_win.activate_object(activate) return self.main_win.do_update() activate = self.net_type_dict.get(self.nic_info.type, self.hostname) self.center_win.activate_object(activate)
class UserScreen(BaseScreen): '''Allow user to set: - root password - user real name - user login - user password ''' HEADER_TEXT = _("Users") INTRO_SHOW_USER = _("Define a root password for the system and user " "account for yourself.") INTRO_HIDE_USER = _("Define a root password for the system. Creation " "of user account is disabled. See Help for " "additional information.") ROOT_TEXT = _("System Root Password") ROOT_LABEL = _("Root password:"******"Confirm password:"******"Create a user account") NAME_LABEL = _("Your real name:") USERNAME_LABEL = _("Username:"******"User password:"******"/%s/users.txt", _("Users")) PASS_SCREEN_LEN = 16 # also used as column width for user input ITEM_OFFSET = 2 def __init__(self, main_win, show_user_account=None): global LOGGER if LOGGER is None: LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig") super(UserScreen, self).__init__(main_win) self.max_text_len = (self.win_size_x - UserScreen.PASS_SCREEN_LEN - UserScreen.ITEM_OFFSET) / 2 max_field = max(textwidth(UserScreen.ROOT_LABEL), textwidth(UserScreen.CONFIRM_LABEL), textwidth(UserScreen.NAME_LABEL), textwidth(UserScreen.USERNAME_LABEL), textwidth(UserScreen.USER_PASS_LABEL)) self.text_len = min(max_field + 1, self.max_text_len) self.list_area = WindowArea(1, self.text_len, 0, UserScreen.ITEM_OFFSET) scrollable_columns = UserInfo.MAX_PASS_LEN + 1 self.edit_area = WindowArea(1, UserScreen.PASS_SCREEN_LEN + 1, 0, self.text_len, scrollable_columns=scrollable_columns) self.username_edit_area = WindowArea( 1, UserScreen.PASS_SCREEN_LEN + 1, 0, self.text_len, scrollable_columns=UserInfo.MAX_USERNAME_LEN + 1) err_x_loc = 2 * self.max_text_len - self.text_len err_width = (self.text_len + UserScreen.PASS_SCREEN_LEN) self.error_area = WindowArea(1, err_width, 0, err_x_loc) self.root = None self.user = None self.root_pass_list = None self.root_pass_edit = None self.root_pass_err = None self.root_confirm_err = None self.root_confirm_list = None self.root_confirm_edit = None self.real_name_err = None self.real_name_list = None self.real_name_edit = None self.username_err = None self.username_list = None self.username_edit = None self.user_pass_err = None self.user_pass_list = None self.user_pass_edit = None self.user_confirm_err = None self.user_confirm_list = None self.user_confirm_edit = None # # If show_user_account is True, complete Users screen will be # displayed (root password edit fields as well as widgets related # to creating initial user account). Otherwise, widgets for initial # user account are hidden. # # If not initialized explicitly by caller (e.g. text installer), # show_user_account is set to True only if all conditions needed # for successful creation of user account are met. # # In particular, existence of parent of home ZFS dataset is checked, # since if parent of home ZFS dataset was missing, then # svc:/system/config-user smf service (responsible for configuring # root and user accounts) would fail to create user account. As # a result of that, the whole system would end up in maintenance mode. # self.show_user_account = show_user_account if self.show_user_account is None: self.show_user_account = self.home_zfs_parent_exists() def _show(self): '''Display the user name, real name, and password fields''' sc_profile = solaris_install.sysconfig.profile.from_engine() # # Create UserInfo instances holding information about root and user # accounts. # if sc_profile.users is None: # # Assume root is a normal account. It will be changed to a role # if the user account is created. # root = UserInfo(login_name="root", is_role=False) # # Initialize attributes of user account which can't be configured # on screens. # user = UserInfo(gid=10, shell="/usr/bin/bash", roles="root", profiles="System Administrator", sudoers="ALL=(ALL) ALL") sc_profile.users = UserInfoContainer(root, user) self.root = sc_profile.users.root self.user = sc_profile.users.user LOGGER.debug("Root: %s", self.root) LOGGER.debug("User: %s", self.user) root_set = (self.root.passlen != 0) user_set = (self.user.passlen != 0) y_loc = 1 if self.show_user_account: intro_text = UserScreen.INTRO_SHOW_USER else: intro_text = UserScreen.INTRO_HIDE_USER self.center_win.add_paragraph(intro_text, y_loc, 1, y_loc + 2, self.win_size_x - 1) y_loc += 3 self.center_win.add_text(UserScreen.ROOT_TEXT, y_loc, 1, self.win_size_x - 1) y_loc += 2 self.error_area.y_loc = y_loc self.list_area.y_loc = y_loc self.root_pass_err = ErrorWindow(self.error_area, window=self.center_win) self.root_pass_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.ROOT_LABEL) self.root_pass_edit = PasswordField(self.edit_area, window=self.root_pass_list, error_win=self.root_pass_err, fill=root_set) y_loc += 1 self.error_area.y_loc = y_loc self.list_area.y_loc = y_loc self.root_confirm_err = ErrorWindow(self.error_area, window=self.center_win) self.root_confirm_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.CONFIRM_LABEL) self.root_confirm_edit = PasswordField(self.edit_area, window=self.root_confirm_list, fill=root_set, on_exit=pass_match, error_win=self.root_confirm_err) rc_edit_kwargs = {"linked_win": self.root_pass_edit} self.root_confirm_edit.on_exit_kwargs = rc_edit_kwargs # User account disabled, do not display related widgets. if not self.show_user_account: self.main_win.do_update() self.center_win.activate_object(self.root_pass_list) return y_loc += 2 self.center_win.add_text(UserScreen.USER_TEXT, y_loc, 1, self.win_size_x - 1) y_loc += 2 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.real_name_err = ErrorWindow(self.error_area, window=self.center_win) self.real_name_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.NAME_LABEL) self.real_name_edit = EditField(self.edit_area, window=self.real_name_list, error_win=self.real_name_err, text=self.user.real_name) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.username_err = ErrorWindow(self.error_area, window=self.center_win) self.username_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.USERNAME_LABEL) self.username_edit = EditField(self.username_edit_area, window=self.username_list, validate=username_valid, error_win=self.username_err, on_exit=login_valid, text=self.user.login_name) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.user_pass_err = ErrorWindow(self.error_area, window=self.center_win) self.user_pass_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.USER_PASS_LABEL) self.user_pass_edit = PasswordField(self.edit_area, window=self.user_pass_list, error_win=self.user_pass_err, fill=user_set) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.user_confirm_err = ErrorWindow(self.error_area, window=self.center_win) self.user_confirm_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.CONFIRM_LABEL) self.user_confirm_edit = PasswordField(self.edit_area, window=self.user_confirm_list, on_exit=pass_match, error_win=self.user_confirm_err, fill=user_set) uc_edit_kwargs = {"linked_win": self.user_pass_edit} self.user_confirm_edit.on_exit_kwargs = uc_edit_kwargs self.main_win.do_update() self.center_win.activate_object(self.root_pass_list) def on_change_screen(self): '''Store entered information into data object cache.''' if self.root_pass_edit.modified: if self.root_pass_edit.compare(self.root_confirm_edit): self.root.password = self.root_pass_edit.get_text() else: self.root.password = "" if self.root.password is None: self.root.password = "" self.root_pass_edit.clear_text() self.root_confirm_edit.clear_text() # # User account disabled, do not store related info into data object # cache. # if not self.show_user_account: return self.user.real_name = self.real_name_edit.get_text() self.user.login_name = self.username_edit.get_text() # If user account is to be created, configure root account as a role. self.root.is_role = bool(self.user.login_name) if self.user_pass_edit.modified: if self.user_pass_edit.compare(self.user_confirm_edit): self.user.password = self.user_pass_edit.get_text() else: self.user.password = "" if self.user.password is None: self.user.password = "" self.user_pass_edit.clear_text() self.user_confirm_edit.clear_text() def validate(self): '''Check for mismatched passwords, bad login names, etc.''' # Note: the Root and User password fields may be filled with # asterisks if the user previously invoked this screen. Therefore, # if not empty we check their modified flags before validating the # contents. if self.root_pass_edit.modified: root_pass_set = bool(self.root_pass_edit.get_text()) else: root_pass_set = (self.root.passlen != 0) # Root password is mandatory and, if modified, must be valid if not root_pass_set or self.root_pass_edit.modified: pass_valid(self.root_pass_edit, msg_prefix=UserScreen.ROOT_LABEL + " ") # Root password confirmation must match original Root password if not self.root_pass_edit.compare(self.root_confirm_edit): raise UIMessage(_("Root passwords don't match")) # User account disabled, skip related validation steps. if not self.show_user_account: return if self.user_pass_edit.modified: user_pass_set = bool(self.user_pass_edit.get_text()) else: user_pass_set = (self.user.passlen != 0) login_name = self.username_edit.get_text() LOGGER.debug("login_name=%s", login_name) real_name = self.real_name_edit.get_text() LOGGER.debug("real_name=%s", real_name) # Username (if specified) must be valid login_valid(self.username_edit) if login_name: # If Username was entered then: # - User password is mandatory and, if modified, must be valid # - User password confirmation must match original User password if not user_pass_set or self.user_pass_edit.modified: pass_valid(self.user_pass_edit, msg_prefix=UserScreen.USER_PASS_LABEL + " ") if not self.user_pass_edit.compare(self.user_confirm_edit): raise UIMessage(_("User passwords don't match")) else: # If either Real name or User password are specified then # Username must also be specified if real_name or user_pass_set: raise UIMessage( _("Enter username or clear all user " "account fields")) def home_zfs_parent_exists(self): '''Return True if parent of to-be-created home ZFS dataset exists. Otherwise, return False. Home ZFS dataset is created in form of <root_pool>/export/home/<login> with mountpoint /export/home/<login> inherited from parent dataset. The check verifies that ZFS dataset with to-be-inherited /export/home mountpoint exists. ''' # obtain mountpoints for all existing ZFS datasets cmd = [ZFS, "list", "-H", "-o", "mountpoint"] try: mountpoint_list = run(cmd, logger=LOGGER) except CalledProcessError: LOGGER.warn("Could not determine if parent of home ZFS dataset " "exists.") return False if "/export/home" not in mountpoint_list.stdout.splitlines(): LOGGER.debug("Parent of home ZFS dataset does not exist, creation " "of user account disabled.") return False LOGGER.debug("Parent of home ZFS dataset exists, creation of user " "account enabled.") return True
def _show(self): """ create the screen to collect user input """ # look in the DOC for an Iscsi object eng = InstallEngine.get_instance() iscsi_obj = eng.doc.volatile.get_children(name=ISCSI_LABEL, class_type=Iscsi) # If there's no iscsi object in the DOC, skip this screen if not iscsi_obj: raise SkipException else: self.iscsi_obj = iscsi_obj[0] LOGGER.debug("show Iscsi object: %s" % str(self.iscsi_obj)) y_loc = 1 self.center_win.add_paragraph(IscsiScreen.INTRO, start_y=y_loc) # look to see if DHCP is providing information if self.check_dhcp(): y_loc += 2 self.center_win.add_paragraph(IscsiScreen.FOUND_DHCP_LABEL, start_y=y_loc) # Target IP y_loc += 2 # Mark this field required self.center_win.window.addch(y_loc, 2, IscsiScreen.REQUIRED_MARK, self.center_win.color_theme.inactive) edit_start = textwidth(IscsiScreen.TARGET_IP_LABEL) + \ IscsiScreen.ITEM_OFFSET ip_area = WindowArea(y_loc=y_loc, x_loc=1, lines=1, columns=edit_start + IscsiScreen.MAX_IP_LEN + 1) self.target_ip_list = ListItem(ip_area, window=self.center_win, text=IscsiScreen.TARGET_IP_LABEL) self.target_ip_list.key_dict.update(self.add_keys) self.default_edit.x_loc = edit_start self.default_edit.columns = IscsiScreen.MAX_IP_LEN + 1 self.target_ip_edit = EditField(self.default_edit, window=self.target_ip_list, validate=incremental_validate_ip, error_win=self.main_win.error_line) self.target_ip_edit.key_dict.update(self.add_keys) if self.target_ip is not None: self.target_ip_edit.set_text(self.target_ip) # Target Port edit_start = ip_area.x_loc + \ textwidth(IscsiScreen.TARGET_PORT_LABEL) + \ IscsiScreen.ITEM_OFFSET port_area = WindowArea(y_loc=y_loc, x_loc=self.half_win_width + IscsiScreen.DEAD_ZONE, lines=1, columns=edit_start + IscsiScreen.MAX_PORT_LEN + 1) self.target_port_list = ListItem(port_area, window=self.center_win, text=IscsiScreen.TARGET_PORT_LABEL) self.target_port_list.key_dict.update(self.add_keys) self.right_edit.x_loc = edit_start self.right_edit.columns = IscsiScreen.MAX_PORT_LEN + 1 self.target_port_edit = EditField(self.right_edit, window=self.target_port_list, validate=incremental_validate_digits, error_win=self.main_win.error_line, text=Iscsi.ISCSI_DEFAULT_PORT) self.target_port_edit.key_dict.update(self.add_keys) if self.target_port is not None: self.target_port_edit.set_text(self.target_port) # Target LUN y_loc += 1 edit_start = textwidth(IscsiScreen.TARGET_LUN_LABEL) + \ IscsiScreen.ITEM_OFFSET lun_area = WindowArea(y_loc=y_loc, x_loc=1, lines=1, columns=edit_start + IscsiScreen.MAX_LUN_LEN + 1) self.target_lun_list = ListItem(lun_area, window=self.center_win, text=IscsiScreen.TARGET_LUN_LABEL) self.target_lun_list.key_dict.update(self.add_keys) self.default_edit.x_loc = edit_start self.default_edit.columns = IscsiScreen.MAX_LUN_LEN + 1 self.target_lun_edit = EditField(self.default_edit, window=self.target_lun_list, validate=incremental_validate_hex, error_win=self.main_win.error_line) self.target_lun_edit.key_dict.update(self.add_keys) if self.target_lun is not None: self.target_lun_edit.set_text(self.target_lun) # Target Name y_loc += 2 name_area = WindowArea(y_loc=y_loc, x_loc=1, lines=1, columns=self.full_win_width) name_area.y_loc = y_loc target_name_list = ListItem(name_area, window=self.center_win, text=IscsiScreen.TARGET_NAME_LABEL) self.name_edit.x_loc = textwidth(IscsiScreen.TARGET_NAME_LABEL) + \ IscsiScreen.ITEM_OFFSET self.name_edit.columns = self.full_win_width - \ textwidth(IscsiScreen.TARGET_NAME_LABEL) - \ IscsiScreen.ITEM_OFFSET self.target_name_edit = EditField(self.name_edit, window=target_name_list) if self.target_name is not None: self.target_name_edit.set_text(self.target_name) # Horizontal line y_loc += 1 self.center_win.window.hline(y_loc, 3, curses.ACS_HLINE, self.full_win_width) # Initiator Name y_loc += 1 if self.is_iscsiboot: # the system BIOS is configured for iSCSI boot. This means the # user will be unable to change the initiator-name. Display the # name, but don't allow it to be changed. text = "%s %s" % \ (IscsiScreen.INITIATOR_NAME_LABEL, self.initiator_name) self.center_win.add_text(text, start_y=y_loc, start_x=1) y_loc += 1 self.center_win.add_text(IscsiScreen.ISCSI_BOOT_LABEL, start_y=y_loc, start_x=1) else: # display the edit field as normal name_area.y_loc = y_loc initiator_name_list = ListItem(name_area, window=self.center_win, text=IscsiScreen.INITIATOR_NAME_LABEL) self.name_edit.x_loc = \ textwidth(IscsiScreen.INITIATOR_NAME_LABEL) + \ IscsiScreen.ITEM_OFFSET self.name_edit.columns = self.full_win_width - \ textwidth(IscsiScreen.INITIATOR_NAME_LABEL) - \ IscsiScreen.ITEM_OFFSET self.initiator_name_edit = EditField(self.name_edit, window=initiator_name_list, text=self.initiator_name) y_loc += 2 self.center_win.add_text(IscsiScreen.USE_CHAP_LABEL, y_loc, 1) # CHAP username y_loc += 1 edit_start = textwidth(IscsiScreen.CHAP_NAME_LABEL) + \ IscsiScreen.ITEM_OFFSET chapname_area = WindowArea(y_loc=y_loc, x_loc=15, lines=1, columns=edit_start + IscsiScreen.CHAP_LEN) chap_name_list = ListItem(chapname_area, window=self.center_win, text=IscsiScreen.CHAP_NAME_LABEL) self.chap_edit.x_loc = edit_start self.chap_edit.columns = IscsiScreen.CHAP_LEN + 1 self.chap_edit.scrollable_columns = IscsiScreen.MAX_NAME_LEN + 1 self.chap_name_edit = EditField(self.chap_edit, window=chap_name_list) if self.chap_name is not None: self.chap_name_edit.set_text(self.chap_name) # CHAP password y_loc += 1 edit_start = textwidth(IscsiScreen.CHAP_PASSWORD_LABEL) + \ IscsiScreen.ITEM_OFFSET chapname_area.y_loc = y_loc chap_password_list = ListItem(chapname_area, window=self.center_win, text=IscsiScreen.CHAP_PASSWORD_LABEL) self.chap_edit.x_loc = textwidth(IscsiScreen.CHAP_PASSWORD_LABEL) + \ IscsiScreen.ITEM_OFFSET self.chap_edit.scrollable_columns = None self.chap_password_edit = PasswordField(self.chap_edit, window=chap_password_list) if self.chap_password is not None: self.chap_password_edit.set_text(self.chap_password) # Legend y_loc += 2 self.center_win.window.addch(y_loc, 1, IscsiScreen.REQUIRED_MARK, self.center_win.color_theme.inactive) self.center_win.add_text(IscsiScreen.REQUIRED_FIELD_LABEL, y_loc, 1) self.main_win.do_update() self.center_win.activate_object()
class UserScreen(BaseScreen): '''Allow user to set: - root password - user real name - user login - user password ''' HEADER_TEXT = _("Users") INTRO_SHOW_USER = _("Define a root password for the system and user " "account for yourself.") INTRO_HIDE_USER = _("Define a root password for the system. Creation " "of user account is disabled. See Help for " "additional information.") ROOT_TEXT = _("System Root Password") ROOT_LABEL = _("Root password:"******"Confirm password:"******"Create a user account") NAME_LABEL = _("Your real name:") USERNAME_LABEL = _("Username:"******"User password:"******"/%s/users.txt", _("Users")) PASS_SCREEN_LEN = 16 # also used as column width for user input ITEM_OFFSET = 2 def __init__(self, main_win, show_user_account=None): global LOGGER if LOGGER is None: LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig") super(UserScreen, self).__init__(main_win) self.max_text_len = (self.win_size_x - UserScreen.PASS_SCREEN_LEN - UserScreen.ITEM_OFFSET) / 2 max_field = max(textwidth(UserScreen.ROOT_LABEL), textwidth(UserScreen.CONFIRM_LABEL), textwidth(UserScreen.NAME_LABEL), textwidth(UserScreen.USERNAME_LABEL), textwidth(UserScreen.USER_PASS_LABEL)) self.text_len = min(max_field + 1, self.max_text_len) self.list_area = WindowArea(1, self.text_len, 0, UserScreen.ITEM_OFFSET) scrollable_columns = UserInfo.MAX_PASS_LEN + 1 self.edit_area = WindowArea(1, UserScreen.PASS_SCREEN_LEN + 1, 0, self.text_len, scrollable_columns=scrollable_columns) self.username_edit_area = WindowArea(1, UserScreen.PASS_SCREEN_LEN + 1, 0, self.text_len, scrollable_columns=UserInfo.MAX_USERNAME_LEN + 1) err_x_loc = 2 * self.max_text_len - self.text_len err_width = (self.text_len + UserScreen.PASS_SCREEN_LEN) self.error_area = WindowArea(1, err_width, 0, err_x_loc) self.root = None self.user = None self.root_pass_list = None self.root_pass_edit = None self.root_pass_err = None self.root_confirm_err = None self.root_confirm_list = None self.root_confirm_edit = None self.real_name_err = None self.real_name_list = None self.real_name_edit = None self.username_err = None self.username_list = None self.username_edit = None self.user_pass_err = None self.user_pass_list = None self.user_pass_edit = None self.user_confirm_err = None self.user_confirm_list = None self.user_confirm_edit = None # # If show_user_account is True, complete Users screen will be # displayed (root password edit fields as well as widgets related # to creating initial user account). Otherwise, widgets for initial # user account are hidden. # # If not initialized explicitly by caller (e.g. text installer), # show_user_account is set to True only if all conditions needed # for successful creation of user account are met. # # In particular, existence of parent of home ZFS dataset is checked, # since if parent of home ZFS dataset was missing, then # svc:/system/config-user smf service (responsible for configuring # root and user accounts) would fail to create user account. As # a result of that, the whole system would end up in maintenance mode. # self.show_user_account = show_user_account if self.show_user_account is None: self.show_user_account = self.home_zfs_parent_exists() def _show(self): '''Display the user name, real name, and password fields''' sc_profile = solaris_install.sysconfig.profile.from_engine() # # Create UserInfo instances holding information about root and user # accounts. # if sc_profile.users is None: # # Assume root is a normal account. It will be changed to a role # if the user account is created. # root = UserInfo(login_name="root", is_role=False) # # Initialize attributes of user account which can't be configured # on screens. # user = UserInfo(gid=10, shell="/usr/bin/bash", roles="root", profiles="System Administrator", sudoers="ALL=(ALL) ALL") sc_profile.users = UserInfoContainer(root, user) self.root = sc_profile.users.root self.user = sc_profile.users.user LOGGER.debug("Root: %s", self.root) LOGGER.debug("User: %s", self.user) root_set = (self.root.passlen != 0) user_set = (self.user.passlen != 0) y_loc = 1 if self.show_user_account: intro_text = UserScreen.INTRO_SHOW_USER else: intro_text = UserScreen.INTRO_HIDE_USER self.center_win.add_paragraph(intro_text, y_loc, 1, y_loc + 2, self.win_size_x - 1) y_loc += 3 self.center_win.add_text(UserScreen.ROOT_TEXT, y_loc, 1, self.win_size_x - 1) y_loc += 2 self.error_area.y_loc = y_loc self.list_area.y_loc = y_loc self.root_pass_err = ErrorWindow(self.error_area, window=self.center_win) self.root_pass_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.ROOT_LABEL) self.root_pass_edit = PasswordField(self.edit_area, window=self.root_pass_list, error_win=self.root_pass_err, fill=root_set) y_loc += 1 self.error_area.y_loc = y_loc self.list_area.y_loc = y_loc self.root_confirm_err = ErrorWindow(self.error_area, window=self.center_win) self.root_confirm_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.CONFIRM_LABEL) self.root_confirm_edit = PasswordField(self.edit_area, window=self.root_confirm_list, fill=root_set, on_exit=pass_match, error_win=self.root_confirm_err) rc_edit_kwargs = {"linked_win": self.root_pass_edit} self.root_confirm_edit.on_exit_kwargs = rc_edit_kwargs # User account disabled, do not display related widgets. if not self.show_user_account: self.main_win.do_update() self.center_win.activate_object(self.root_pass_list) return y_loc += 2 self.center_win.add_text(UserScreen.USER_TEXT, y_loc, 1, self.win_size_x - 1) y_loc += 2 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.real_name_err = ErrorWindow(self.error_area, window=self.center_win) self.real_name_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.NAME_LABEL) self.real_name_edit = EditField(self.edit_area, window=self.real_name_list, error_win=self.real_name_err, text=self.user.real_name) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.username_err = ErrorWindow(self.error_area, window=self.center_win) self.username_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.USERNAME_LABEL) self.username_edit = EditField(self.username_edit_area, window=self.username_list, validate=username_valid, error_win=self.username_err, on_exit=login_valid, text=self.user.login_name) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.user_pass_err = ErrorWindow(self.error_area, window=self.center_win) self.user_pass_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.USER_PASS_LABEL) self.user_pass_edit = PasswordField(self.edit_area, window=self.user_pass_list, error_win=self.user_pass_err, fill=user_set) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.user_confirm_err = ErrorWindow(self.error_area, window=self.center_win) self.user_confirm_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.CONFIRM_LABEL) self.user_confirm_edit = PasswordField(self.edit_area, window=self.user_confirm_list, on_exit=pass_match, error_win=self.user_confirm_err, fill=user_set) uc_edit_kwargs = {"linked_win": self.user_pass_edit} self.user_confirm_edit.on_exit_kwargs = uc_edit_kwargs self.main_win.do_update() self.center_win.activate_object(self.root_pass_list) def on_change_screen(self): '''Store entered information into data object cache.''' if self.root_pass_edit.modified: if self.root_pass_edit.compare(self.root_confirm_edit): self.root.password = self.root_pass_edit.get_text() else: self.root.password = "" if self.root.password is None: self.root.password = "" self.root_pass_edit.clear_text() self.root_confirm_edit.clear_text() # # User account disabled, do not store related info into data object # cache. # if not self.show_user_account: return self.user.real_name = self.real_name_edit.get_text() self.user.login_name = self.username_edit.get_text() # If user account is to be created, configure root account as a role. self.root.is_role = bool(self.user.login_name) if self.user_pass_edit.modified: if self.user_pass_edit.compare(self.user_confirm_edit): self.user.password = self.user_pass_edit.get_text() else: self.user.password = "" if self.user.password is None: self.user.password = "" self.user_pass_edit.clear_text() self.user_confirm_edit.clear_text() def validate(self): '''Check for mismatched passwords, bad login names, etc.''' # Note: the Root and User password fields may be filled with # asterisks if the user previously invoked this screen. Therefore, # if not empty we check their modified flags before validating the # contents. if self.root_pass_edit.modified: root_pass_set = bool(self.root_pass_edit.get_text()) else: root_pass_set = (self.root.passlen != 0) # Root password is mandatory and, if modified, must be valid if not root_pass_set or self.root_pass_edit.modified: pass_valid(self.root_pass_edit, msg_prefix=UserScreen.ROOT_LABEL + " ") # Root password confirmation must match original Root password if not self.root_pass_edit.compare(self.root_confirm_edit): raise UIMessage(_("Root passwords don't match")) # User account disabled, skip related validation steps. if not self.show_user_account: return if self.user_pass_edit.modified: user_pass_set = bool(self.user_pass_edit.get_text()) else: user_pass_set = (self.user.passlen != 0) login_name = self.username_edit.get_text() LOGGER.debug("login_name=%s", login_name) real_name = self.real_name_edit.get_text() LOGGER.debug("real_name=%s", real_name) # Username (if specified) must be valid login_valid(self.username_edit) if login_name: # If Username was entered then: # - User password is mandatory and, if modified, must be valid # - User password confirmation must match original User password if not user_pass_set or self.user_pass_edit.modified: pass_valid(self.user_pass_edit, msg_prefix=UserScreen.USER_PASS_LABEL + " ") if not self.user_pass_edit.compare(self.user_confirm_edit): raise UIMessage(_("User passwords don't match")) else: # If either Real name or User password are specified then # Username must also be specified if real_name or user_pass_set: raise UIMessage(_("Enter username or clear all user " "account fields")) def home_zfs_parent_exists(self): '''Return True if parent of to-be-created home ZFS dataset exists. Otherwise, return False. Home ZFS dataset is created in form of <root_pool>/export/home/<login> with mountpoint /export/home/<login> inherited from parent dataset. The check verifies that ZFS dataset with to-be-inherited /export/home mountpoint exists. ''' # obtain mountpoints for all existing ZFS datasets cmd = [ZFS, "list", "-H", "-o", "mountpoint"] try: mountpoint_list = run(cmd, logger=LOGGER) except CalledProcessError: LOGGER.warn("Could not determine if parent of home ZFS dataset " "exists.") return False if "/export/home" not in mountpoint_list.stdout.splitlines(): LOGGER.debug("Parent of home ZFS dataset does not exist, creation " "of user account disabled.") return False LOGGER.debug("Parent of home ZFS dataset exists, creation of user " "account enabled.") return True
class NetworkTypeScreen(BaseScreen): ''' Let the user: - Choose the hostname - Select network type (Automatic, Manual, or None) ''' HEADER_TEXT = _("Network") PARAGRAPH = _("Enter a name for this computer that identifies it on " "the network. It must be at least two characters. It " "can contain letters, numbers, and minus signs (-).") HOSTNAME_TEXT = _("Computer Name: ") NET_TYPE_TEXT = _("Select how the wired ethernet network " "connection is configured.") AUTO_TEXT = _("Automatically") AUTO_DETAIL = _("Automatically configure the connection") MANUAL_TEXT = _("Manually") MANUAL_DETAIL = _("Enter the information on the following screen") NONE_TEXT = _("None") NONE_DETAIL = _("Do not configure the network at this time") NO_NICS_FOUND = _("No wired network interfaces found. Additional " "device drivers may be needed.") ALL_NICS_FROMGZ = _("No configurable network interfaces found. They are " "all controlled from global zone.") ITEM_OFFSET = 2 ITEM_MAX_WIDTH = 17 ITEM_DESC_OFFSET = ITEM_MAX_WIDTH + ITEM_OFFSET + 1 HOSTNAME_SCREEN_LEN = 25 HELP_DATA = (SCI_HELP + "/%s/network.txt", _("Network")) def __init__(self, main_win, configure_network=False): global LOGGER if LOGGER is None: LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig") super(NetworkTypeScreen, self).__init__(main_win) self.hostfield_offset = textwidth(NetworkTypeScreen.HOSTNAME_TEXT) self.menu_item_desc_max = (self.win_size_x - NetworkTypeScreen.ITEM_DESC_OFFSET) self.net_type_dict = {} self.sys_info = None self.automatic = None self.manual = None self.none_option = None self.hostname = None self.nic_info = NetworkInfo() # find_links() returns tuple containing # * dictionary of configurable NICs # * number of NICs mandated from global zone. # # Taking that information into account, initialize type # of network configuration: # * FROMGZ - One or more link found, but all found links are # controlled from global zone. # * None - otherwise # # Set 'have_nic' flag to True if there is at least one configurable # link, otherwise set the flag to False. # self.ether_nics, self.fromgz_num = NetworkInfo.find_links() self.nic_info.type = NetworkInfo.NONE self.have_nic = True if len(self.ether_nics) == 0: self.have_nic = False if self.fromgz_num > 0: self.nic_info.type = NetworkInfo.FROMGZ self.configure_network = configure_network def _show(self): '''Create an EditField for entering hostname, and list items for each of the network types ''' sc_profile = solaris_install.sysconfig.profile.from_engine() if sc_profile.system is None: sc_profile.system = SystemInfo() self.sys_info = sc_profile.system if sc_profile.nic is None: sc_profile.nic = self.nic_info y_loc = 1 y_loc += self.center_win.add_paragraph(NetworkTypeScreen.PARAGRAPH, y_loc) y_loc += 1 self.center_win.add_text(NetworkTypeScreen.HOSTNAME_TEXT, y_loc) max_cols = self.win_size_x - self.hostfield_offset cols = min(max_cols, NetworkTypeScreen.HOSTNAME_SCREEN_LEN) scrollable_columns = SystemInfo.MAX_HOSTNAME_LEN + 1 hostname_area = WindowArea(1, cols, y_loc, self.hostfield_offset, scrollable_columns=scrollable_columns) self.hostname = EditField(hostname_area, window=self.center_win, text=self.sys_info.hostname, validate=hostname_is_valid, error_win=self.main_win.error_line) self.hostname.item_key = None # Display network configuration part of screen only if applicable. if self.configure_network: y_loc += 3 # If there are no configurable links, there is no point to let # user select type of network configuration. if not self.have_nic: # Inform user that no network interfaces were found # on the system. # If this is the case of non-global zone with all links # mandated from global zone, be more specific. if self.nic_info.type == NetworkInfo.FROMGZ: self.center_win.add_paragraph( NetworkTypeScreen.ALL_NICS_FROMGZ, y_loc, 1) else: self.center_win.add_paragraph( NetworkTypeScreen.NO_NICS_FOUND, y_loc, 1) self.main_win.do_update() activate = self.net_type_dict.get(self.nic_info.type, self.hostname) self.center_win.activate_object(activate) return self.main_win.do_update() activate = self.net_type_dict.get(self.nic_info.type, self.hostname) self.center_win.activate_object(activate) def on_change_screen(self): '''Save hostname and selected network type on change screen''' if self.configure_network and self.have_nic: self.nic_info.type = self.center_win.get_active_object().item_key if self.nic_info.type is None: self.nic_info.type = NetworkInfo.NONE LOGGER.info("Configuring NIC as: %s", self.nic_info.type) self.sys_info.hostname = self.hostname.get_text() def validate(self): '''Ensure hostname is set and a network type is chosen (unless no NICs are present) ''' hostname_text = self.hostname.get_text() if not hostname_text: raise UIMessage(_("A Hostname is required.")) if len(hostname_text) < 2: raise UIMessage(_("A Hostname must be at least two characters.")) if self.configure_network and self.have_nic and self.nic_info.type is None: item_key = self.center_win.get_active_object().item_key if item_key not in self.net_type_dict: raise UIMessage( _("Select the wired network configuration: " "Automatically, Manually, or None."))
class DateTimeScreen(BaseScreen): ''' Allow user to select year, month, day, hour, and minute to be used to set system clock. ''' HEADER_TEXT = _("Date and Time") YEAR_TEXT = _("Year:") MONTH_TEXT = _("Month:") DAY_TEXT = _("Day:") HOUR_TEXT = _("Hour:") MINUTE_TEXT = _("Minute:") YEAR_FORMAT = _("(YYYY)") PARAGRAPH = _("Edit the date and time as necessary.\n" "The time is in 24 hour format.") HELP_DATA = (SCI_HELP + "/%s/date_time.txt", _("Date and Time")) YEAR_DIGITS = 4 TWO_DIGITS = 2 YEAR_LEN = len(YEAR_TEXT) MONTH_LEN = len(MONTH_TEXT) DAY_LEN = len(DAY_TEXT) HOUR_LEN = len(HOUR_TEXT) MINUTE_LEN = len(MINUTE_TEXT) MAX_LEN = max(YEAR_LEN, MONTH_LEN, DAY_LEN, HOUR_LEN, MINUTE_LEN) + 1 ITEM_OFFSET = 2 def __init__(self, main_win): global LOGGER if LOGGER is None: LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig") super(DateTimeScreen, self).__init__(main_win) year_edit_width = DateTimeScreen.YEAR_DIGITS + 1 list_width = DateTimeScreen.MAX_LEN + year_edit_width self.list_area = WindowArea(1, list_width, 0, DateTimeScreen.ITEM_OFFSET) self.year_edit_area = WindowArea(1, year_edit_width, 0, DateTimeScreen.MAX_LEN + 1) other_edit_width = DateTimeScreen.TWO_DIGITS + 1 other_edit_offset = (DateTimeScreen.MAX_LEN + (DateTimeScreen.YEAR_DIGITS - DateTimeScreen.TWO_DIGITS) + 1) self.edit_area = WindowArea(1, other_edit_width, 0, other_edit_offset) self.info_offset = (DateTimeScreen.ITEM_OFFSET + self.list_area.columns + 1) self.info_width = len(DateTimeScreen.YEAR_FORMAT) err_offset = self.info_offset + self.info_width + 2 err_width = self.win_size_x - err_offset self.err_area = WindowArea(1, err_width, 0, err_offset) self.year_edit = None self.year_err = None self.year_list = None self.month_edit = None self.month_err = None self.month_list = None self.day_edit = None self.day_err = None self.day_list = None self.hour_edit = None self.hour_err = None self.hour_list = None self.minute_edit = None self.minute_err = None self.minute_list = None self.year_is_valid = True self.month_is_valid = True self.date_range_loc = None self.saved_year = None self.saved_month = None self.saved_day = None self.saved_hour = None self.saved_minute = None self.saved_days_in_month = None def _show(self): ''' Prepare the editable fields for day, month, year, hour and minute ''' y_loc = 1 y_loc += self.center_win.add_paragraph(DateTimeScreen.PARAGRAPH, y_loc) sc_profile = solaris_install.sysconfig.profile.from_engine() os.environ["TZ"] = sc_profile.system.tz_timezone now = datetime.datetime.now() LOGGER.log(LOG_LEVEL_INPUT, "Current date (year-month-day hour:minute)" ": %s-%s-%s %s:%s", now.year, now.month, now.day, now.hour, now.minute) # Only update saved values if this is first time on screen or # if we have saved offset in profile (F2, return to screen) # update_vals = False if self.saved_year is None: update_vals = True showtime = now elif sc_profile.system.time_offset != 0: showtime = now + sc_profile.system.time_offset update_vals = True sc_profile.system.time_offset = 0 if update_vals: self.saved_year = str(showtime.year) self.saved_month = str(showtime.month) self.saved_day = str(showtime.day) self.saved_hour = str(showtime.hour) self.saved_minute = str(showtime.minute) self.saved_days_in_month = calendar.monthrange(showtime.year, showtime.month)[1] LOGGER.debug("starting year month day hour minute:_%s_%s_%s_%s_%s", self.saved_year, self.saved_month, self.saved_day, self.saved_hour, self.saved_minute) LOGGER.debug("starting days_in_month: %s", self.saved_days_in_month) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.year_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.year_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.YEAR_TEXT) self.year_edit = EditField(self.year_edit_area, window=self.year_list, validate=year_valid, error_win=self.year_err, on_exit=year_on_exit, text=self.saved_year) self.year_edit.clear_on_enter = True self.center_win.add_text(DateTimeScreen.YEAR_FORMAT, y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.month_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.month_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.MONTH_TEXT) self.month_edit = EditField(self.edit_area, window=self.month_list, validate=month_valid, error_win=self.month_err, on_exit=month_on_exit, text=self.saved_month, numeric_pad="0") self.month_edit.clear_on_enter = True self.month_edit.right_justify = True self.center_win.add_text("(1-12)", y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.day_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.day_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.DAY_TEXT) self.day_edit = EditField(self.edit_area, window=self.day_list, validate=day_valid, error_win=self.day_err, on_exit=day_on_exit, text=self.saved_day, numeric_pad="0") self.day_edit.clear_on_enter = True self.day_edit.right_justify = True self.month_edit.validate_kwargs["date_time"] = self self.month_edit.validate_kwargs["year_edit"] = self.year_edit self.month_edit.validate_kwargs["day_edit"] = self.day_edit self.year_edit.validate_kwargs["date_time"] = self self.year_edit.validate_kwargs["month_edit"] = self.month_edit self.year_edit.validate_kwargs["day_edit"] = self.day_edit self.day_edit.validate_kwargs["date_time"] = self self.day_edit.validate_kwargs["year_edit"] = self.year_edit self.day_edit.validate_kwargs["month_edit"] = self.month_edit self.date_range_loc = (y_loc, self.info_offset) self.update_day_range(self.saved_days_in_month) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.hour_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.hour_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.HOUR_TEXT) self.hour_edit = EditField(self.edit_area, window=self.hour_list, validate=hour_valid, error_win=self.hour_err, on_exit=hour_on_exit, text=self.saved_hour, numeric_pad="0") self.hour_edit.clear_on_enter = True self.hour_edit.right_justify = True self.center_win.add_text("(0-23)", y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.minute_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.minute_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.MINUTE_TEXT) self.minute_edit = EditField(self.edit_area, window=self.minute_list, validate=minute_valid, error_win=self.minute_err, on_exit=minute_on_exit, text=self.saved_minute, numeric_pad="0") self.minute_edit.clear_on_enter = True self.minute_edit.right_justify = True self.center_win.add_text("(0-59)", y_loc, self.info_offset) self.main_win.do_update() self.center_win.activate_object(self.year_list) def validate(self): '''Verify each of the edit fields''' year_value = self.year_edit.get_text() month_value = self.month_edit.get_text() day_value = self.day_edit.get_text() hour_value = self.hour_edit.get_text() minute_value = self.minute_edit.get_text() LOGGER.debug("year_value=%s", year_value) LOGGER.debug("month_value=%s", month_value) LOGGER.debug("day_value=%s", day_value) LOGGER.debug("hour_value=%s", hour_value) LOGGER.debug("minute_value=%s", minute_value) had_err = False if not self.year_edit.run_on_exit(): had_err = True if not self.month_edit.run_on_exit(): had_err = True if not self.day_edit.run_on_exit(): had_err = True if not self.hour_edit.run_on_exit(): had_err = True if not self.minute_edit.run_on_exit(): had_err = True if had_err: raise UIMessage(_("Invalid date/time. See errors above.")) def update_day_range(self, maxday=31): ''' Update the day range displayed. The max number of days can vary depending on the month, so calling functions can update appropriately. ''' self.center_win.add_text("(1-%d)" % maxday, self.date_range_loc[0], self.date_range_loc[1], self.win_size_x - 3) self.saved_days_in_month = maxday def on_change_screen(self): '''Save current user input for return to screen''' self.saved_year = self.year_edit.get_text() self.saved_month = self.month_edit.get_text() self.saved_day = self.day_edit.get_text() self.saved_hour = self.hour_edit.get_text() self.saved_minute = self.minute_edit.get_text() def on_continue(self): '''Save time offset to profile''' saved_time = datetime.datetime(int(self.year_edit.get_text()), int(self.month_edit.get_text()), int(self.day_edit.get_text()), int(self.hour_edit.get_text()), int(self.minute_edit.get_text())) userdelta = saved_time - datetime.datetime.now() LOGGER.debug("delta time=%s", userdelta) sc_profile = solaris_install.sysconfig.profile.from_engine() sc_profile.system.time_offset = userdelta install_datetime = datetime.datetime.now() + userdelta LOGGER.debug("date command would be: /usr/bin/date %s", install_datetime.strftime("%m%d%H%M%y"))
class DateTimeScreen(BaseScreen): ''' Allow user to select year, month, day, hour, and minute to be used to set system clock. ''' HEADER_TEXT = _("Date and Time") YEAR_TEXT = _("Year:") MONTH_TEXT = _("Month:") DAY_TEXT = _("Day:") HOUR_TEXT = _("Hour:") MINUTE_TEXT = _("Minute:") YEAR_FORMAT = _("(YYYY)") PARAGRAPH = _("Edit the date and time as necessary.\n" "The time is in 24 hour format.") HELP_DATA = (SCI_HELP + "/%s/date_time.txt", _("Date and Time")) YEAR_DIGITS = 4 TWO_DIGITS = 2 YEAR_LEN = len(YEAR_TEXT) MONTH_LEN = len(MONTH_TEXT) DAY_LEN = len(DAY_TEXT) HOUR_LEN = len(HOUR_TEXT) MINUTE_LEN = len(MINUTE_TEXT) MAX_LEN = max(YEAR_LEN, MONTH_LEN, DAY_LEN, HOUR_LEN, MINUTE_LEN) + 1 ITEM_OFFSET = 2 def __init__(self, main_win): global LOGGER if LOGGER is None: LOGGER = logging.getLogger(INSTALL_LOGGER_NAME + ".sysconfig") super(DateTimeScreen, self).__init__(main_win) year_edit_width = DateTimeScreen.YEAR_DIGITS + 1 list_width = DateTimeScreen.MAX_LEN + year_edit_width self.list_area = WindowArea(1, list_width, 0, DateTimeScreen.ITEM_OFFSET) self.year_edit_area = WindowArea(1, year_edit_width, 0, DateTimeScreen.MAX_LEN + 1) other_edit_width = DateTimeScreen.TWO_DIGITS + 1 other_edit_offset = ( DateTimeScreen.MAX_LEN + (DateTimeScreen.YEAR_DIGITS - DateTimeScreen.TWO_DIGITS) + 1) self.edit_area = WindowArea(1, other_edit_width, 0, other_edit_offset) self.info_offset = (DateTimeScreen.ITEM_OFFSET + self.list_area.columns + 1) self.info_width = len(DateTimeScreen.YEAR_FORMAT) err_offset = self.info_offset + self.info_width + 2 err_width = self.win_size_x - err_offset self.err_area = WindowArea(1, err_width, 0, err_offset) self.year_edit = None self.year_err = None self.year_list = None self.month_edit = None self.month_err = None self.month_list = None self.day_edit = None self.day_err = None self.day_list = None self.hour_edit = None self.hour_err = None self.hour_list = None self.minute_edit = None self.minute_err = None self.minute_list = None self.year_is_valid = True self.month_is_valid = True self.date_range_loc = None self.saved_year = None self.saved_month = None self.saved_day = None self.saved_hour = None self.saved_minute = None self.saved_days_in_month = None def _show(self): ''' Prepare the editable fields for day, month, year, hour and minute ''' y_loc = 1 y_loc += self.center_win.add_paragraph(DateTimeScreen.PARAGRAPH, y_loc) sc_profile = solaris_install.sysconfig.profile.from_engine() os.environ["TZ"] = sc_profile.system.tz_timezone now = datetime.datetime.now() LOGGER.log( LOG_LEVEL_INPUT, "Current date (year-month-day hour:minute)" ": %s-%s-%s %s:%s", now.year, now.month, now.day, now.hour, now.minute) # Only update saved values if this is first time on screen or # if we have saved offset in profile (F2, return to screen) # update_vals = False if self.saved_year is None: update_vals = True showtime = now elif sc_profile.system.time_offset != 0: showtime = now + sc_profile.system.time_offset update_vals = True sc_profile.system.time_offset = 0 if update_vals: self.saved_year = str(showtime.year) self.saved_month = str(showtime.month) self.saved_day = str(showtime.day) self.saved_hour = str(showtime.hour) self.saved_minute = str(showtime.minute) self.saved_days_in_month = calendar.monthrange( showtime.year, showtime.month)[1] LOGGER.debug("starting year month day hour minute:_%s_%s_%s_%s_%s", self.saved_year, self.saved_month, self.saved_day, self.saved_hour, self.saved_minute) LOGGER.debug("starting days_in_month: %s", self.saved_days_in_month) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.year_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.year_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.YEAR_TEXT) self.year_edit = EditField(self.year_edit_area, window=self.year_list, validate=year_valid, error_win=self.year_err, on_exit=year_on_exit, text=self.saved_year) self.year_edit.clear_on_enter = True self.center_win.add_text(DateTimeScreen.YEAR_FORMAT, y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.month_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.month_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.MONTH_TEXT) self.month_edit = EditField(self.edit_area, window=self.month_list, validate=month_valid, error_win=self.month_err, on_exit=month_on_exit, text=self.saved_month, numeric_pad="0") self.month_edit.clear_on_enter = True self.month_edit.right_justify = True self.center_win.add_text("(1-12)", y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.day_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.day_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.DAY_TEXT) self.day_edit = EditField(self.edit_area, window=self.day_list, validate=day_valid, error_win=self.day_err, on_exit=day_on_exit, text=self.saved_day, numeric_pad="0") self.day_edit.clear_on_enter = True self.day_edit.right_justify = True self.month_edit.validate_kwargs["date_time"] = self self.month_edit.validate_kwargs["year_edit"] = self.year_edit self.month_edit.validate_kwargs["day_edit"] = self.day_edit self.year_edit.validate_kwargs["date_time"] = self self.year_edit.validate_kwargs["month_edit"] = self.month_edit self.year_edit.validate_kwargs["day_edit"] = self.day_edit self.day_edit.validate_kwargs["date_time"] = self self.day_edit.validate_kwargs["year_edit"] = self.year_edit self.day_edit.validate_kwargs["month_edit"] = self.month_edit self.date_range_loc = (y_loc, self.info_offset) self.update_day_range(self.saved_days_in_month) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.hour_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.hour_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.HOUR_TEXT) self.hour_edit = EditField(self.edit_area, window=self.hour_list, validate=hour_valid, error_win=self.hour_err, on_exit=hour_on_exit, text=self.saved_hour, numeric_pad="0") self.hour_edit.clear_on_enter = True self.hour_edit.right_justify = True self.center_win.add_text("(0-23)", y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.minute_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.minute_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.MINUTE_TEXT) self.minute_edit = EditField(self.edit_area, window=self.minute_list, validate=minute_valid, error_win=self.minute_err, on_exit=minute_on_exit, text=self.saved_minute, numeric_pad="0") self.minute_edit.clear_on_enter = True self.minute_edit.right_justify = True self.center_win.add_text("(0-59)", y_loc, self.info_offset) self.main_win.do_update() self.center_win.activate_object(self.year_list) def validate(self): '''Verify each of the edit fields''' year_value = self.year_edit.get_text() month_value = self.month_edit.get_text() day_value = self.day_edit.get_text() hour_value = self.hour_edit.get_text() minute_value = self.minute_edit.get_text() LOGGER.debug("year_value=%s", year_value) LOGGER.debug("month_value=%s", month_value) LOGGER.debug("day_value=%s", day_value) LOGGER.debug("hour_value=%s", hour_value) LOGGER.debug("minute_value=%s", minute_value) had_err = False if not self.year_edit.run_on_exit(): had_err = True if not self.month_edit.run_on_exit(): had_err = True if not self.day_edit.run_on_exit(): had_err = True if not self.hour_edit.run_on_exit(): had_err = True if not self.minute_edit.run_on_exit(): had_err = True if had_err: raise UIMessage(_("Invalid date/time. See errors above.")) def update_day_range(self, maxday=31): ''' Update the day range displayed. The max number of days can vary depending on the month, so calling functions can update appropriately. ''' self.center_win.add_text("(1-%d)" % maxday, self.date_range_loc[0], self.date_range_loc[1], self.win_size_x - 3) self.saved_days_in_month = maxday def on_change_screen(self): '''Save current user input for return to screen''' self.saved_year = self.year_edit.get_text() self.saved_month = self.month_edit.get_text() self.saved_day = self.day_edit.get_text() self.saved_hour = self.hour_edit.get_text() self.saved_minute = self.minute_edit.get_text() def on_continue(self): '''Save time offset to profile''' saved_time = datetime.datetime(int(self.year_edit.get_text()), int(self.month_edit.get_text()), int(self.day_edit.get_text()), int(self.hour_edit.get_text()), int(self.minute_edit.get_text())) userdelta = saved_time - datetime.datetime.now() LOGGER.debug("delta time=%s", userdelta) sc_profile = solaris_install.sysconfig.profile.from_engine() sc_profile.system.time_offset = userdelta install_datetime = datetime.datetime.now() + userdelta LOGGER.debug("date command would be: /usr/bin/date %s", install_datetime.strftime("%m%d%H%M%y"))
class ValidSample(BaseScreen): HEADER_TEXT = "Validation - Sample" def __init__(self, main_win): super(ValidSample, self).__init__(main_win) # Boilerplate; for storing references to the created ListItems, # EditFields, and ErrorWindows self.char_list = None self.char_field = None self.char2_list = None self.char2_field = None self.char2_err = None self.focus_list = None self.focus_field = None self.focus_err = None def _show(self): # WindowArea boilerplate list_area = WindowArea(lines=1, columns=40, y_loc=1, x_loc=1) edit_area = WindowArea(lines=1, columns=20, y_loc=0, x_loc=15) # EditFields support per-character validation by passing in # a callback function as the "validate" keyword argument. The function # is called after each keypress with a single parameter, the EditField # in question (from which one can grab the current text). If the # current value is valid, the function should do nothing. If invalid, # a UIMessage exception should be raised. # For the sake of 'flow', the validation functions for this sample # will be defined inline; in general, they should be defined elsewhere # in the file. Finally, remember that, since these functions are # called after each keystroke, they need to be able to handle partially # correct values as well. For example, "2", "25", "255", "255.", # "255.2", "255.25", ..., "255.255.255.0" all would need to be accepted # by a netmask validation function. def digits_only(edit_field): text = edit_field.get_text() if text and not text.isdigit(): raise UIMessage("Only digits allowed!") list_area.y_loc = 1 self.char_list = ListItem(list_area, window=self.center_win, text="validate:") self.char_edit = EditField(edit_area, window=self.char_list, validate=digits_only, error_win=self.main_win.error_line) # The error_win parameter is required to make anything meaningful # display to the user; it should be a reference to an ErrorWindow # object in which to display the message. (self.main_win.error_line # is used here as filler; a more appropriate example follows) list_area.y_loc = 2 # There's nothing too special about creating an ErrorWindow; # it's much like a ListItem or EditField: error_area = WindowArea(lines=1, columns=30, y_loc=2, x_loc=40) self.char2_err = ErrorWindow(error_area, self.center_win) self.char2_list = ListItem(list_area, window=self.center_win, text="validate(2):") self.char2_edit = EditField(edit_area, window=self.char2_list, validate=digits_only, error_win=self.char2_err) # An EditField can also be checked for validity on loss of focus, # by passing a function to the "on_exit" argument # (though care must be taken to also check validity when changing # screens; screen changes don't trigger loss-of-focus checks in the # same way) # The following EditField illustrates such a thing. (An on_exit # function would be an appropriate place to ensure that a user # entered "255.255.255.0" for a netmask, and not just "255.") list_area.y_loc = 3 error_area.y_loc = 3 self.focus_err = ErrorWindow(error_area, self.center_win) self.focus_list = ListItem(list_area, window=self.center_win, text="on_exit:") self.focus_edit = EditField(edit_area, window=self.focus_list, on_exit=digits_only, error_win=self.focus_err) self.center_win.activate_object() def validate(self): # As a final (and perhaps, most important) form of validation, when # a subclass of BaseScreen attempts to move *forward* to the next # screen, it will call its "validate()" function, if any. Like the # callback functions for EditFields, this function should raise a # UIMessage if there are any conditions which fail validation. # # validate() is not called if the user decides to go backwards; the # user is never locked out of reversing their direction # # Note: validate() is always called prior to "on_continue()"; thus, # any code in the on_continue function, if defined, can be certain # that the values for this screen are valid. # For this sample, the first two fields will be required to have # identical text. if self.char_edit.get_text() != self.char2_edit.get_text(): raise UIMessage("First 2 fields must have identical text!")
def _show(self): # WindowArea boilerplate list_area = WindowArea(lines=1, columns=40, y_loc=1, x_loc=1) edit_area = WindowArea(lines=1, columns=20, y_loc=0, x_loc=15) # EditFields support per-character validation by passing in # a callback function as the "validate" keyword argument. The function # is called after each keypress with a single parameter, the EditField # in question (from which one can grab the current text). If the # current value is valid, the function should do nothing. If invalid, # a UIMessage exception should be raised. # For the sake of 'flow', the validation functions for this sample # will be defined inline; in general, they should be defined elsewhere # in the file. Finally, remember that, since these functions are # called after each keystroke, they need to be able to handle partially # correct values as well. For example, "2", "25", "255", "255.", # "255.2", "255.25", ..., "255.255.255.0" all would need to be accepted # by a netmask validation function. def digits_only(edit_field): text = edit_field.get_text() if text and not text.isdigit(): raise UIMessage("Only digits allowed!") list_area.y_loc = 1 self.char_list = ListItem(list_area, window=self.center_win, text="validate:") self.char_edit = EditField(edit_area, window=self.char_list, validate=digits_only, error_win=self.main_win.error_line) # The error_win parameter is required to make anything meaningful # display to the user; it should be a reference to an ErrorWindow # object in which to display the message. (self.main_win.error_line # is used here as filler; a more appropriate example follows) list_area.y_loc = 2 # There's nothing too special about creating an ErrorWindow; # it's much like a ListItem or EditField: error_area = WindowArea(lines=1, columns=30, y_loc=2, x_loc=40) self.char2_err = ErrorWindow(error_area, self.center_win) self.char2_list = ListItem(list_area, window=self.center_win, text="validate(2):") self.char2_edit = EditField(edit_area, window=self.char2_list, validate=digits_only, error_win=self.char2_err) # An EditField can also be checked for validity on loss of focus, # by passing a function to the "on_exit" argument # (though care must be taken to also check validity when changing # screens; screen changes don't trigger loss-of-focus checks in the # same way) # The following EditField illustrates such a thing. (An on_exit # function would be an appropriate place to ensure that a user # entered "255.255.255.0" for a netmask, and not just "255.") list_area.y_loc = 3 error_area.y_loc = 3 self.focus_err = ErrorWindow(error_area, self.center_win) self.focus_list = ListItem(list_area, window=self.center_win, text="on_exit:") self.focus_edit = EditField(edit_area, window=self.focus_list, on_exit=digits_only, error_win=self.focus_err) self.center_win.activate_object()
def _show(self): '''Display the user name, real name, and password fields''' sc_profile = solaris_install.sysconfig.profile.from_engine() # # Create UserInfo instances holding information about root and user # accounts. # if sc_profile.users is None: # # Assume root is a normal account. It will be changed to a role # if the user account is created. # root = UserInfo(login_name="root", is_role=False) # # Initialize attributes of user account which can't be configured # on screens. # user = UserInfo(gid=10, shell="/usr/bin/bash", roles="root", profiles="System Administrator", sudoers="ALL=(ALL) ALL") sc_profile.users = UserInfoContainer(root, user) self.root = sc_profile.users.root self.user = sc_profile.users.user LOGGER.debug("Root: %s", self.root) LOGGER.debug("User: %s", self.user) root_set = (self.root.passlen != 0) user_set = (self.user.passlen != 0) y_loc = 1 if self.show_user_account: intro_text = UserScreen.INTRO_SHOW_USER else: intro_text = UserScreen.INTRO_HIDE_USER self.center_win.add_paragraph(intro_text, y_loc, 1, y_loc + 2, self.win_size_x - 1) y_loc += 3 self.center_win.add_text(UserScreen.ROOT_TEXT, y_loc, 1, self.win_size_x - 1) y_loc += 2 self.error_area.y_loc = y_loc self.list_area.y_loc = y_loc self.root_pass_err = ErrorWindow(self.error_area, window=self.center_win) self.root_pass_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.ROOT_LABEL) self.root_pass_edit = PasswordField(self.edit_area, window=self.root_pass_list, error_win=self.root_pass_err, fill=root_set) y_loc += 1 self.error_area.y_loc = y_loc self.list_area.y_loc = y_loc self.root_confirm_err = ErrorWindow(self.error_area, window=self.center_win) self.root_confirm_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.CONFIRM_LABEL) self.root_confirm_edit = PasswordField(self.edit_area, window=self.root_confirm_list, fill=root_set, on_exit=pass_match, error_win=self.root_confirm_err) rc_edit_kwargs = {"linked_win": self.root_pass_edit} self.root_confirm_edit.on_exit_kwargs = rc_edit_kwargs # User account disabled, do not display related widgets. if not self.show_user_account: self.main_win.do_update() self.center_win.activate_object(self.root_pass_list) return y_loc += 2 self.center_win.add_text(UserScreen.USER_TEXT, y_loc, 1, self.win_size_x - 1) y_loc += 2 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.real_name_err = ErrorWindow(self.error_area, window=self.center_win) self.real_name_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.NAME_LABEL) self.real_name_edit = EditField(self.edit_area, window=self.real_name_list, error_win=self.real_name_err, text=self.user.real_name) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.username_err = ErrorWindow(self.error_area, window=self.center_win) self.username_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.USERNAME_LABEL) self.username_edit = EditField(self.username_edit_area, window=self.username_list, validate=username_valid, error_win=self.username_err, on_exit=login_valid, text=self.user.login_name) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.user_pass_err = ErrorWindow(self.error_area, window=self.center_win) self.user_pass_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.USER_PASS_LABEL) self.user_pass_edit = PasswordField(self.edit_area, window=self.user_pass_list, error_win=self.user_pass_err, fill=user_set) y_loc += 1 self.list_area.y_loc = y_loc self.error_area.y_loc = y_loc self.user_confirm_err = ErrorWindow(self.error_area, window=self.center_win) self.user_confirm_list = ListItem(self.list_area, window=self.center_win, text=UserScreen.CONFIRM_LABEL) self.user_confirm_edit = PasswordField(self.edit_area, window=self.user_confirm_list, on_exit=pass_match, error_win=self.user_confirm_err, fill=user_set) uc_edit_kwargs = {"linked_win": self.user_pass_edit} self.user_confirm_edit.on_exit_kwargs = uc_edit_kwargs self.main_win.do_update() self.center_win.activate_object(self.root_pass_list)
class NSLDAPProfile(NameService): HEADER_TEXT = _("LDAP Profile") HELP_DATA = (SCI_HELP + "/%s/ldap_profile.txt", HEADER_TEXT) def __init__(self, main_win): super(NSLDAPProfile, self).__init__(main_win) self.title = _("Profile name:") self.title3 = _("Search base:") def _show(self): super(NSLDAPProfile, self)._show() if self.nameservice.nameservice != 'LDAP': raise SkipException if self.nameservice.dns: self.intro = \ _("Specify the name of the LDAP profile to be used to " "configure this system and the host name or IP address of " "the server that contains the profile.") self.title2 = _("Profile server host name or IP address:") else: self.intro = \ _("Specify the name of the LDAP profile to be used to " "configure this system and the IP address of the " "server that contains the profile.") self.title2 = _("Profile server IP address:") self.intro += _(" Enter the LDAP search base.") y_loc = self._paint_opening() maxtitlelen = max(textwidth(self.title), textwidth(self.title2), textwidth(self.title3)) aligned_x_loc = maxtitlelen + INDENT + 1 cols = self.win_size_x - aligned_x_loc self.center_win.add_text(self.title.rjust(maxtitlelen), y_loc, INDENT) area = WindowArea(1, cols, y_loc, aligned_x_loc) self.ldap_profile = EditField(area, window=self.center_win, text=self.nameservice.ldap_profile, error_win=self.main_win.error_line, validate=inc_validate_nowhite_nospecial) # in case of error, tell user what is being validated self.ldap_profile.validate_kwargs['etext'] = _('profile name') y_loc += 1 area = WindowArea(1, cols, y_loc, aligned_x_loc, scrollable_columns=NameService.HOSTNAME_SCREEN_LEN + 1) self.center_win.add_text(self.title2.rjust(maxtitlelen), y_loc, INDENT) # create edit field, validating for host name or IP address depending # on whether DNS was selected self.ldap_ip = EditField(area, window=self.center_win, text=self.nameservice.ldap_ip, error_win=self.main_win.error_line, validate=(incremental_validate_host if self.nameservice.dns else incremental_validate_ip)) # search base y_loc += 1 self.center_win.add_text(self.title3.rjust(maxtitlelen), y_loc, INDENT) area = WindowArea(1, cols, y_loc, aligned_x_loc, scrollable_columns=MAXDNLEN + 1) self.ldap_search_base = EditField(area, window=self.center_win, text=self.nameservice.ldap_search_base, error_win=self.main_win.error_line) self.main_win.do_update() self.center_win.activate_object(self.ldap_ip) def validate(self): validate_ldap_profile(self.ldap_profile.get_text()) ldap_ip = self.ldap_ip.get_text() if self.nameservice.dns: validate_host_or_ip(ldap_ip) else: validate_ip(ldap_ip) if not self.ldap_profile.get_text(): raise UIMessage(_("The LDAP profile name cannot be blank.")) if not ldap_ip: raise UIMessage(_("The LDAP server IP address cannot be blank.")) def on_change_screen(self): self.nameservice.ldap_profile = self.ldap_profile.get_text() self.nameservice.ldap_ip = self.ldap_ip.get_text() new_search_base = self.ldap_search_base.get_text() if new_search_base != self.nameservice.ldap_search_base: self.nameservice.ldap_search_base = new_search_base # update DN with any changes in search_base from user fixedbase = _ldap_domain_fixup(self.nameservice.ldap_pb_dn, new_search_base) if fixedbase: self.nameservice.ldap_pb_dn = fixedbase
def _show(self): ''' Prepare the editable fields for day, month, year, hour and minute ''' y_loc = 1 y_loc += self.center_win.add_paragraph(DateTimeScreen.PARAGRAPH, y_loc) sc_profile = solaris_install.sysconfig.profile.from_engine() os.environ["TZ"] = sc_profile.system.tz_timezone now = datetime.datetime.now() LOGGER.log(LOG_LEVEL_INPUT, "Current date (year-month-day hour:minute)" ": %s-%s-%s %s:%s", now.year, now.month, now.day, now.hour, now.minute) # Only update saved values if this is first time on screen or # if we have saved offset in profile (F2, return to screen) # update_vals = False if self.saved_year is None: update_vals = True showtime = now elif sc_profile.system.time_offset != 0: showtime = now + sc_profile.system.time_offset update_vals = True sc_profile.system.time_offset = 0 if update_vals: self.saved_year = str(showtime.year) self.saved_month = str(showtime.month) self.saved_day = str(showtime.day) self.saved_hour = str(showtime.hour) self.saved_minute = str(showtime.minute) self.saved_days_in_month = calendar.monthrange(showtime.year, showtime.month)[1] LOGGER.debug("starting year month day hour minute:_%s_%s_%s_%s_%s", self.saved_year, self.saved_month, self.saved_day, self.saved_hour, self.saved_minute) LOGGER.debug("starting days_in_month: %s", self.saved_days_in_month) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.year_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.year_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.YEAR_TEXT) self.year_edit = EditField(self.year_edit_area, window=self.year_list, validate=year_valid, error_win=self.year_err, on_exit=year_on_exit, text=self.saved_year) self.year_edit.clear_on_enter = True self.center_win.add_text(DateTimeScreen.YEAR_FORMAT, y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.month_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.month_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.MONTH_TEXT) self.month_edit = EditField(self.edit_area, window=self.month_list, validate=month_valid, error_win=self.month_err, on_exit=month_on_exit, text=self.saved_month, numeric_pad="0") self.month_edit.clear_on_enter = True self.month_edit.right_justify = True self.center_win.add_text("(1-12)", y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.day_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.day_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.DAY_TEXT) self.day_edit = EditField(self.edit_area, window=self.day_list, validate=day_valid, error_win=self.day_err, on_exit=day_on_exit, text=self.saved_day, numeric_pad="0") self.day_edit.clear_on_enter = True self.day_edit.right_justify = True self.month_edit.validate_kwargs["date_time"] = self self.month_edit.validate_kwargs["year_edit"] = self.year_edit self.month_edit.validate_kwargs["day_edit"] = self.day_edit self.year_edit.validate_kwargs["date_time"] = self self.year_edit.validate_kwargs["month_edit"] = self.month_edit self.year_edit.validate_kwargs["day_edit"] = self.day_edit self.day_edit.validate_kwargs["date_time"] = self self.day_edit.validate_kwargs["year_edit"] = self.year_edit self.day_edit.validate_kwargs["month_edit"] = self.month_edit self.date_range_loc = (y_loc, self.info_offset) self.update_day_range(self.saved_days_in_month) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.hour_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.hour_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.HOUR_TEXT) self.hour_edit = EditField(self.edit_area, window=self.hour_list, validate=hour_valid, error_win=self.hour_err, on_exit=hour_on_exit, text=self.saved_hour, numeric_pad="0") self.hour_edit.clear_on_enter = True self.hour_edit.right_justify = True self.center_win.add_text("(0-23)", y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.minute_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.minute_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.MINUTE_TEXT) self.minute_edit = EditField(self.edit_area, window=self.minute_list, validate=minute_valid, error_win=self.minute_err, on_exit=minute_on_exit, text=self.saved_minute, numeric_pad="0") self.minute_edit.clear_on_enter = True self.minute_edit.right_justify = True self.center_win.add_text("(0-59)", y_loc, self.info_offset) self.main_win.do_update() self.center_win.activate_object(self.year_list)
def _show(self): ''' Prepare the editable fields for day, month, year, hour and minute ''' y_loc = 1 y_loc += self.center_win.add_paragraph(DateTimeScreen.PARAGRAPH, y_loc) sc_profile = solaris_install.sysconfig.profile.from_engine() os.environ["TZ"] = sc_profile.system.tz_timezone now = datetime.datetime.now() LOGGER.log( LOG_LEVEL_INPUT, "Current date (year-month-day hour:minute)" ": %s-%s-%s %s:%s", now.year, now.month, now.day, now.hour, now.minute) # Only update saved values if this is first time on screen or # if we have saved offset in profile (F2, return to screen) # update_vals = False if self.saved_year is None: update_vals = True showtime = now elif sc_profile.system.time_offset != 0: showtime = now + sc_profile.system.time_offset update_vals = True sc_profile.system.time_offset = 0 if update_vals: self.saved_year = str(showtime.year) self.saved_month = str(showtime.month) self.saved_day = str(showtime.day) self.saved_hour = str(showtime.hour) self.saved_minute = str(showtime.minute) self.saved_days_in_month = calendar.monthrange( showtime.year, showtime.month)[1] LOGGER.debug("starting year month day hour minute:_%s_%s_%s_%s_%s", self.saved_year, self.saved_month, self.saved_day, self.saved_hour, self.saved_minute) LOGGER.debug("starting days_in_month: %s", self.saved_days_in_month) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.year_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.year_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.YEAR_TEXT) self.year_edit = EditField(self.year_edit_area, window=self.year_list, validate=year_valid, error_win=self.year_err, on_exit=year_on_exit, text=self.saved_year) self.year_edit.clear_on_enter = True self.center_win.add_text(DateTimeScreen.YEAR_FORMAT, y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.month_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.month_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.MONTH_TEXT) self.month_edit = EditField(self.edit_area, window=self.month_list, validate=month_valid, error_win=self.month_err, on_exit=month_on_exit, text=self.saved_month, numeric_pad="0") self.month_edit.clear_on_enter = True self.month_edit.right_justify = True self.center_win.add_text("(1-12)", y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.day_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.day_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.DAY_TEXT) self.day_edit = EditField(self.edit_area, window=self.day_list, validate=day_valid, error_win=self.day_err, on_exit=day_on_exit, text=self.saved_day, numeric_pad="0") self.day_edit.clear_on_enter = True self.day_edit.right_justify = True self.month_edit.validate_kwargs["date_time"] = self self.month_edit.validate_kwargs["year_edit"] = self.year_edit self.month_edit.validate_kwargs["day_edit"] = self.day_edit self.year_edit.validate_kwargs["date_time"] = self self.year_edit.validate_kwargs["month_edit"] = self.month_edit self.year_edit.validate_kwargs["day_edit"] = self.day_edit self.day_edit.validate_kwargs["date_time"] = self self.day_edit.validate_kwargs["year_edit"] = self.year_edit self.day_edit.validate_kwargs["month_edit"] = self.month_edit self.date_range_loc = (y_loc, self.info_offset) self.update_day_range(self.saved_days_in_month) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.hour_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.hour_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.HOUR_TEXT) self.hour_edit = EditField(self.edit_area, window=self.hour_list, validate=hour_valid, error_win=self.hour_err, on_exit=hour_on_exit, text=self.saved_hour, numeric_pad="0") self.hour_edit.clear_on_enter = True self.hour_edit.right_justify = True self.center_win.add_text("(0-23)", y_loc, self.info_offset) y_loc += 1 self.err_area.y_loc = y_loc self.list_area.y_loc = y_loc self.minute_err = ErrorWindow(self.err_area, window=self.center_win, centered=False) self.minute_list = ListItem(self.list_area, window=self.center_win, text=DateTimeScreen.MINUTE_TEXT) self.minute_edit = EditField(self.edit_area, window=self.minute_list, validate=minute_valid, error_win=self.minute_err, on_exit=minute_on_exit, text=self.saved_minute, numeric_pad="0") self.minute_edit.clear_on_enter = True self.minute_edit.right_justify = True self.center_win.add_text("(0-59)", y_loc, self.info_offset) self.main_win.do_update() self.center_win.activate_object(self.year_list)
class IscsiScreen(BaseScreen): """ Allow the user to specify parameters for iSCSI LUNs """ HEADER_TEXT = _("iSCSI Discovery") INTRO = _("The installer needs additional information for iSCSI LUN " "discovery") FOUND_DHCP_LABEL = _("DHCP has iSCSI parameters defined for this host") TARGET_IP_LABEL = _("Target IP:") TARGET_PORT_LABEL = _("Port:") TARGET_LUN_LABEL = _("Target LUN:") TARGET_NAME_LABEL = _("Target Name:") INITIATOR_NAME_LABEL = _("Initiator Name:") USE_CHAP_LABEL = _("Use CHAP:") CHAP_NAME_LABEL = _("CHAP Name:") CHAP_PASSWORD_LABEL = _("CHAP Password:"******"Required Field") USE_CHAP_LABEL = _("If using CHAP for authentication") MAPPING_LUN_LABEL = _("Mapping iSCSI LUN...") MAPPING_TARGET_LABEL = _("Mapping iSCSI Target...") ISCSI_BOOT_LABEL = _("iSCSI boot enabled - Initiator Name set in BIOS") # error strings MISSING_TARGET_IP = _("Target IP address not provided") INVALID_TARGET_IP = _("Invalid Target IP address") INVALID_INITIATOR_IQN = _("Invalid Initiator IQN string") INVALID_TARGET_IQN = _("Invalid Target IQN string") CHAP_USERNAME_MISSING = _("CHAP username not specified") CHAP_PASSWORD_MISSING = _("CHAP password not specified") CHAP_PASSWORD_TOO_SHORT = _("CHAP password must be between 12 and 16 " "characters") UNABLE_TO_MAP = _("Unable to map iSCSI LUN: ") HELP_DATA = (TUI_HELP + "/%s/iscsi.txt", _("iSCSI")) MAX_IP_LEN = 15 MAX_LUN_LEN = 4 MAX_PORT_LEN = 5 MAX_NAME_LEN = 223 CHAP_LEN = 16 ITEM_OFFSET = 2 DEAD_ZONE = 3 REQUIRED_MARK = EditField.ASTERISK_CHAR def __init__(self, main_win): """ screen object containing iSCSI criteria objects """ global LOGGER LOGGER = logging.getLogger(INSTALL_LOGGER_NAME) super(IscsiScreen, self).__init__(main_win) self.target_ip = None self.target_port = None self.target_lun = None self.target_name = None self._initiator_name = None self.chap_name = None self.chap_password = None self.full_win_width = self.win_size_x - IscsiScreen.DEAD_ZONE self.half_win_width = (self.win_size_x - IscsiScreen.DEAD_ZONE) / 2 self.default_edit = WindowArea(y_loc=0, lines=1, columns=IscsiScreen.CHAP_LEN) self.right_edit = WindowArea(y_loc=0, lines=1, columns=IscsiScreen.MAX_PORT_LEN) self.name_edit = WindowArea(y_loc=0, lines=1, scrollable_columns=IscsiScreen.MAX_NAME_LEN + 1) self.chap_edit = WindowArea(y_loc=0, lines=1, columns=IscsiScreen.CHAP_LEN) self.target_ip_list = None self.target_ip_edit = None self.target_port_list = None self.target_port_edit = None self.target_lun_list = None self.target_lun_edit = None self.target_name_edit = None self.initiator_name_edit = None self.chap_name_edit = None self.chap_password_edit = None # key map dictionary for Target entries self.add_keys = {curses.KEY_LEFT: self.on_arrow_key, curses.KEY_RIGHT: self.on_arrow_key, curses.KEY_DOWN: self.on_arrow_key, curses.KEY_UP: self.on_arrow_key} self.iscsi_obj = None self.is_iscsiboot = is_iscsiboot() def on_arrow_key(self, input_key): """ override the default behavior of the arrow keys for specific EditFields. """ # get the active object active = self.center_win.get_active_object() # only allow the right arrow to move from IP to Port if input_key == curses.KEY_RIGHT and active is self.target_ip_list: self.center_win.activate_object(self.target_port_list) return None # only allow the left arrow to move from Port to IP elif input_key == curses.KEY_LEFT and active is self.target_port_list: self.center_win.activate_object(self.target_ip_list) return None # override the default behavior for the up and down arrows to skip the # Port field if moving from IP to LUN elif input_key == curses.KEY_DOWN and active is self.target_ip_list: self.center_win.activate_object(self.target_lun_list) return None elif input_key == curses.KEY_UP and active is self.target_lun_list: self.center_win.activate_object(self.target_ip_list) return None return input_key def check_dhcp(self): """ query the DHCP server for the Rootpath string. If present, update the proper attributes. """ dhcp_params = Iscsi.get_dhcp() if dhcp_params is not None: self.target_ip, self.target_port, self.target_lun, self.target_name = dhcp_params return True return False @property def initiator_name(self): """ property to return the initiator name """ if self._initiator_name is None: cmd = [ISCSIADM, "list", "initiator-node"] p = run(cmd) for line in p.stdout.splitlines(): if line.startswith("Initiator node name:"): self._initiator_name = line.split(": ")[1] return self._initiator_name @initiator_name.setter def initiator_name(self, name): """ property setter for _initiator_name """ self._initiator_name = name def _show(self): """ create the screen to collect user input """ # look in the DOC for an Iscsi object eng = InstallEngine.get_instance() iscsi_obj = eng.doc.volatile.get_children(name=ISCSI_LABEL, class_type=Iscsi) # If there's no iscsi object in the DOC, skip this screen if not iscsi_obj: raise SkipException else: self.iscsi_obj = iscsi_obj[0] LOGGER.debug("show Iscsi object: %s" % str(self.iscsi_obj)) y_loc = 1 self.center_win.add_paragraph(IscsiScreen.INTRO, start_y=y_loc) # look to see if DHCP is providing information if self.check_dhcp(): y_loc += 2 self.center_win.add_paragraph(IscsiScreen.FOUND_DHCP_LABEL, start_y=y_loc) # Target IP y_loc += 2 # Mark this field required self.center_win.window.addch(y_loc, 2, IscsiScreen.REQUIRED_MARK, self.center_win.color_theme.inactive) edit_start = textwidth(IscsiScreen.TARGET_IP_LABEL) + \ IscsiScreen.ITEM_OFFSET ip_area = WindowArea(y_loc=y_loc, x_loc=1, lines=1, columns=edit_start + IscsiScreen.MAX_IP_LEN + 1) self.target_ip_list = ListItem(ip_area, window=self.center_win, text=IscsiScreen.TARGET_IP_LABEL) self.target_ip_list.key_dict.update(self.add_keys) self.default_edit.x_loc = edit_start self.default_edit.columns = IscsiScreen.MAX_IP_LEN + 1 self.target_ip_edit = EditField(self.default_edit, window=self.target_ip_list, validate=incremental_validate_ip, error_win=self.main_win.error_line) self.target_ip_edit.key_dict.update(self.add_keys) if self.target_ip is not None: self.target_ip_edit.set_text(self.target_ip) # Target Port edit_start = ip_area.x_loc + \ textwidth(IscsiScreen.TARGET_PORT_LABEL) + \ IscsiScreen.ITEM_OFFSET port_area = WindowArea(y_loc=y_loc, x_loc=self.half_win_width + IscsiScreen.DEAD_ZONE, lines=1, columns=edit_start + IscsiScreen.MAX_PORT_LEN + 1) self.target_port_list = ListItem(port_area, window=self.center_win, text=IscsiScreen.TARGET_PORT_LABEL) self.target_port_list.key_dict.update(self.add_keys) self.right_edit.x_loc = edit_start self.right_edit.columns = IscsiScreen.MAX_PORT_LEN + 1 self.target_port_edit = EditField(self.right_edit, window=self.target_port_list, validate=incremental_validate_digits, error_win=self.main_win.error_line, text=Iscsi.ISCSI_DEFAULT_PORT) self.target_port_edit.key_dict.update(self.add_keys) if self.target_port is not None: self.target_port_edit.set_text(self.target_port) # Target LUN y_loc += 1 edit_start = textwidth(IscsiScreen.TARGET_LUN_LABEL) + \ IscsiScreen.ITEM_OFFSET lun_area = WindowArea(y_loc=y_loc, x_loc=1, lines=1, columns=edit_start + IscsiScreen.MAX_LUN_LEN + 1) self.target_lun_list = ListItem(lun_area, window=self.center_win, text=IscsiScreen.TARGET_LUN_LABEL) self.target_lun_list.key_dict.update(self.add_keys) self.default_edit.x_loc = edit_start self.default_edit.columns = IscsiScreen.MAX_LUN_LEN + 1 self.target_lun_edit = EditField(self.default_edit, window=self.target_lun_list, validate=incremental_validate_hex, error_win=self.main_win.error_line) self.target_lun_edit.key_dict.update(self.add_keys) if self.target_lun is not None: self.target_lun_edit.set_text(self.target_lun) # Target Name y_loc += 2 name_area = WindowArea(y_loc=y_loc, x_loc=1, lines=1, columns=self.full_win_width) name_area.y_loc = y_loc target_name_list = ListItem(name_area, window=self.center_win, text=IscsiScreen.TARGET_NAME_LABEL) self.name_edit.x_loc = textwidth(IscsiScreen.TARGET_NAME_LABEL) + \ IscsiScreen.ITEM_OFFSET self.name_edit.columns = self.full_win_width - \ textwidth(IscsiScreen.TARGET_NAME_LABEL) - \ IscsiScreen.ITEM_OFFSET self.target_name_edit = EditField(self.name_edit, window=target_name_list) if self.target_name is not None: self.target_name_edit.set_text(self.target_name) # Horizontal line y_loc += 1 self.center_win.window.hline(y_loc, 3, curses.ACS_HLINE, self.full_win_width) # Initiator Name y_loc += 1 if self.is_iscsiboot: # the system BIOS is configured for iSCSI boot. This means the # user will be unable to change the initiator-name. Display the # name, but don't allow it to be changed. text = "%s %s" % \ (IscsiScreen.INITIATOR_NAME_LABEL, self.initiator_name) self.center_win.add_text(text, start_y=y_loc, start_x=1) y_loc += 1 self.center_win.add_text(IscsiScreen.ISCSI_BOOT_LABEL, start_y=y_loc, start_x=1) else: # display the edit field as normal name_area.y_loc = y_loc initiator_name_list = ListItem(name_area, window=self.center_win, text=IscsiScreen.INITIATOR_NAME_LABEL) self.name_edit.x_loc = \ textwidth(IscsiScreen.INITIATOR_NAME_LABEL) + \ IscsiScreen.ITEM_OFFSET self.name_edit.columns = self.full_win_width - \ textwidth(IscsiScreen.INITIATOR_NAME_LABEL) - \ IscsiScreen.ITEM_OFFSET self.initiator_name_edit = EditField(self.name_edit, window=initiator_name_list, text=self.initiator_name) y_loc += 2 self.center_win.add_text(IscsiScreen.USE_CHAP_LABEL, y_loc, 1) # CHAP username y_loc += 1 edit_start = textwidth(IscsiScreen.CHAP_NAME_LABEL) + \ IscsiScreen.ITEM_OFFSET chapname_area = WindowArea(y_loc=y_loc, x_loc=15, lines=1, columns=edit_start + IscsiScreen.CHAP_LEN) chap_name_list = ListItem(chapname_area, window=self.center_win, text=IscsiScreen.CHAP_NAME_LABEL) self.chap_edit.x_loc = edit_start self.chap_edit.columns = IscsiScreen.CHAP_LEN + 1 self.chap_edit.scrollable_columns = IscsiScreen.MAX_NAME_LEN + 1 self.chap_name_edit = EditField(self.chap_edit, window=chap_name_list) if self.chap_name is not None: self.chap_name_edit.set_text(self.chap_name) # CHAP password y_loc += 1 edit_start = textwidth(IscsiScreen.CHAP_PASSWORD_LABEL) + \ IscsiScreen.ITEM_OFFSET chapname_area.y_loc = y_loc chap_password_list = ListItem(chapname_area, window=self.center_win, text=IscsiScreen.CHAP_PASSWORD_LABEL) self.chap_edit.x_loc = textwidth(IscsiScreen.CHAP_PASSWORD_LABEL) + \ IscsiScreen.ITEM_OFFSET self.chap_edit.scrollable_columns = None self.chap_password_edit = PasswordField(self.chap_edit, window=chap_password_list) if self.chap_password is not None: self.chap_password_edit.set_text(self.chap_password) # Legend y_loc += 2 self.center_win.window.addch(y_loc, 1, IscsiScreen.REQUIRED_MARK, self.center_win.color_theme.inactive) self.center_win.add_text(IscsiScreen.REQUIRED_FIELD_LABEL, y_loc, 1) self.main_win.do_update() self.center_win.activate_object() def on_change_screen(self): """ save the user's choices in case they return to this screen """ self.target_ip = self.target_ip_edit.get_text() self.target_port = self.target_port_edit.get_text() self.target_lun = self.target_lun_edit.get_text() self.target_name = self.target_name_edit.get_text() if not self.is_iscsiboot: self.initiator_name = self.initiator_name_edit.get_text() self.chap_name = self.chap_name_edit.get_text() self.chap_password = self.chap_password_edit.get_text() def validate(self): """ validate the iSCSI attributes before continuing to disk selection. """ target_ip = self.target_ip_edit.get_text() target_lun = self.target_lun_edit.get_text() target_port = self.target_port_edit.get_text() target_name = self.target_name_edit.get_text() if not self.is_iscsiboot: initiator_name = self.initiator_name_edit.get_text() chap_name = self.chap_name_edit.get_text() chap_password = self.chap_password_edit.get_text() # validate the target IP if not target_ip: raise UIMessage(IscsiScreen.MISSING_TARGET_IP) else: try: IPAddress.convert_address(target_ip) except ValueError as error: raise UIMessage("%s: %s" % \ (IscsiScreen.INVALID_TARGET_IP, str(error))) # validate the IQN strings (by default re.match only matches at the # beginning of a string) if not self.is_iscsiboot and initiator_name: if IQN_RE.match(initiator_name) is None: raise UIMessage(IscsiScreen.INVALID_INITIATOR_IQN) if target_name: if IQN_RE.match(target_name) is None: raise UIMessage(IscsiScreen.INVALID_TARGET_IQN) # validate that both CHAP username and password were specified (or not # at all) if chap_name and not chap_password: raise UIMessage(IscsiScreen.CHAP_PASSWORD_MISSING) if chap_password and not chap_name: raise UIMessage(IscsiScreen.CHAP_USERNAME_MISSING) # validate the CHAP password if chap_password: if not 12 <= len(chap_password) <= 16: raise UIMessage(IscsiScreen.CHAP_PASSWORD_TOO_SHORT) # Update the Iscsi DOC object self.iscsi_obj.target_ip = target_ip # force target_lun back to None if the user comes back and removes the # LUN entry from the screen if target_lun: self.iscsi_obj.target_lun = target_lun else: self.iscsi_obj.target_lun = None if target_name: self.iscsi_obj.target_name = target_name if target_port: self.iscsi_obj.target_port = target_port if not self.is_iscsiboot and initiator_name: self.iscsi_obj.initiator_name = initiator_name if chap_name: self.iscsi_obj.chap_name = chap_name if chap_password: self.iscsi_obj.chap_password = chap_password # attempt to connect to the LUN if target_lun: self.main_win.error_line.display_err(IscsiScreen.MAPPING_LUN_LABEL) else: self.main_win.error_line.display_err( IscsiScreen.MAPPING_TARGET_LABEL) try: self.iscsi_obj.setup_iscsi() LOGGER.debug("Iscsi object: %s" % str(self.iscsi_obj)) except (CalledProcessError, RuntimeError) as err: # remove the iSCSI configuration since it's invalid try: self.iscsi_obj.teardown() except CalledProcessError: # ignore any errors pass raise UIMessage("%s %s" % (IscsiScreen.UNABLE_TO_MAP, str(err)))
class NSDomain(NameService): HEADER_TEXT = _("Domain Name") HELP_DATA = (SCI_HELP + "/%s/domain.txt", HEADER_TEXT) def __init__(self, main_win, screen=None): super(NSDomain, self).__init__(main_win) self.intro = \ _("Specify the domain for the NIS or LDAP name server. " "Use the domain name's exact capitalization and " "punctuation.") self.title = _("Domain Name:") def _show(self): ''' show domain ''' super(NSDomain, self)._show() if not _has_name_service(): raise SkipException if not self.nameservice.nameservice: raise SkipException y_loc = self._paint_opening() cols = min(MAXDOMAINLEN + 1, self.win_size_x - textwidth(self.title) - INDENT - 1) self.center_win.add_text(self.title, y_loc, INDENT) area = WindowArea(1, cols, y_loc, textwidth(self.title) + INDENT + 1, scrollable_columns=MAXDOMAINLEN + 1) self.domain = EditField(area, window=self.center_win, text=self.nameservice.domain, validate=incremental_validate_domain, error_win=self.main_win.error_line) self.main_win.do_update() self.center_win.activate_object(self.domain) def validate(self): validate_domain(self.domain.get_text(), allow_empty=False) def on_change_screen(self): ns = self.nameservice new_domain = self.domain.get_text() if ns.domain != new_domain or \ (ns.nameservice == 'LDAP' and not ns.ldap_search_base): ns.domain = new_domain # default in LDAP-formatted values for domain if self.nameservice.nameservice == 'LDAP': ldapdom = _convert_to_ldap_domain(new_domain) # default in search base from domain if not ns.ldap_search_base or \ not ns.ldap_search_base.startswith(ldapdom): ns.ldap_search_base = ldapdom # base DN on search base if ns.ldap_pb_dn: # update DN with any changes in search_base from user fixedbase = _ldap_domain_fixup(ns.ldap_pb_dn, ns.ldap_search_base) if fixedbase: # user changed search base, update DN ns.ldap_pb_dn = fixedbase else: # provide probable DN default ns.ldap_pb_dn = 'cn=proxyagent,ou=profile,' + \ ns.ldap_search_base