137 lines
5.7 KiB
Python
137 lines
5.7 KiB
Python
# Copyright 2016 Canonical Ltd
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
import os
|
|
|
|
from oslo_config import cfg
|
|
from oslo_utils import fileutils
|
|
from nova import exception
|
|
from nova import utils
|
|
from nova.virt import driver
|
|
|
|
from nova.virt.lxd import common
|
|
|
|
CONF = cfg.CONF
|
|
|
|
|
|
def attach_ephemeral(client, block_device_info, lxd_config, instance):
|
|
"""Attach ephemeral storage to an instance."""
|
|
ephemeral_storage = driver.block_device_info_get_ephemerals(
|
|
block_device_info)
|
|
if ephemeral_storage:
|
|
storage_driver = lxd_config['environment']['storage']
|
|
|
|
container = client.containers.get(instance.name)
|
|
container_id_map = container.config[
|
|
'volatile.last_state.idmap'].split(',')
|
|
storage_id = container_id_map[2].split(':')[1]
|
|
|
|
instance_attrs = common.InstanceAttributes(instance)
|
|
for ephemeral in ephemeral_storage:
|
|
storage_dir = os.path.join(
|
|
instance_attrs.storage_path, ephemeral['virtual_name'])
|
|
if storage_driver == 'zfs':
|
|
# NOTE(ajkavanagh) - BUG/1782329 - this is temporary until
|
|
# storage pools is implemented. LXD 3 removed the
|
|
# storage.zfs_pool_name key from the config. So, if it fails,
|
|
# we need to grab the configured storage pool and use that as
|
|
# the name instead.
|
|
try:
|
|
zfs_pool = lxd_config['config']['storage.zfs_pool_name']
|
|
except KeyError:
|
|
zfs_pool = CONF.lxd.pool
|
|
|
|
utils.execute(
|
|
'zfs', 'create',
|
|
'-o', 'mountpoint=%s' % storage_dir,
|
|
'-o', 'quota=%sG' % instance.ephemeral_gb,
|
|
'%s/%s-ephemeral' % (zfs_pool, instance.name),
|
|
run_as_root=True)
|
|
elif storage_driver == 'btrfs':
|
|
# We re-use the same btrfs subvolumes that LXD uses,
|
|
# so the ephemeral storage path is updated in the profile
|
|
# before the container starts.
|
|
storage_dir = os.path.join(
|
|
instance_attrs.container_path, ephemeral['virtual_name'])
|
|
profile = client.profiles.get(instance.name)
|
|
storage_name = ephemeral['virtual_name']
|
|
profile.devices[storage_name]['source'] = storage_dir
|
|
profile.save()
|
|
|
|
utils.execute(
|
|
'btrfs', 'subvolume', 'create', storage_dir,
|
|
run_as_root=True)
|
|
utils.execute(
|
|
'btrfs', 'qgroup', 'limit',
|
|
'%sg' % instance.ephemeral_gb, storage_dir,
|
|
run_as_root=True)
|
|
elif storage_driver == 'lvm':
|
|
fileutils.ensure_tree(storage_dir)
|
|
|
|
lvm_pool = lxd_config['config']['storage.lvm_vg_name']
|
|
lvm_volume = '%s-%s' % (instance.name,
|
|
ephemeral['virtual_name'])
|
|
lvm_path = '/dev/%s/%s' % (lvm_pool, lvm_volume)
|
|
|
|
cmd = (
|
|
'lvcreate', '-L', '%sG' % instance.ephemeral_gb,
|
|
'-n', lvm_volume, lvm_pool)
|
|
utils.execute(*cmd, run_as_root=True, attempts=3)
|
|
|
|
utils.execute('mkfs', '-t', 'ext4',
|
|
lvm_path, run_as_root=True)
|
|
cmd = ('mount', '-t', 'ext4', lvm_path, storage_dir)
|
|
utils.execute(*cmd, run_as_root=True)
|
|
else:
|
|
reason = _("Unsupport LXD storage detected. Supported"
|
|
" storage drivers are zfs and btrfs.")
|
|
raise exception.NovaException(reason)
|
|
|
|
utils.execute(
|
|
'chown', storage_id,
|
|
storage_dir, run_as_root=True)
|
|
|
|
|
|
def detach_ephemeral(client, block_device_info, lxd_config, instance):
|
|
"""Detach ephemeral device from the instance."""
|
|
ephemeral_storage = driver.block_device_info_get_ephemerals(
|
|
block_device_info)
|
|
if ephemeral_storage:
|
|
storage_driver = lxd_config['environment']['storage']
|
|
|
|
for ephemeral in ephemeral_storage:
|
|
if storage_driver == 'zfs':
|
|
# NOTE(ajkavanagh) - BUG/1782329 - this is temporary until
|
|
# storage pools is implemented. LXD 3 removed the
|
|
# storage.zfs_pool_name key from the config. So, if it fails,
|
|
# we need to grab the configured storage pool and use that as
|
|
# the name instead.
|
|
try:
|
|
zfs_pool = lxd_config['config']['storage.zfs_pool_name']
|
|
except KeyError:
|
|
zfs_pool = CONF.lxd.pool
|
|
|
|
utils.execute(
|
|
'zfs', 'destroy',
|
|
'%s/%s-ephemeral' % (zfs_pool, instance.name),
|
|
run_as_root=True)
|
|
if storage_driver == 'lvm':
|
|
lvm_pool = lxd_config['config']['storage.lvm_vg_name']
|
|
|
|
lvm_path = '/dev/%s/%s-%s' % (
|
|
lvm_pool, instance.name, ephemeral['virtual_name'])
|
|
|
|
utils.execute('umount', lvm_path, run_as_root=True)
|
|
utils.execute('lvremove', '-f', lvm_path, run_as_root=True)
|