Source code for lmi.scripts.storage.lvm

# Storage Management Providers
#
# Copyright (C) 2013-2014 Red Hat, Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and documentation are
# those of the authors and should not be interpreted as representing official
# policies, either expressed or implied, of the FreeBSD Project.
#
# Authors: Jan Safranek <jsafrane@redhat.com>
#

"""
LVM management functions.
"""

from lmi.scripts.common.errors import LmiFailed
from lmi.scripts.common import get_logger
LOG = get_logger(__name__)
from lmi.scripts.storage import common

[docs]def get_lvs(ns, vgs=None): """ Retrieve list of all logical volumes allocated from given volume groups. If no volume groups are provided, all logical volumes on the system are returned. :type vgs: list of LMIInstance/LMI_VGStoragePool or list of strings :param vgs: Volume Groups to examine. :rtype: list of LMIInstance/LMI_LVStorageExtent. """ if vgs: for vg in vgs: vg = common.str2vg(ns, vg) LOG().debug("Getting LVs on %s", vg.ElementName) for lv in get_vg_lvs(ns, vg): yield lv else: # No vgs supplied, list all LVs for lv in ns.LMI_LVStorageExtent.instances(): # XXX workaround for https://fedorahosted.org/openlmi/ticket/277 supports_thin = 'ThinlyProvisioned' in lv.properties() if not supports_thin: yield lv elif supports_thin and not lv.ThinlyProvisioned: yield lv
def get_tlvs(ns, tps=None): if tps: for tp in tps: tp = common.str2vg(ns, tp) for tlv in get_vg_lvs(ns, tp): yield tlv else: for tlv in ns.LMI_LVStorageExtent.instances(): if tlv.ThinlyProvisioned: yield tlv
[docs]def create_lv(ns, vg, name, size): """ Create new Logical Volume on given Volume Group. :type vg: LMIInstance/LMI_VGStoragePool or string :param vg: Volume Group to allocate the volume from. :type name: string :param name: Name of the logical volume. :type size: int :param size: Size of the logical volume in bytes. :rtype: LMIInstance/LMI_LVStorageExtent """ vg = common.str2vg(ns, vg) service = ns.LMI_StorageConfigurationService.first_instance() (ret, outparams, err) = service.SyncCreateOrModifyLV( ElementName=name, Size=size, InPool=vg) if ret != 0: if err: raise LmiFailed("Cannot create the logical volume: %s." % err) values = service.CreateOrModifyLV.CreateOrModifyLVValues raise LmiFailed("Cannot create the logical volume: %s." % (values.value_name(ret),)) lv = outparams['TheElement'].to_instance() LOG().info("Created logical volume %s", lv.Name) return lv
def create_tlv(ns, tp, name, size): tp = common.str2vg(ns, tp) args = {'ElementName':name, 'ThinPool':tp, 'Size':size} service = ns.LMI_StorageConfigurationService.first_instance() (ret, outparams, err) = service.SyncCreateOrModifyThinLV(**args) if ret != 0: raise LmiFailed("Cannot create thin LV: %s." % (err if err else ret)) tlv = outparams['TheElement'].to_instance() LOG().info("Created thin logical volume %s", tlv.Name) return tlv
[docs]def delete_lv(ns, lv): """ Destroy given Logical Volume. :type lv: LMIInstance/LMI_LVStorageExtent or string :param lv: Logical Volume to destroy. """ lv = common.str2device(ns, lv) service = ns.LMI_StorageConfigurationService.first_instance() (ret, _outparams, err) = service.SyncDeleteLV(TheElement=lv) if ret != 0: if err: raise LmiFailed("Cannot delete the LV: %s." % err) raise LmiFailed("Cannot delete the LV: %s." % (service.DeleteLV.DeleteLVValues.value_name(ret),)) LOG().info("Deleted logical volume %s", lv.Name)
[docs]def get_vgs(ns): """ Retrieve list of all volume groups on the system. :rtype: list of LMIInstance/LMI_VGStoragePool """ LOG().debug("get_vgs: Loading list of all volume groups.") for vg in ns.LMI_VGStoragePool.instances(): if vg.SpaceLimitDetermination: # skip thin pools continue yield vg
[docs]def create_vg(ns, devices, name, extent_size=None): """ Create new Volume Group from given devices. :type devices: list of LMIInstance/CIM_StorageExtent or list of strings :param device: Devices to add to the Volume Group. :type name: string :param name: Name of the Volume gGoup. :type extent_size: int :param extent_size: Extent size in bytes. :rtype: LMIInstance/LMI_VGStoragePool """ devs = [common.str2device(ns, device) for device in devices] args = { 'InExtents': devs, 'ElementName': name} goal = None try: if extent_size: # create (and use) VGStorageSetting caps = ns.LMI_VGStorageCapabilities.first_instance() (ret, outparams, err) = caps.CreateVGStorageSetting( InExtents=devs) if ret != 0: if err: raise LmiFailed("Cannot create setting for the volume " \ "group: %s." % err) vals = caps.CreateVGStorageSetting.CreateVGStorageSettingValues raise LmiFailed("Cannot create setting for the volume group:" \ " %s." % (vals.value_name(ret),)) goal = outparams['Setting'] goal = goal.to_instance() goal.ExtentSize = extent_size (ret, outparams, err) = goal.push() if ret != 0: if err: raise LmiFailed("Cannot modify setting for the volume " \ "group: %s." % err) raise LmiFailed("Cannot modify setting for the volume group:" \ " %d." % ret) args['Goal'] = goal service = ns.LMI_StorageConfigurationService.first_instance() (ret, outparams, err) = service.SyncCreateOrModifyVG(**args) if ret != 0: if err: raise LmiFailed("Cannot create the volume group: %s." % err) values = service.CreateOrModifyVG.CreateOrModifyVGValues raise LmiFailed("Cannot create the volume group: %s." % (values.value_name(ret),)) finally: if goal: goal.delete() pool = outparams['Pool'].to_instance() LOG().info("Created volume group %s", pool.Name) return pool
def create_tp(ns, name, vg, size): vg = common.str2vg(ns, vg) args = {'InPool':vg, 'ElementName':name, 'Size':size} service = ns.LMI_StorageConfigurationService.first_instance() (ret, outparams, err) = service.SyncCreateOrModifyThinPool(**args) if ret != 0: raise LmiFailed("Cannot create thin pool: %s." % (err if err else ret)) pool = outparams['Pool'].to_instance() LOG().info("Created thin volume group %s", pool.Name) return pool
[docs]def modify_vg(ns, vg, add_pvs=None, remove_pvs=None): """ Modify given Volume Group. Add 'add_pvs' devices as Physical Volumes of the group. Remove 'remove_pvs' devices from the Volume Group. :type vg: LMIInstance/LMI_VGStoragePool or string :param vg: Volume Group to delete. :type add_pvs: List of LMIInstances/LMI_VGStoragePools or strings :param add_pvs: List of new devices to be added as Physical Volumes of the VG. :type remove_pvs: List of LMIInstances/LMI_VGStoragePools or strings :param remove_pvs: List of Physical Volume to be removed from the VG. """ vg = common.str2vg(ns, vg) service = ns.LMI_StorageConfigurationService.first_instance() # get list of current PVs pvs = get_vg_pvs(ns, vg) for device in add_pvs: device = common.str2device(ns, device) if device not in pvs: pvs.append(device) for device in remove_pvs: device = common.str2device(ns, device) # don't report error when removing device that is not a PV if device in pvs: pvs.remove(device) (ret, _outparams, err) = service.SyncCreateOrModifyVG(Pool=vg, InExtents = list(pvs)) if ret != 0: if err: raise LmiFailed("Cannot modify the VG: %s." % err) raise LmiFailed("Cannot modify the VG: %s." % (service.CreateOrModifyVG.CreateOrModifyVG.value_name(ret),)) LOG().info("Modified volume group %s", vg.Name)
[docs]def delete_vg(ns, vg): """ Destroy given Volume Group. :type vg: LMIInstance/LMI_VGStoragePool or string :param vg: Volume Group to delete. """ vg = common.str2vg(ns, vg) service = ns.LMI_StorageConfigurationService.first_instance() (ret, _outparams, err) = service.SyncDeleteVG(Pool=vg) if ret != 0: if err: raise LmiFailed("Cannot delete the VG: %s." % err) raise LmiFailed("Cannot delete the VG: %s." % (service.DeleteVG.DeleteVGValues.value_name(ret),)) LOG().info("Deleted volume group %s", vg.Name)
[docs]def get_vg_lvs(ns, vg): """ Return list of Logical Volumes on given Volume Group. :type vg: LMIInstance/LMI_VGStoragePool or string :param vg: Volume Group to examine. :rtype: list of LMIInstance/LMI_LVStorageExtent """ vg = common.str2vg(ns, vg) return vg.associators(AssocClass="LMI_LVAllocatedFromStoragePool")
[docs]def get_lv_vg(ns, lv): """ Return Volume Group of given Logical Volume. :type lv: LMIInstance/LMI_LVStorageExtent or string :param lv: Logical Volume to examine. :rtype: LMIInstance/LMI_VGStoragePool """ lv = common.str2device(ns, lv) return lv.first_associator(AssocClass="LMI_LVAllocatedFromStoragePool")
[docs]def get_vg_pvs(ns, vg): """ Return Physical Volumes of given Volume Group. :type vg: LMIInstance/LMI_VGStoragePool or string :param vg: Volume Group to examine. :rtype: list of LMIInstance/CIM_StorageExtent """ vg = common.str2vg(ns, vg) return vg.associators(AssocClass="LMI_VGAssociatedComponentExtent")
[docs]def get_vg_tps(ns, vg): """ Return Thin Pools of given Volume Group. :type vg: LMIInstance/LMI_VGStoragePool or string :param vg: Volume Group to examine. :rtype: list of LMIInstance/CIM_StoragePool """ # XXX workaround for https://fedorahosted.org/openlmi/ticket/276 assoc_class = "LMI_VGAllocatedFromStoragePool" if not assoc_class in ns.classes(): return [] vg = common.str2vg(ns, vg) return vg.associators(AssocClass=assoc_class)
[docs]def get_tps(ns): """ Retrieve list of all thin pools on the system. :rtype: list of LMIInstance/LMI_VGStoragePool """ if "LMI_VGAllocatedFromStoragePool" in ns.classes(): LOG().debug("get_tps: Loading list of all thin pools.") for vg in ns.LMI_VGStoragePool.instances(): if vg.SpaceLimitDetermination: yield vg
[docs]def get_tp_vgs(ns, tp): """ Return Volume Groups of given Thin Pool. Alias for get_vg_tps. """ return get_vg_tps(ns, tp)