Esempio n. 1
0
def workaround_lxd_kernel_params():
    """
    Workaround for kubelet not starting in LXD when kernel params are not set
    to the desired values.
    """
    if host.is_container():
        hookenv.log("LXD detected, faking kernel params via bind mounts")
        root_dir = "/root/cdk/lxd-kernel-params"
        os.makedirs(root_dir, exist_ok=True)
        # Kernel params taken from:
        # https://github.com/kubernetes/kubernetes/blob/v1.22.0/pkg/kubelet/cm/container_manager_linux.go#L421-L426
        # https://github.com/kubernetes/kubernetes/blob/v1.22.0/pkg/util/sysctl/sysctl.go#L30-L64
        params = {
            "vm.overcommit_memory": 1,
            "vm.panic_on_oom": 0,
            "kernel.panic": 10,
            "kernel.panic_on_oops": 1,
            "kernel.keys.root_maxkeys": 1000000,
            "kernel.keys.root_maxbytes": 1000000 * 25,
        }
        for param, param_value in params.items():
            fake_param_path = root_dir + "/" + param
            with open(fake_param_path, "w") as f:
                f.write(str(param_value))
            real_param_path = "/proc/sys/" + param.replace(".", "/")
            host.fstab_add(fake_param_path, real_param_path, "none", "bind")
        subprocess.check_call(["mount", "-a"])
    else:
        hookenv.log("LXD not detected, not faking kernel params")
Esempio n. 2
0
def update_nfs():
    rhost = relation_get('private-address')
    mpath = relation_get('mountpath')
    if len(mpath):
        umount('/mnt/plex/')
        fstab_remove('/mnt/plex')

        fstab_add(
            '{}:{}'.format(rhost, mpath),
            '/mnt/plex',
            'nfs rw'
        )
        mount()
Esempio n. 3
0
def setup_storage():
    # Ensure /srv/node exists just in case no disks
    # are detected and used.
    mkdir(os.path.join('/srv', 'node'),
          owner='swift',
          group='swift',
          perms=0o755)
    reformat = str(config('overwrite')).lower() == "true"
    for dev in determine_block_devices():
        if is_device_in_ring(os.path.basename(dev)):
            log("Device '%s' already in the ring - ignoring" % (dev))
            continue

        if reformat:
            clean_storage(dev)

        try:
            # If not cleaned and in use, mkfs should fail.
            mkfs_xfs(dev, force=reformat)
        except subprocess.CalledProcessError as exc:
            # This is expected is a formatted device is provided and we are
            # forcing the format.
            log("Format device '%s' failed (%s) - continuing to next device" %
                (dev, exc),
                level=WARNING)
            continue

        basename = os.path.basename(dev)
        _mp = os.path.join('/srv', 'node', basename)
        mkdir(_mp, owner='swift', group='swift')

        options = None
        loopback_device = is_mapped_loopback_device(dev)

        if loopback_device:
            dev = loopback_device
            options = "loop, defaults"

        mountpoint = '/srv/node/%s' % basename
        filesystem = "xfs"

        mount(dev, mountpoint, filesystem=filesystem)
        fstab_add(dev, mountpoint, filesystem, options=options)

        check_call(['chown', '-R', 'swift:swift', mountpoint])
        check_call(['chmod', '-R', '0755', mountpoint])
def setup_storage():
    # Ensure /srv/node exists just in case no disks
    # are detected and used.
    mkdir(os.path.join('/srv', 'node'),
          owner='swift', group='swift',
          perms=0o755)
    reformat = str(config('overwrite')).lower() == "true"
    for dev in determine_block_devices():
        if is_device_in_ring(os.path.basename(dev)):
            log("Device '%s' already in the ring - ignoring" % (dev))
            continue

        if reformat:
            clean_storage(dev)

        try:
            # If not cleaned and in use, mkfs should fail.
            mkfs_xfs(dev, force=reformat)
        except subprocess.CalledProcessError as exc:
            # This is expected is a formatted device is provided and we are
            # forcing the format.
            log("Format device '%s' failed (%s) - continuing to next device" %
                (dev, exc), level=WARNING)
            continue

        basename = os.path.basename(dev)
        _mp = os.path.join('/srv', 'node', basename)
        mkdir(_mp, owner='swift', group='swift')

        options = None
        loopback_device = is_mapped_loopback_device(dev)

        if loopback_device:
            dev = loopback_device
            options = "loop, defaults"

        mountpoint = '/srv/node/%s' % basename
        filesystem = "xfs"

        mount(dev, mountpoint, filesystem=filesystem)
        fstab_add(dev, mountpoint, filesystem, options=options)

    check_call(['chown', '-R', 'swift:swift', '/srv/node/'])
    check_call(['chmod', '-R', '0755', '/srv/node/'])
