class KdumpSpoke(EditTUISpoke): title = N_("Kdump") category = "system" edit_fields = [ Entry("Enable kdump", "enabled", EditTUISpoke.CHECK, True), Entry("Reserve amount", "reserveMB", RESERVE_VALID, lambda self, args: args.enabled) ] def __init__(self, app, data, storage, payload, instclass): if getOS() == "fedora": KdumpSpoke.edit_fields = [ Entry("Enable kdump", "enabled", EditTUISpoke.CHECK, True), Entry("Reserve amount", "reserveMB", FEDORA_RESERVE_VALID, lambda self, args: args.enabled) ] EditTUISpoke.__init__(self, app, data, storage, payload, instclass) self.args = self.data.addons.com_redhat_kdump def apply(self): pass @property def completed(self): return True @property def status(self): if self.args.enabled: state = _("Kdump is enabled") else: state = _("Kdump is disabled") return state
class KdumpSpoke(EditTUISpoke): title = N_("Kdump") category = SystemCategory lower, upper ,_step = getMemoryBounds() edit_fields = [ Entry("Enable kdump", "enabled", EditTUISpoke.CHECK, True), Entry("Enable dump mode fadump", "enablefadump", EditTUISpoke.CHECK, os.path.exists(FADUMP_CAPABLE_FILE) and (lambda self,args: args.enabled)), Entry("Reserve amount (%d - %d MB)" % (lower, upper), "reserveMB", RESERVE_VALID, lambda self,args: args.enabled) ] @classmethod def should_run(cls, environment, data): # the KdumpSpoke should run only if requested return flags.cmdline.getbool("kdump_addon", default=False) def __init__(self, app, data, storage, payload, instclass): EditTUISpoke.__init__(self, app, data, storage, payload, instclass) self.args = self.data.addons.com_redhat_kdump def apply(self): pass @property def completed(self): return True @property def status(self): if self.args.enabled: state = _("Kdump is enabled") else: state = _("Kdump is disabled") return state
def __init__(self, app, data, storage, payload, instclass): if getOS() == "fedora": KdumpSpoke.edit_fields = [ Entry("Enable kdump", "enabled", EditTUISpoke.CHECK, True), Entry("Reserve amount", "reserveMB", FEDORA_RESERVE_VALID, lambda self, args: args.enabled) ] EditTUISpoke.__init__(self, app, data, storage, payload, instclass) self.args = self.data.addons.com_redhat_kdump
class HelloWorldEditSpoke(EditTUISpoke): """Example class demonstrating usage of EditTUISpoke inheritance""" title = N_("Hello World Edit") category = HelloWorldCategory # simple RE used to specify we only accept a single word as a valid input _valid_input = re.compile(r'^\w+$') # special class attribute defining spoke's entries as: # Entry(TITLE, ATTRIBUTE, CHECKING_RE or TYPE, SHOW_FUNC or SHOW) # where: # TITLE specifies descriptive title of the entry # ATTRIBUTE specifies attribute of self.args that should be set to the # value entered by the user (may contain dots, i.e. may specify # a deep attribute) # CHECKING_RE specifies compiled RE used for deciding about # accepting/rejecting user's input # TYPE may be one of EditTUISpoke.CHECK or EditTUISpoke.PASSWORD used # instead of CHECKING_RE for simple checkboxes or password entries, # respectively # SHOW_FUNC is a function taking self and self.args and returning True or # False indicating whether the entry should be shown or not # SHOW is a boolean value that may be used instead of the SHOW_FUNC # # :see: pyanaconda.ui.tui.spokes.EditTUISpoke edit_fields = [ Entry("Simple checkbox", "checked", EditTUISpoke.CHECK, True), Entry("Always shown input", "shown_input", _valid_input, True), Entry("Conditioned input", "hidden_input", _valid_input, lambda self, args: bool(args.shown_input)), ] def __init__(self, app, data, storage, payload, instclass): EditTUISpoke.__init__(self, app, data, storage, payload, instclass) # just populate the self.args attribute to have a store for data # typically self.data or a subtree of self.data is used as self.args self.args = _EditData() @property def completed(self): # completed if user entered something non-empty to the Conditioned input return bool(self.args.hidden_input) @property def status(self): return "Hidden input %s" % ("entered" if self.args.hidden_input else "not entered") def apply(self): # nothing needed here, values are set in the self.args tree pass
class SpecifyNFSRepoSpoke(SourceSwitchHandler, EditTUISpoke): """ Specify server and mount opts here if NFS selected. """ title = N_("Specify Repo Options") category = "software" edit_fields = [ Entry(N_("NFS <server>:/<path>"), "server", re.compile(".*$"), True), Entry(N_("NFS mount options"), "opts", re.compile(".*$"), True) ] def __init__(self, app, data, storage, payload, instclass, selection, errors): EditTUISpoke.__init__(self, app, data, storage, payload, instclass) SourceSwitchHandler.__init__(self, data, storage) self.selection = selection self.errors = errors nfs = self.data.method self.args = DataHolder(server="", opts=nfs.opts or "") if nfs.method == "nfs" and nfs.server and nfs.dir: self.args.server = "%s:%s" % (nfs.server, nfs.dir) def refresh(self, args=None): """ Refresh window. """ return EditTUISpoke.refresh(self, args) @property def indirect(self): return True def apply(self): """ Apply our changes. """ if self.args.server == "" or not ':' in self.args.server: return False if self.args.server.startswith("nfs://"): self.args.server = self.args.server.strip("nfs://") try: (self.data.method.server, self.data.method.dir) = self.args.server.split(":", 2) except ValueError as err: LOG.error("ValueError: %s" % (err, )) self.errors.append( _("Failed to set up installation source. Check the source address." )) return opts = self.args.opts or "" self.set_source_nfs(opts)
class SpecifyNFSRepoSpoke(EditTUISpoke, SourceSwitchHandler): """ Specify server and mount opts here if NFS selected. """ title = N_("Specify Repo Options") category = SoftwareCategory edit_fields = [ Entry(N_("SERVER:/PATH"), "server", re.compile(".*$"), True), Entry(N_("NFS mount options"), "opts", re.compile(".*$"), True) ] def __init__(self, app, data, storage, payload, instclass, selection, error): EditTUISpoke.__init__(self, app, data, storage, payload, instclass) SourceSwitchHandler.__init__(self) self.selection = selection self._error = error nfs = self.data.method self.args = DataHolder(server="", opts=nfs.opts or "") if nfs.method == "nfs" and nfs.server and nfs.dir: self.args.server = "%s:%s" % (nfs.server, nfs.dir) def refresh(self, args=None): """ Refresh window. """ return EditTUISpoke.refresh(self, args) @property def indirect(self): return True def apply(self): """ Apply our changes. """ if self.args.server == "" or not ':' in self.args.server: return False if self.args.server.startswith("nfs://"): self.args.server = self.args.server[6:] try: (self.data.method.server, self.data.method.dir) = self.args.server.split(":", 2) except ValueError as err: log.error("ValueError: %s", err) self._error = True return opts = self.args.opts or "" self.set_source_nfs(opts)
class SpecifyRepoSpoke(EditTUISpoke): """ Specify the repo URL here if closest mirror not selected. """ title = _("Specify Repo Options") category = "software" edit_fields = [Entry(_("Repo URL"), "url", re.compile(".*$"), True)] def __init__(self, app, data, storage, payload, instclass, selection): EditTUISpoke.__init__(self, app, data, storage, payload, instclass) self.selection = selection self.args = self.data.method def refresh(self, args=None): """ Refresh window. """ return EditTUISpoke.refresh(self, args) @property def indirect(self): return True def apply(self): """ Apply all of our changes. """ if self.selection == 2 and not self.args.url.startswith("http://"): self.data.method.url = "http://" + self.args.url elif self.selection == 3 and not self.args.url.startswith("https://"): self.data.method.url = "https://" + self.args.url elif self.selection == 4 and not self.args.url.startswith("ftp://"): self.data.method.url = "ftp://" + self.args.url else: # protocol either unknown or entry already starts with a protocol # specification self.data.method.url = self.args.url
class ConfigureNetworkSpoke(EditTUISpoke): """ Spoke to set various configuration options for net devices. """ title = N_("Device configuration") category = "network" edit_fields = [ Entry( N_('IPv4 address or %s for DHCP') % '"dhcp"', "ip", re.compile("^(?:" + IPV4_PATTERN_WITHOUT_ANCHORS + "|dhcp)$"), True), Entry(N_("IPv4 netmask"), "netmask", re.compile("^" + IPV4_PATTERN_WITHOUT_ANCHORS + "$"), True), Entry(N_("IPv4 gateway"), "gateway", re.compile("^" + IPV4_PATTERN_WITHOUT_ANCHORS + "$"), True), Entry( N_('IPv6 address or %(auto)s for automatic, %(dhcp)s for DHCP, %(ignore)s to turn off' ) % { "auto": '"auto"', "dhcp": '"dhcp"', "ignore": '"ignore"' }, "ipv6", Fake_RE_IPV6(allow_prefix=True, whitelist=["auto", "dhcp", "ignore"]), True), Entry(N_("IPv6 default gateway"), "ipv6gateway", Fake_RE_IPV6(), True), Entry(N_("Nameservers (comma separated)"), "nameserver", Fake_RE_Nameservers(separator=","), True), Entry(N_("Connect automatically after reboot"), "onboot", EditTUISpoke.CHECK, True), Entry(N_("Apply configuration in installer"), "_apply", EditTUISpoke.CHECK, True), ] def __init__(self, app, data, storage, payload, instclass, ndata): EditTUISpoke.__init__(self, app, data, storage, payload, instclass) self.args = ndata if self.args.bootProto == "dhcp": self.args.ip = "dhcp" if self.args.noipv6: self.args.ipv6 = "ignore" self.args._apply = False self.dialog.wrong_input_message = _("Bad format of the IP address") def refresh(self, args=None): """ Refresh window. """ EditTUISpoke.refresh(self, args) message = _("Configuring device %s.") % self.args.device self._window += [TextWidget(message), ""] return True @property def indirect(self): return True def apply(self): """ Apply our changes. """
def input(self, args, key): """ Handle the input. """ try: num = int(key) except ValueError: return key if num == 1: # set hostname self.app.switch_screen_modal( self.hostname_dialog, Entry(_("Hostname"), "hostname", re.compile(".*$"), True)) self.apply() return INPUT_PROCESSED elif 2 <= num <= len(self.supported_devices) + 1: # configure device devname = self.supported_devices[num - 2] ndata = network.ksdata_from_ifcfg(devname) newspoke = ConfigureNetworkSpoke(self.app, self.data, self.storage, self.payload, self.instclass, ndata) self.app.switch_screen_modal(newspoke) if ndata.ip == "dhcp": ndata.bootProto = "dhcp" ndata.ip = "" else: ndata.bootProto = "static" if not ndata.gateway or not ndata.netmask: self.errors.append( _("Configuration not saved: gateway or netmask missing in static configuration" )) return INPUT_PROCESSED if ndata.ipv6 == "ignore": ndata.noipv6 = True ndata.ipv6 = "" else: ndata.noipv6 = False network.update_settings_with_ksdata(devname, ndata) if ndata._apply: uuid = nm.nm_device_setting_value(devname, "connection", "uuid") try: nm.nm_activate_device_connection(devname, uuid) except (nm.UnmanagedDeviceError, nm.UnknownConnectionError): self.errors.append( _("Can't apply configuration, device activation failed." )) self.apply() return INPUT_PROCESSED else: return key
class ConfigureNetworkSpoke(EditTUISpoke): """ Spoke to set various configuration options for net devices. """ title = N_("Device configuration") category = "network" edit_fields = [ Entry(N_('IPv4 address or %s for DHCP') % '"dhcp"', "ip", re.compile("^(?:" + IPV4_PATTERN_WITHOUT_ANCHORS + "|dhcp)$"), True), Entry(N_("IPv4 netmask"), "netmask", re.compile("^" + IPV4_NETMASK_WITHOUT_ANCHORS + "$"), True), Entry(N_("IPv4 gateway"), "gateway", re.compile("^" + IPV4_PATTERN_WITHOUT_ANCHORS + "$"), True), Entry(N_('IPv6 address[/prefix] or %(auto)s for automatic, %(dhcp)s for DHCP, %(ignore)s to turn off') % {"auto": '"auto"', "dhcp": '"dhcp"', "ignore": '"ignore"'}, "ipv6", check_ipv6_config, True), Entry(N_("IPv6 default gateway"), "ipv6gateway", check_ipv6_address, True), Entry(N_("Nameservers (comma separated)"), "nameserver", check_nameservers, True), Entry(N_("Connect automatically after reboot"), "onboot", EditTUISpoke.CHECK, True), Entry(N_("Apply configuration in installer"), "_apply", EditTUISpoke.CHECK, True), ] def __init__(self, app, data, storage, payload, instclass, ndata): EditTUISpoke.__init__(self, app, data, storage, payload, instclass) self.args = ndata if self.args.bootProto == "dhcp": self.args.ip = "dhcp" if self.args.noipv6: self.args.ipv6 = "ignore" self.args._apply = False def refresh(self, args=None): """ Refresh window. """ EditTUISpoke.refresh(self, args) message = _("Configuring device %s.") % self.args.device self._window += [TextWidget(message), ""] return True def input(self, args, key): self.dialog.wrong_input_message = _("Bad format of the IP address") try: field = self.visible_fields[int(key)-1] except (ValueError, IndexError): pass else: if field.attribute == "netmask": self.dialog.wrong_input_message = _("Bad format of the netmask") return EditTUISpoke.input(self, args, key) @property def indirect(self): return True def apply(self): """ Apply our changes. """
class SpecifyRepoSpoke(EditTUISpoke, SourceSwitchHandler): """ Specify the repo URL here if closest mirror not selected. """ category = SoftwareCategory HTTP = 1 HTTPS = 2 FTP = 3 edit_fields = [Entry(N_("Repo URL"), "url", re.compile(".*$"), True)] def __init__(self, data, storage, payload, instclass, protocol): EditTUISpoke.__init__(self, data, storage, payload, instclass) SourceSwitchHandler.__init__(self) self.title = N_("Specify Repo Options") self.protocol = protocol self.args = self.data.method def refresh(self, args=None): """ Refresh window. """ EditTUISpoke.refresh(self, args) @property def indirect(self): return True def apply(self): """ Apply all of our changes. """ if self.protocol == SpecifyRepoSpoke.HTTP and not self.args.url.startswith( "http://"): url = "http://" + self.args.url elif self.protocol == SpecifyRepoSpoke.HTTPS and not self.args.url.startswith( "https://"): url = "https://" + self.args.url elif self.protocol == SpecifyRepoSpoke.FTP and not self.args.url.startswith( "ftp://"): url = "ftp://" + self.args.url else: # protocol either unknown or entry already starts with a protocol # specification url = self.args.url self.set_source_url(url)
class UserSpoke(FirstbootSpokeMixIn, EditTUISpoke): """ .. inheritance-diagram:: UserSpoke :parts: 3 """ title = N_("User creation") category = UserSettingsCategory edit_fields = [ Entry("Create user", "_create", EditTUISpoke.CHECK, True), Entry("Fullname", "gecos", GECOS_VALID, lambda self, args: args._create), Entry("Username", "name", USERNAME_VALID, lambda self, args: args._create), Entry("Use password", "_use_password", EditTUISpoke.CHECK, lambda self, args: args._create), Entry("Password", "_password", EditTUISpoke.PASSWORD, lambda self, args: args._use_password and args._create), Entry("Administrator", "_admin", EditTUISpoke.CHECK, lambda self, args: args._create), Entry("Groups", "_groups", GROUPLIST_SIMPLE_VALID, lambda self, args: args._create) ] @classmethod def should_run(cls, environment, data): # the user spoke should run always in the anaconda and in firstboot only # when doing reconfig or if no user has been created in the installation if environment == ANACONDA_ENVIRON: return True elif environment == FIRSTBOOT_ENVIRON and data is None: # cannot decide, stay in the game and let another call with data # available (will come) decide return True elif environment == FIRSTBOOT_ENVIRON and data and \ (data.firstboot.firstboot == FIRSTBOOT_RECONFIG or \ len(data.user.userList) == 0): return True else: return False def __init__(self, app, data, storage, payload, instclass): FirstbootSpokeMixIn.__init__(self) EditTUISpoke.__init__(self, app, data, storage, payload, instclass, "user") self.dialog.wrong_input_message = _( "You have provided an invalid user name.\n" "Tip: Keep your user name shorter than 32 " "characters and do not use spaces.\n") if self.data.user.userList: self.args = self.data.user.userList[0] self.args._create = True else: self.args = self.data.UserData() self.args._create = False self.args._use_password = self.args.isCrypted or self.args.password # Keep the password separate from the kickstart data until apply() # so that all of the properties are set at once self.args._password = "" self.errors = [] def refresh(self, args=None): self.args._admin = "wheel" in self.args.groups self.args._groups = ", ".join(self.args.groups) # if we have any errors, display them while self.errors: print(self.errors.pop()) return EditTUISpoke.refresh(self, args) @property def completed(self): """ Verify a user is created; verify pw is set if option checked. """ if len(self.data.user.userList) > 0: if self.args._use_password and not bool(self.args.password or self.args.isCrypted): return False else: return True else: return False @property def showable(self): return not (self.completed and flags.automatedInstall and self.data.user.seen and not self.dialog.policy.changesok) @property def mandatory(self): """ Only mandatory if the root pw hasn't been set in the UI eg. not mandatory if the root account was locked in a kickstart """ return not self.data.rootpw.password and not self.data.rootpw.lock @property def status(self): if len(self.data.user.userList) == 0: return _("No user will be created") elif self.args._use_password and not bool(self.args.password or self.args.isCrypted): return _("You must set a password") elif "wheel" in self.data.user.userList[0].groups: return _("Administrator %s will be created" ) % self.data.user.userList[0].name else: return _( "User %s will be created") % self.data.user.userList[0].name def apply(self): if self.args.gecos and not self.args.name: username = guess_username(self.args.gecos) if not USERNAME_VALID.match(username): self.errors.append(_("Invalid user name: %s.\n") % username) else: self.args.name = guess_username(self.args.gecos) self.args.groups = [ g.strip() for g in self.args._groups.split(",") if g ] # Add or remove the user from wheel group if self.args._admin and "wheel" not in self.args.groups: self.args.groups.append("wheel") elif not self.args._admin and "wheel" in self.args.groups: self.args.groups.remove("wheel") # Add or remove the user from userlist as needed if self.args._create and (self.args not in self.data.user.userList and self.args.name): self.data.user.userList.append(self.args) elif (not self.args._create) and (self.args in self.data.user.userList): self.data.user.userList.remove(self.args) # encrypt and store password only if user entered anything; this should # preserve passwords set via kickstart if self.args._use_password and len(self.args._password) > 0: self.args.password = self.args._password self.args.isCrypted = True self.args.password_kickstarted = False # clear pw when user unselects to use pw else: self.args.password = "" self.args.isCrypted = False self.args.password_kickstarted = False
class UserSpoke(FirstbootSpokeMixIn, EditTUISpoke): title = _("Create user") category = "password" edit_fields = [ Entry("Create user", "_create", EditTUISpoke.CHECK, True), Entry("Fullname", "gecos", GECOS_VALID, lambda self, args: args._create), Entry("Username", "name", USERNAME_VALID, lambda self, args: args._create), Entry("Use password", "_use_password", EditTUISpoke.CHECK, lambda self, args: args._create), Entry("Password", "_password", EditTUISpoke.PASSWORD, lambda self, args: args._use_password and args._create), Entry("Administrator", "_admin", EditTUISpoke.CHECK, lambda self, args: args._create), Entry("Groups", "_groups", GROUPLIST_SIMPLE_VALID, lambda self, args: args._create) ] @classmethod def should_run(cls, environment, data): # the user spoke should run always in the anaconda and in firstboot only # when doing reconfig or if no user has been created in the installation if environment == ANACONDA_ENVIRON: return True elif environment == FIRSTBOOT_ENVIRON and data is None: # cannot decide, stay in the game and let another call with data # available (will come) decide return True elif environment == FIRSTBOOT_ENVIRON and data and \ (data.firstboot.firstboot == FIRSTBOOT_RECONFIG or \ len(data.user.userList) == 0): return True else: return False def __init__(self, app, data, storage, payload, instclass): FirstbootSpokeMixIn.__init__(self) EditTUISpoke.__init__(self, app, data, storage, payload, instclass) if self.data.user.userList: self.args = self.data.user.userList[0] self.args._create = True else: self.args = self.data.UserData() self.args._create = False self.args._use_password = self.args.isCrypted or self.args.password # Keep the password separate from the kickstart data until apply() # so that all of the properties are set at once self.args._password = "" def refresh(self, args=None): self.args._admin = "wheel" in self.args.groups self.args._groups = ", ".join(self.args.groups) return EditTUISpoke.refresh(self, args) @property def completed(self): """ Verify a user is created; verify pw is set if option checked. """ if len(self.data.user.userList) > 0: if self.args._use_password and not bool(self.args.password or self.args.isCrypted): return False else: return True else: return False @property def mandatory(self): """ Only mandatory if root account is disabled. """ return not bool(self.data.rootpw.password) or self.data.rootpw.lock @property def status(self): if len(self.data.user.userList) == 0: return _("No user will be created") elif self.args._use_password and not bool(self.args.password or self.args.isCrypted): return _("You must set a password") elif "wheel" in self.data.user.userList[0].groups: return _("Administrator %s will be created" ) % self.data.user.userList[0].name else: return _( "User %s will be created") % self.data.user.userList[0].name def _sabayon_extend_groups(self): # Sabayon: make user be part of all groups the LIVE_USER is. from pyanaconda.sabayon.const import LIVE_USER import grp # Sabayon: get admin user groups from LIVE_USER def get_all_groups(user): for group in grp.getgrall(): if user in group.gr_mem: yield group.gr_name groups = list(get_all_groups(LIVE_USER)) for group in groups: if group not in self.args.groups: self.args.groups.append(group) def apply(self): if self.args.gecos and not self.args.name: username = guess_username(self.args.gecos) if USERNAME_VALID.match(username): self.args.name = guess_username(self.args.gecos) self.args.groups = [ g.strip() for g in self.args._groups.split(",") if g ] self._sabayon_extend_groups() # Add or remove the user from wheel group if self.args._admin and "wheel" not in self.args.groups: self.args.groups.append("wheel") elif not self.args._admin and "wheel" in self.args.groups: self.args.groups.remove("wheel") # Add or remove the user from userlist as needed if self.args._create and (self.args not in self.data.user.userList): self.data.user.userList.append(self.args) elif (not self.args._create) and (self.args in self.data.user.userList): self.data.user.userList.remove(self.args) # encrypt and store password only if user entered anything; this should # preserve passwords set via kickstart if self.args._use_password and len(self.args._password) > 0: self.args.password = self.args._password self.args.isCrypted = True self.args.password_kickstarted = False # clear pw when user unselects to use pw else: self.args.password = "" self.args.isCrypted = False self.args.password_kickstarted = False
def _set_hostname_callback(self, data): # set hostname entry = Entry(_("Host Name"), "hostname", re.compile(".*$"), True) ScreenHandler.push_screen_modal(self.hostname_dialog, entry) self.redraw() self.apply()
class HomerSettingsSpoke(FirstbootSpokeMixIn, EditTUISpoke): title = N_("Homer 5") category = "localization" # simple RE used to specify we only accept a single word as a valid input _valid_input = re.compile(r'\w') edit_fields = [ Entry("DB User Name", "homer_user", _valid_input, True), Entry("DB User Password", "homer_password", EditTUISpoke.PASSWORD, True), Entry("DB Name", "homer_database_name", _valid_input, True), Entry("DB Host", "homer_database_host", _valid_input, True), Entry("DB WEB Server Type", "homer_webserver_type", _valid_input, True), ] def __init__(self, app, data, storage, payload, instclass): EditTUISpoke.__init__(self, app, data, storage, payload, instclass) self.args = _EditData() def initialize(self): EditTUISpoke.initialize(self) def refresh(self, args=None): self.homer_user = self.data.addons.org_sipcapture_homer.homer_user self.homer_password = self.data.addons.org_sipcapture_homer.homer_password self.homer_database_name = self.data.addons.org_sipcapture_homer.homer_database_name self.homer_database_host = self.data.addons.org_sipcapture_homer.homer_database_host self.homer_webserver_type = self.data.addons.org_sipcapture_homer.homer_webserver_type return True def apply(self): self.data.addons.org_sipcapture_homer.homer_user = self.homer_user self.data.addons.org_sipcapture_homer.homer_password = self.homer_password self.data.addons.org_sipcapture_homer.homer_database_name = self.homer_database_name self.data.addons.org_sipcapture_homer.homer_database_host = self.homer_database_host self.data.addons.org_sipcapture_homer.homer_webserver_type = self.homer_webserver_type def prompt(self, args=None): return "1) DB User Name%s\n2) DB User Password%s\n3) DB name%s\n4) DB host%s\n5) WEB Server Type%s\n%s: " % ( ((" [%s]" % self.args.homer_user) if self.args.homer_user else "[!]"), ((" [*****]") if self.args.homer_password else " [!]"), ((" [%s]" % self.args.homer_database_name) if self.args.homer_database_name else "[!]"), ((" [%s]" % self.args.homer_database_host) if self.args.homer_database_host else "[!]"), ((" [%s]" % self.args.homer_webserver_type) if self.args.homer_webserver_type else "[!]"), "Please, make your choice from above ['q' to quit | 'c' to return to main menu]: " ) def execute(self): pass @property def completed(self): return bool(self.data.addons.org_sipcapture_homer.homer_user and self.data.addons.org_sipcapture_homer.homer_password and self.data.addons.org_sipcapture_homer.homer_database_name and self.data.addons.org_sipcapture_homer.homer_database_host and self.data.addons.org_sipcapture_homer.homer_webserver_type); @property def status(self): return "%sonfigured" % ("C" if self.data.addons.org_sipcapture_homer.homer_user and self.data.addons.org_sipcapture_homer.homer_password and self.data.addons.org_sipcapture_homer.homer_database_name and self.data.addons.org_sipcapture_homer.homer_database_host and self.data.addons.org_sipcapture_homer.homer_webserver_type else "Not c");
class UserSpoke(EditTUISpoke): """ .. inheritance-diagram:: UserSpoke :parts: 3 """ title = N_("User creation") category = UserSettingsCategory edit_fields = [ Entry("Create user", "_create", EditTUISpoke.CHECK, True), Entry("Username", "name", check_username, lambda self, args: args._create), Entry("Use password", "_use_password", EditTUISpoke.CHECK, lambda self, args: args._create), Entry("Password", "_password", EditTUISpoke.PASSWORD, lambda self, args: args._use_password and args._create), Entry("Groups", "_groups", GROUPLIST_SIMPLE_VALID, lambda self, args: args._create) ] @classmethod def should_run(cls, environment, data): # the user spoke should run always in the anaconda and in firstboot only # when doing reconfig or if no user has been created in the installation if environment == ANACONDA_ENVIRON: return True elif environment == FIRSTBOOT_ENVIRON and data is None: # cannot decide, stay in the game and let another call with data # available (will come) decide return True elif environment == FIRSTBOOT_ENVIRON and data and \ (data.firstboot.firstboot == FIRSTBOOT_RECONFIG or \ len(data.user.userList) == 0): return True else: return False def __init__(self, app, data, storage, payload, instclass): EditTUISpoke.__init__(self, app, data, storage, payload, instclass, "user") if self.data.user.userList: self.args = self.data.user.userList[0] self.args._create = True else: self.args = self.data.UserData() self.args._create = False self.args._use_password = self.args.isCrypted or self.args.password # Keep the password separate from the kickstart data until apply() # so that all of the properties are set at once self.args._password = "" self.errors = [] def refresh(self, args=None): self.args._groups = ", ".join(self.args.groups) # if we have any errors, display them while self.errors: print(self.errors.pop()) return EditTUISpoke.refresh(self, args) @property def completed(self): """ Verify a user is created; verify pw is set if option checked. """ if len(self.data.user.userList) > 0: if self.args._use_password and not bool(self.args.password or self.args.isCrypted): return False else: return True else: return False @property def showable(self): return not (self.completed and flags.automatedInstall and self.data.user.seen and not self.dialog.policy.changesok) @property def mandatory(self): return True @property def status(self): if len(self.data.user.userList) == 0: return _("No user will be created") elif self.args._use_password and not bool(self.args.password or self.args.isCrypted): return _("You must set a password") elif "wheel" in self.data.user.userList[0].groups: return _("Administrator %s will be created" ) % self.data.user.userList[0].name else: return _( "User %s will be created") % self.data.user.userList[0].name def input(self, args, key): self.dialog.wrong_input_message = None try: field = self.visible_fields[int(key) - 1] except (ValueError, IndexError): pass else: if field.attribute == "gecos": self.dialog.wrong_input_message = _( "Full name can't contain the ':' character") elif field.attribute == "name": # more granular message is returned by check_username pass elif field.attribute == "_groups": self.dialog.wrong_input_message = _( "Either a group name in the group list is invalid or groups are not separated by a comma" ) return EditTUISpoke.input(self, args, key) def apply(self): self.args.groups = [ g.strip() for g in self.args._groups.split(",") if g ] # Add the user to the wheel and qubes groups if "wheel" not in self.args.groups: self.args.groups.append("wheel") if "qubes" not in self.args.groups: self.args.groups.append("qubes") # Add or remove the user from userlist as needed if self.args._create and (self.args not in self.data.user.userList and self.args.name): self.data.user.userList.append(self.args) elif (not self.args._create) and (self.args in self.data.user.userList): self.data.user.userList.remove(self.args) # encrypt and store password only if user entered anything; this should # preserve passwords set via kickstart if self.args._use_password and len(self.args._password) > 0: self.args.password = self.args._password self.args.isCrypted = True self.args.password_kickstarted = False # clear pw when user unselects to use pw else: self.args.password = "" self.args.isCrypted = False self.args.password_kickstarted = False
def input(self, args, key): """ Handle the input. """ try: num = int(key) except ValueError: return super(NetworkSpoke, self).input(args, key) if num == 1: # set hostname self.app.switch_screen_modal( self.hostname_dialog, Entry(_("Host Name"), "hostname", re.compile(".*$"), True)) self.apply() return INPUT_PROCESSED elif 2 <= num <= len(self.supported_devices) + 1: # configure device devname = self.supported_devices[num - 2] ndata = network.ksdata_from_ifcfg(devname) if not ndata: try: nm.nm_device_setting_value(devname, "connection", "uuid") except nm.SettingsNotFoundError: pass else: log.debug( "network: dumping ifcfg file for in-memory connection %s", devname) nm.nm_update_settings_of_device( devname, [['connection', 'id', devname, None]]) ndata = network.ksdata_from_ifcfg(devname) if not ndata: log.debug("network: can't find any connection for %s", devname) self.errors.append(_("Configuration of device not found")) return INPUT_PROCESSED newspoke = ConfigureNetworkSpoke(self.app, self.data, self.storage, self.payload, self.instclass, ndata) self.app.switch_screen_modal(newspoke) if ndata.ip == "dhcp": ndata.bootProto = "dhcp" ndata.ip = "" else: ndata.bootProto = "static" if not ndata.netmask: self.errors.append( _("Configuration not saved: netmask missing in static configuration" )) return INPUT_PROCESSED if ndata.ipv6 == "ignore": ndata.noipv6 = True ndata.ipv6 = "" else: ndata.noipv6 = False network.update_settings_with_ksdata(devname, ndata) network.update_onboot_value(devname, ndata.onboot, ksdata=None, root_path="") if ndata._apply: self._apply = True uuid = nm.nm_device_setting_value(devname, "connection", "uuid") try: nm.nm_activate_device_connection(devname, uuid) except (nm.UnmanagedDeviceError, nm.UnknownConnectionError): self.errors.append( _("Can't apply configuration, device activation failed." )) self.apply() return INPUT_PROCESSED else: return key