Esempio n. 1
0
class IntegrationForm(Form):
    def __init__(self, initial):
        super().__init__(initial=initial)

    custom_path = MountField(_("Mount Location"),
                             help=_("Location for the automount"))
    custom_mount_opt = StringField(
        _("Mount Option"), help=_("Mount option passed for the automount"))
    gen_host = BooleanField(
        _("Enable Host Generation"),
        help=_("Selecting enables /etc/host re-generation at every start"))
    gen_resolvconf = BooleanField(
        _("Enable resolv.conf Generation"),
        help=_(
            "Selecting enables /etc/resolv.conf re-generation at every start"))
    gui_integration = BooleanField(
        _("GUI Integration"),
        help=
        _("Selecting enables automatic DISPLAY environment set-up. Third-party X server required."
          ))

    def validate_custom_path(self):
        p = self.custom_path.value
        if p != "" and (re.fullmatch(r"(/[^/ ]*)+/?", p) is None):
            return _(
                "Mount location must be a absolute UNIX path without space.")

    def validate_custom_mount_opt(self):
        o = self.custom_mount_opt.value
        # filesystem independent mount option
        fsimo = [
            r"async", r"(no)?atime", r"(no)?auto",
            r"(fs|def|root)?context=\w+", r"(no)?dev", r"(no)?diratime",
            r"dirsync", r"(no)?exec", r"group", r"(no)?iversion", r"(no)?mand",
            r"_netdev", r"nofail", r"(no)?relatime", r"(no)?strictatime",
            r"(no)?suid", r"owner", r"remount", r"ro", r"rw", r"_rnetdev",
            r"sync", r"(no)?user", r"users"
        ]
        # DrvFs filesystem mount option
        drvfsmo = r"case=(dir|force|off)|metadata|(u|g)id=\d+|(u|f|d)mask=\d+|"
        fso = "{0}{1}".format(drvfsmo, '|'.join(fsimo))

        if o != "":
            e_t = ""
            p = o.split(',')
            x = True
            for i in p:
                if i == "":
                    e_t += _("an empty entry detected; ")
                    x = x and False
                elif re.fullmatch(fso, i) is not None:
                    x = x and True
                else:
                    e_t += _("{} is not a valid mount option; ").format(i)
                    x = x and False
            if not x:
                return _(
                    "Invalid Input: {}Please check "
                    "https://docs.microsoft.com/en-us/windows/wsl/wsl-config#mount-options "
                    "for correct valid input").format(e_t)
Esempio n. 2
0
class GuidedChoiceForm(SubForm):

    disk = ChoiceField(caption=NO_CAPTION, help=NO_HELP, choices=["x"])
    use_lvm = BooleanField(_("Set up this disk as an LVM group"), help=NO_HELP)
    lvm_options = SubFormField(LVMOptionsForm, "", help=NO_HELP)

    def __init__(self, parent):
        super().__init__(parent)
        options = []
        tables = []
        initial = -1
        for disk in parent.model.all_disks():
            for obj, cells in summarize_device(disk):
                table = TablePile([TableRow(cells)])
                tables.append(table)
                enabled = False
                if obj is disk and disk.size > 6 * (2**30):
                    enabled = True
                    if initial < 0:
                        initial = len(options)
                options.append(Option((table, enabled, obj)))
        t0 = tables[0]
        for t in tables[1:]:
            t0.bind(t)
        self.disk.widget.options = options
        self.disk.widget.index = initial
        connect_signal(self.use_lvm.widget, 'change', self._toggle)
        self.lvm_options.enabled = self.use_lvm.value

    def _toggle(self, sender, val):
        self.lvm_options.enabled = val
Esempio n. 3
0
class LVMOptionsForm(SubForm):
    def __init__(self, parent):
        super().__init__(parent)
        connect_signal(self.encrypt.widget, 'change', self._toggle)
        self.luks_options.enabled = self.encrypt.value

    def _toggle(self, sender, val):
        self.luks_options.enabled = val

    encrypt = BooleanField(_("Encrypt the LVM group with LUKS"), help=NO_HELP)
    luks_options = SubFormField(LUKSOptionsForm, "", help=NO_HELP)
