Beispiel #1
0
def enable_spi():
    # FIXME: instead of rebooting, add a reboot_required property to
    # Changed/Unchanged and allow chaining these.
    #
    # e.g.
    #
    # c = some_operation()
    # c = c.chain(another_operation, msg=....)
    #
    # return c
    #
    # at any point in time, c.reboot_required can be resolved, either
    # in a plan/operation or by the driver ("reboot_if_needed()")

    # FIXME: check for /etc/modprobe.d/raspi-blacklist.conf
    #        mentioned at https://www.raspberrypi.org/documentation/
    #                             hardware/raspberrypi/spi/README.md

    with fs.edit('/boot/config.txt', create=False) as boot:
        boot.insert_line('dtparam=spi=on')
        boot.insert_line('dtoverlay=spi-bcm2835-overlay')

    if boot.changed:
        linux.enable_module('spi_bcm2835', load=False)
        return Changed('Enabled SPI, need to reboot now')

    if linux.enable_module('spi_bcm2835').changed:
        return Changed('SPI kernel module enabled')

    return Unchanged('SPI already enabled')
Beispiel #2
0
def set_password(name, password=None, hashed=False, salt=None):
    if salt is None:
        salt = hashlib.sha1(os.urandom(64)).hexdigest()

    if not hashed:
        # hash using sha256
        hash = crypt(password, "$6$" + salt)
    else:
        hash = password

    # at this point, we have a hashed password
    with fs.edit('/etc/shadow', create=False) as shadow:
        new_lines = []

        for line in shadow.lines():
            entry = ShadowEntry.from_line(line)

            if entry.name == name:
                # we need to check if the password already matches (with a
                # different salt)

                pwc = entry.password_encrypted

                need_update = True

                if hashed:
                    # we were supplied a hashed password, simply compare the
                    # hashes
                    need_update = (pwc != password)
                else:
                    # not hashed
                    if '$' in pwc:
                        lead = pwc[:pwc.rindex('$')]
                        need_update = (crypt(password, lead) != pwc)

                if need_update:
                    entry = entry._replace(password_encrypted=hash)
                    new_lines.append(entry.to_line())
                    continue

            new_lines.append(line)

        shadow.set_lines(new_lines)

    if shadow.changed:
        return Changed(msg='Updated password for user {}'.format(name))

    return Unchanged(msg='Password for {} already set'.format(name))
Beispiel #3
0
def set_password(name, password=None, hashed=False, salt=None):
    if salt is None:
        salt = hashlib.sha1(os.urandom(64)).hexdigest()

    if not hashed:
        # hash using sha256
        hash = crypt(password, "$6$" + salt)
    else:
        hash = password

    # at this point, we have a hashed password
    with fs.edit('/etc/shadow', create=False) as shadow:
        new_lines = []

        for line in shadow.lines():
            entry = ShadowEntry.from_line(line)

            if entry.name == name:
                # we need to check if the password already matches (with a
                # different salt)

                pwc = entry.password_encrypted

                need_update = True

                if hashed:
                    # we were supplied a hashed password, simply compare the
                    # hashes
                    need_update = (pwc != password)
                else:
                    # not hashed
                    if '$' in pwc:
                        lead = pwc[:pwc.rindex('$')]
                        need_update = (crypt(password, lead) != pwc)

                if need_update:
                    entry = entry._replace(password_encrypted=hash)
                    new_lines.append(entry.to_line())
                    continue

            new_lines.append(line)

        shadow.set_lines(new_lines)

    if shadow.changed:
        return Changed(msg='Updated password for user {}'.format(name))

    return Unchanged(msg='Password for {} already set'.format(name))
Beispiel #4
0
def enable_systemd():
    changed = False
    changed |= apt.install_packages(['systemd']).changed

    with fs.edit('/boot/cmdline.txt', create=False) as e:
        flag = 'init=/bin/systemd'
        lines = e.lines()
        assert len(lines) == 1

        if flag not in lines[0]:
            lines[0] += ' ' + flag
            e.set_lines(lines)

    changed |= e.changed

    if changed:
        return Changed(msg='Installed systemd')

    return Unchanged(msg='systemd already active')
Beispiel #5
0
def enable_module(module_name, load=True, modules_file="/etc/modules"):
    mods = info["linux.modules"]

    c = False

    # load module if not loaded
    if load and module_name not in mods:
        proc.run(["modprobe", module_name])
        c = True

    # ensure module is found in modules_files
    with fs.edit(modules_file) as mf:
        mf.insert_line(module_name)

    c |= mf.changed

    if c:
        return Changed(msg="Kernel module {}, enabled in {}".format(module_name, modules_file))

    return Unchanged(msg="Kernel module {} already enabled in {}".format(module_name, modules_file))