Esempio n. 5
0
def encrypt_device(device, mountpoint=None, uuid=None):
    """
    Set up encryption for the given block device, and optionally create and
    mount an XFS filesystem on the encrypted device.

    If ``mountpoint`` is not given, the device will not be formatted or
    mounted.  When interacting with or mounting the device manually, the
    name returned by :func:`decrypted_device` called on the device name
    should be used in place of the raw device name.
    """
    if not is_block_device(device):
        raise VaultLockerError('Cannot encrypt non-block device: {}', device)
    if is_device_mounted(device):
        raise VaultLockerError('Cannot encrypt mounted device: {}', device)
    hookenv.log('Encrypting device: {}'.format(device))
    if uuid is None:
        uuid = str(uuid4())
    try:
        check_call(['vaultlocker', 'encrypt', '--uuid', uuid, device])
        unitdata.kv().set('layer.vaultlocker.uuids.{}'.format(device), uuid)
        if mountpoint:
            mapped_device = decrypted_device(device)
            hookenv.log('Creating filesystem on {} ({})'.format(
                mapped_device, device))
            # If this fails, it's probalby due to the size of the loopback
            #    backing file that is defined by the `dd`.
            mkfs_xfs(mapped_device)
            Path(mountpoint).mkdir(mode=0o755, parents=True, exist_ok=True)
            hookenv.log('Mounting filesystem for {} ({}) at {}'
                        ''.format(mapped_device, device, mountpoint))
            host.mount(mapped_device, mountpoint, filesystem='xfs')
            host.fstab_add(
                mapped_device, mountpoint, 'xfs', ','.join([
                    "defaults",
                    "nofail",
                    "x-systemd.requires=vaultlocker-decrypt@{uuid}.service".
                    format(uuid=uuid, ),
                    "comment=vaultlocker",
                ]))
    except (CalledProcessError, OSError) as e:
        raise VaultLockerError('Error configuring VaultLocker') from e
def configure_local_ephemeral_storage():
    """Configure local block device for use as ephemeral instance storage"""
    # Preflight check vault relation if encryption is enabled
    vault_kv = vaultlocker.VaultKVContext(
        secret_backend=vaultlocker.VAULTLOCKER_BACKEND)
    context = vault_kv()
    encrypt = config('encrypt')
    if encrypt and not vault_kv.complete:
        log("Encryption requested but vault relation not complete",
            level=DEBUG)
        return
    elif encrypt and vault_kv.complete:
        # NOTE: only write vaultlocker configuration once relation is complete
        #       otherwise we run the chance of an empty configuration file
        #       being installed on a machine with other vaultlocker based
        #       services
        vaultlocker.write_vaultlocker_conf(context, priority=80)

    db = kv()
    storage_configured = db.get('storage-configured', False)
    if storage_configured:
        log("Ephemeral storage already configured, skipping", level=DEBUG)
        return

    dev = determine_block_device()

    if not dev:
        log('No block device configuration found, skipping', level=DEBUG)
        return

    if not is_block_device(dev):
        log("Device '{}' is not a block device, "
            "unable to configure storage".format(dev),
            level=DEBUG)
        return

    # NOTE: this deals with a dm-crypt'ed block device already in
    #       use
    if is_device_mounted(dev):
        log("Device '{}' is already mounted, "
            "unable to configure storage".format(dev),
            level=DEBUG)
        return

    options = None
    if encrypt:
        dev_uuid = str(uuid.uuid4())
        check_call(['vaultlocker', 'encrypt', '--uuid', dev_uuid, dev])
        dev = '/dev/mapper/crypt-{}'.format(dev_uuid)
        options = ','.join([
            "defaults",
            "nofail",
            ("x-systemd.requires="
             "vaultlocker-decrypt@{uuid}.service".format(uuid=dev_uuid)),
            "comment=vaultlocker",
        ])

    # If not cleaned and in use, mkfs should fail.
    mkfs_xfs(dev, force=True)

    mountpoint = '/var/lib/nova/instances'
    filesystem = "xfs"
    mount(dev, mountpoint, filesystem=filesystem)
    fstab_add(dev, mountpoint, filesystem, options=options)

    check_call(['chown', '-R', 'nova:nova', mountpoint])
    check_call(['chmod', '-R', '0755', mountpoint])

    # NOTE: record preparation of device - this ensures that ephemeral
    #       storage is never reconfigured by mistake, losing instance disks
    db.set('storage-configured', True)
    db.flush()