Esempio n. 4
0
class VolGroupForm(CompoundDiskForm):
    def __init__(self, model, possible_components, initial, vg_names,
                 deleted_vg_names):
        self.vg_names = vg_names
        self.deleted_vg_names = deleted_vg_names
        super().__init__(model, possible_components, initial)
        connect_signal(self.encrypt.widget, 'change', self._change_encrypt)
        setup_password_validation(self, _("passphrases"))
        self._change_encrypt(None, self.encrypt.value)

    name = VGNameField(_("Name:"))
    devices = MultiDeviceField(_("Devices:"))
    size = ReadOnlyField(_("Size:"))
    encrypt = BooleanField(_("Create encrypted volume"))
    password = PasswordField(_("Passphrase:"))
    confirm_password = PasswordField(_("Confirm passphrase:"))

    def _change_encrypt(self, sender, new_value):
        self.password.enabled = new_value
        self.confirm_password.enabled = new_value
        if not new_value:
            self.password.validate()
            self.confirm_password.validate()

    def validate_devices(self):
        if len(self.devices.value) < 1:
            return _("Select at least one device to be part of the volume "
                     "group.")

    def validate_name(self):
        v = self.name.value
        if not v:
            return _("The name of a volume group cannot be empty")
        if v.startswith('-'):
            return _("The name of a volume group cannot start with a hyphen")
        if v in self.vg_names:
            return _("There is already a volume group named '{name}'").format(
                name=self.name.value)
        if v in ('.', '..', 'md') or os.path.exists('/dev/' + v):
            if v not in self.deleted_vg_names:
                return _("{name} is not a valid name for a volume "
                         "group").format(name=v)

    def validate_password(self):
        if self.encrypt.value and len(self.password.value) < 1:
            return _("Passphrase must be set")

    def validate_confirm_password(self):
        if self.encrypt.value and \
          self.password.value != self.confirm_password.value:
            return _("Passphrases do not match")
Esempio n. 5
0
class IdentityForm(Form):
    def __init__(self, reserved_usernames, initial):
        self.reserved_usernames = reserved_usernames
        super().__init__(initial=initial)

    username = UsernameField(
        _("Pick a username:"******"The username does not need to match your Windows username"))
    password = PasswordField(_("Choose a password:"******"Confirm your password:"******"Show Advanced Options Next Page"))

    def validate_username(self):
        username = self.username.value
        if len(username) < 1:
            return _("Username missing")

        if len(username) > USERNAME_MAXLEN:
            return _("Username too long, must be less than {limit}").format(
                limit=USERNAME_MAXLEN)

        if not re.match(r'[a-z_][a-z0-9_-]*', username):
            return _("Username must match NAME_REGEX, i.e. [a-z_][a-z0-9_-]*")

        if username in self.reserved_usernames:
            return _(
                'The username "{username}" is reserved for use by the system.'
            ).format(username=username)

    def validate_password(self):
        if len(self.password.value) < 1:
            return _("Password must be set")

    def validate_confirm_password(self):
        if self.password.value != self.confirm_password.value:
            return _("Passwords do not match")

    def validate_show_advanced(self):
        pass
