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")
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()
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/'])
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()
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()