Beispiel #6
0
def set_unlocked_no_password(names):
    # FIXME: decide API guidelines, add typechecking once Python3 is available
    # example: passing a string to names will work, but result in non-sensical
    # results.
    with fs.edit('/etc/shadow', create=False) as shadow:
        new_lines = []

        for line in shadow.lines():
            entry = ShadowEntry.from_line(line)

            if entry.name in names:
                entry = entry._replace(password_encrypted='*')
                new_lines.append(entry.to_line())
            else:
                new_lines.append(line)

        shadow.set_lines(new_lines)

    if shadow.changed:
        return Changed(msg='Unlocked users {}'.format(names))

    return Unchanged(msg='Users {} already unlocked'.format(names))
Beispiel #7
0
def set_unlocked_no_password(names):
    # FIXME: decide API guidelines, add typechecking once Python3 is available
    # example: passing a string to names will work, but result in non-sensical
    # results.
    with fs.edit('/etc/shadow', create=False) as shadow:
        new_lines = []

        for line in shadow.lines():
            entry = ShadowEntry.from_line(line)

            if entry.name in names:
                entry = entry._replace(password_encrypted='*')
                new_lines.append(entry.to_line())
            else:
                new_lines.append(line)

        shadow.set_lines(new_lines)

    if shadow.changed:
        return Changed(msg='Unlocked users {}'.format(names))

    return Unchanged(msg='Users {} already unlocked'.format(names))
Beispiel #8
0
def enable_module(module_name, load=True, modules_file='/etc/modules'):
    mods = info['linux.modules']

    c = False

    # load module if not loaded
    if load and module_name not in mods:
        proc.run(['modprobe', module_name])
        c = True

    # ensure module is found in modules_files
    with fs.edit(modules_file) as mf:
        mf.insert_line(module_name)

    c |= mf.changed

    if c:
        return Changed(msg='Kernel module {}, enabled in {}'.format(
            module_name, modules_file))

    return Unchanged(msg='Kernel module {} already enabled in {}'.format(
        module_name, modules_file))
Beispiel #9
0
def set_hostname(hostname, domain=None, config_only=False):
    prev_hostname = info_hostname()

    changed = False
    changed |= fs.upload_string('{}\n'.format(hostname),
                                '/etc/hostname').changed

    if not config_only and prev_hostname != hostname:
        proc.run(['hostname', hostname])
        changed = True

    # update /etc/hosts
    # this will also set the domain name
    # see http://jblevins.org/log/hostname
    #
    # we adopt the following convention:

    host_line = '127.0.1.1\t' + hostname
    if domain:
        host_line = '127.0.1.1\t{}.{}\t{}'.format(hostname, domain, hostname)

    with fs.edit('/etc/hosts') as hosts:
        if host_line not in hosts.lines():
            hosts.comment_out(r'^127.0.1.1')

            # comment out old lines
            lines = [host_line] + hosts.lines()
            hosts.set_lines(lines)

    changed |= hosts.changed

    if changed:
        info_hostname.invalidate_cache()
        info_fqdn.invalidate_cache()
        return Changed(msg='Hostname changed from {} to {}'.format(
            prev_hostname, hostname))

    return Unchanged(msg='Hostname already set to {}'.format(hostname))
Beispiel #10
0
def set_hostname(hostname, domain=None, config_only=False):
    prev_hostname = info_hostname()

    changed = False
    changed |= fs.upload_string('{}\n'.format(hostname),
                                '/etc/hostname').changed

    if not config_only and prev_hostname != hostname:
        proc.run(['hostname', hostname])
        changed = True

    # update /etc/hosts
    # this will also set the domain name
    # see http://jblevins.org/log/hostname
    #
    # we adopt the following convention:

    host_line = '127.0.1.1\t' + hostname
    if domain:
        host_line = '127.0.1.1\t{}.{}\t{}'.format(hostname, domain, hostname)

    with fs.edit('/etc/hosts') as hosts:
        if host_line not in hosts.lines():
            hosts.comment_out(r'^127.0.1.1')

            # comment out old lines
            lines = [host_line] + hosts.lines()
            hosts.set_lines(lines)

    changed |= hosts.changed

    if changed:
        info_hostname.invalidate_cache()
        info_fqdn.invalidate_cache()
        return Changed(msg='Hostname changed from {} to {}'.format(
            prev_hostname, hostname))

    return Unchanged(msg='Hostname already set to {}'.format(hostname))