Esempio n. 6
0
class PartitionForm(Form):

    def __init__(self, model, max_size, initial, lvm_names, device):
        self.model = model
        self.device = device
        self.existing_fs_type = None
        if device:
            ofstype = device.original_fstype()
            if ofstype:
                self.existing_fs_type = ofstype
        initial_path = initial.get('mount')
        self.mountpoints = {
            m.path: m.device.volume for m in self.model.all_mounts()
            if m.path != initial_path}
        self.max_size = max_size
        if max_size is not None:
            self.size_str = humanize_size(max_size)
            self.size.caption = _("Size (max {}):").format(self.size_str)
        self.lvm_names = lvm_names
        super().__init__(initial)
        if max_size is None:
            self.remove_field('size')
        connect_signal(self.fstype.widget, 'select', self.select_fstype)
        self.form_pile = None
        self.select_fstype(None, self.fstype.widget.value)

    def select_fstype(self, sender, fstype):
        show_use = False
        if fstype is None and self.existing_fs_type is not None:
            self.mount.widget.disable_unsuitable_mountpoints_for_existing_fs()
            self.mount.value = self.mount.value
        else:
            self.mount.widget.enable_common_mountpoints()
            self.mount.value = self.mount.value
        if fstype is None:
            if self.existing_fs_type == "swap":
                show_use = True
        if self.form_pile is not None:
            for i, (w, o) in enumerate(self.form_pile.contents):
                if w is self.mount._table and show_use:
                    self.form_pile.contents[i] = (self.use_swap._table, o)
                elif w is self.use_swap._table and not show_use:
                    self.form_pile.contents[i] = (self.mount._table, o)
        if getattr(self.device, 'flag', None) != "boot":
            fstype_for_check = fstype
            if fstype_for_check is None:
                fstype_for_check = self.existing_fs_type
            self.mount.enabled = self.model.is_mounted_filesystem(
                fstype_for_check)
        self.fstype.value = fstype
        self.mount.showing_extra = False
        self.mount.validate()

    name = LVNameField(_("Name: "))
    size = SizeField()
    fstype = FSTypeField(_("Format:"))
    mount = MountField(_("Mount:"))
    use_swap = BooleanField(
        _("Use as swap"),
        help=_("Use this swap partition in the installed system."))

    def clean_size(self, val):
        if not val:
            return self.max_size
        suffixes = ''.join(HUMAN_UNITS) + ''.join(HUMAN_UNITS).lower()
        if val[-1] not in suffixes:
            val += self.size_str[-1]
        if val == self.size_str:
            return self.max_size
        else:
            return dehumanize_size(val)

    def clean_mount(self, val):
        if self.model.is_mounted_filesystem(self.fstype):
            return val
        else:
            return None

    def validate_name(self):
        if self.lvm_names is None:
            return None
        v = self.name.value
        if not v:
            return _("The name of a logical volume cannot be empty")
        if v.startswith('-'):
            return _("The name of a logical volume cannot start with a hyphen")
        if v in ('.', '..', 'snapshot', 'pvmove'):
            return _("A logical volume may not be called {}").format(v)
        for substring in ['_cdata', '_cmeta',   '_corig',  '_mlog',  '_mimage',
                          '_pmspare',  '_rimage',  '_rmeta',  '_tdata',
                          '_tmeta', '_vorigin']:
            if substring in v:
                return _('The name of a logical volume may not contain '
                         '"{}"').format(substring)
        if v in self.lvm_names:
            return _("There is already a logical volume named {}.").format(
                self.name.value)

    def validate_mount(self):
        mount = self.mount.value
        if mount is None:
            return
        # /usr/include/linux/limits.h:PATH_MAX
        if len(mount) > 4095:
            return _('Path exceeds PATH_MAX')
        dev = self.mountpoints.get(mount)
        if dev is not None:
            return _("{} is already mounted at {}.").format(
                dev.label.title(), mount)
        if self.existing_fs_type is not None:
            if self.fstype.value is None:
                if mount in common_mountpoints:
                    if mount not in suitable_mountpoints_for_existing_fs:
                        self.mount.show_extra(
                            ('info_error',
                             _("Mounting an existing filesystem at {} is "
                               "usually a bad idea, proceed only with "
                               "caution.").format(mount)))

    def as_rows(self):
        r = super().as_rows()
        if self.existing_fs_type == "swap":
            exclude = self.mount._table
        else:
            exclude = self.use_swap._table
        i = r.index(exclude)
        del r[i-1:i+1]
        return r
Esempio n. 7
0
class SSHForm(Form):

    install_server = BooleanField(_("Install OpenSSH server"))

    ssh_import_id = ChoiceField(
        _("Import SSH identity:"),
        choices=[
            (_("No"), True, None),
            (_("from GitHub"), True, "gh"),
            (_("from Launchpad"), True, "lp"),
            ],
        help=_("You can import your SSH keys from GitHub or Launchpad."))

    import_username = UsernameField(_ssh_import_data[None]['caption'])

    pwauth = BooleanField(_("Allow password authentication over SSH"))

    cancel_label = _("Back")

    def __init__(self, initial):
        super().__init__(initial=initial)
        connect_signal(
            self.install_server.widget, 'change', self._toggle_server)
        self._toggle_server(None, self.install_server.value)

    def _toggle_server(self, sender, new_value):
        if new_value:
            self.ssh_import_id.enabled = True
            self.import_username.enabled = self.ssh_import_id.value is not None
            self.pwauth.enabled = self.ssh_import_id.value is not None
        else:
            self.ssh_import_id.enabled = False
            self.import_username.enabled = False
            self.pwauth.enabled = False

    # validation of the import username does not read from
    # ssh_import_id.value because it is sometimes done from the
    # 'select' signal of the import id selector, which is called
    # before the import id selector's value has actually changed. so
    # the signal handler stuffs the value here before doing
    # validation (yes, this is a hack).
    ssh_import_id_value = None

    def validate_import_username(self):
        if self.ssh_import_id_value is None:
            return
        username = self.import_username.value
        if len(username) == 0:
            return _("This field must not be blank.")
        if len(username) > SSH_IMPORT_MAXLEN:
            return _("SSH id too long, must be < ") + str(SSH_IMPORT_MAXLEN)
        if self.ssh_import_id_value == 'lp':
            lp_regex = r"^[a-z0-9][a-z0-9\+\.\-]*$"
            if not re.match(lp_regex, self.import_username.value):
                return _("A Launchpad username must start with a letter or "
                         "number. All letters must be lower-case. The "
                         "characters +, - and . are also allowed after "
                         "the first character.""")
        elif self.ssh_import_id_value == 'gh':
            if not re.match(r'^[a-zA-Z0-9\-]+$', username):
                return _("A GitHub username may only contain alphanumeric "
                         "characters or single hyphens, and cannot begin or "
                         "end with a hyphen.")