Esempio n. 7
0
def setup_storage(encrypt=False):
    # Preflight check vault relation if encryption is enabled
    vault_kv = vaultlocker.VaultKVContext(vaultlocker.VAULTLOCKER_BACKEND)
    context = vault_kv()
    if encrypt and not vault_kv.complete:
        log("Encryption requested but vault relation not complete",
            level=DEBUG)
        return
    elif encrypt and vault_kv.complete:
        # NOTE: only write vaultlocker configuration once relation is complete
        #       otherwise we run the chance of an empty configuration file
        #       being installed on a machine with other vaultlocker based
        #       services
        vaultlocker.write_vaultlocker_conf(context, priority=90)

    # Ensure /srv/node exists just in case no disks
    # are detected and used.
    mkdir(os.path.join('/srv', 'node'),
          owner='swift', group='swift',
          perms=0o755)
    reformat = str(config('overwrite')).lower() == "true"

    db = kv()
    prepared_devices = db.get('prepared-devices', [])

    for dev in determine_block_devices():
        if dev in prepared_devices:
            log('Device {} already processed by charm,'
                ' skipping'.format(dev))
            continue

        if is_device_in_ring(os.path.basename(dev)):
            log("Device '%s' already in the ring - ignoring" % (dev))
            # NOTE: record existing use of device dealing with
            #       upgrades from older versions of charms without
            #       this feature
            prepared_devices.append(dev)
            db.set('prepared-devices', prepared_devices)
            db.flush()
            continue

        # NOTE: this deals with a dm-crypt'ed block device already in
        #       use
        if is_device_mounted(dev):
            log("Device '{}' is already mounted, ignoring".format(dev))
            continue

        if reformat:
            clean_storage(dev)

        loopback_device = is_mapped_loopback_device(dev)
        options = None

        if encrypt and not loopback_device:
            dev_uuid = str(uuid.uuid4())
            check_call(['vaultlocker', 'encrypt',
                        '--uuid', dev_uuid,
                        dev])
            dev = '/dev/mapper/crypt-{}'.format(dev_uuid)
            options = ','.join([
                "defaults",
                "nofail",
                ("x-systemd.requires="
                 "vaultlocker-decrypt@{uuid}.service".format(uuid=dev_uuid)),
                "comment=vaultlocker",
            ])

        try:
            # If not cleaned and in use, mkfs should fail.
            mkfs_xfs(dev, force=reformat)
        except subprocess.CalledProcessError as exc:
            # This is expected is a formatted device is provided and we are
            # forcing the format.
            log("Format device '%s' failed (%s) - continuing to next device" %
                (dev, exc), level=WARNING)
            continue

        basename = os.path.basename(dev)
        _mp = os.path.join('/srv', 'node', basename)
        mkdir(_mp, owner='swift', group='swift')

        mountpoint = '/srv/node/%s' % basename
        if loopback_device:
            # If an exiting fstab entry exists using the image file as the
            # source then preserve it, otherwise use the loopback device
            # directly to avoid a secound implicit loopback device being
            # created on mount. Bug #1762390
            fstab = charmhelpers.core.fstab.Fstab()
            fstab_entry = fstab.get_entry_by_attr('mountpoint', mountpoint)
            if fstab_entry and loopback_device == fstab_entry.device:
                dev = loopback_device
            options = "loop,nofail,defaults"

        filesystem = "xfs"

        mount(dev, mountpoint, filesystem=filesystem)
        fstab_add(dev, mountpoint, filesystem, options=options)

        check_call(['chown', '-R', 'swift:swift', mountpoint])
        check_call(['chmod', '-R', '0755', mountpoint])

        # NOTE: record preparation of device - this will be used when
        #       providing block device configuration for ring builders.
        prepared_devices.append(dev)
        db.set('prepared-devices', prepared_devices)
        db.flush()