diff options
author | Jan Synacek <jsynacek@redhat.com> | 2014-02-20 14:47:14 +0100 |
---|---|---|
committer | Jan Synacek <jsynacek@redhat.com> | 2014-02-20 14:47:14 +0100 |
commit | 56ee83625009261963a20f1c793d25ed1c50c111 (patch) | |
tree | f8ef95786fdcc8eca1cc686b6c565e4565ffe176 /commands/storage/lmi | |
parent | ac4fcb7869b927fe633e4d040d94eff9790128b7 (diff) | |
download | openlmi-scripts-56ee83625009261963a20f1c793d25ed1c50c111.tar.gz openlmi-scripts-56ee83625009261963a20f1c793d25ed1c50c111.tar.xz openlmi-scripts-56ee83625009261963a20f1c793d25ed1c50c111.zip |
add thin provisioning scripts
Diffstat (limited to 'commands/storage/lmi')
-rw-r--r-- | commands/storage/lmi/scripts/storage/cmd/thinlv.py | 134 | ||||
-rw-r--r-- | commands/storage/lmi/scripts/storage/cmd/thinpool.py | 136 | ||||
-rw-r--r-- | commands/storage/lmi/scripts/storage/lvm.py | 61 | ||||
-rw-r--r-- | commands/storage/lmi/scripts/storage/show.py | 43 | ||||
-rw-r--r-- | commands/storage/lmi/scripts/storage/storage_cmd.py | 10 |
5 files changed, 384 insertions, 0 deletions
diff --git a/commands/storage/lmi/scripts/storage/cmd/thinlv.py b/commands/storage/lmi/scripts/storage/cmd/thinlv.py new file mode 100644 index 0000000..0fcb293 --- /dev/null +++ b/commands/storage/lmi/scripts/storage/cmd/thinlv.py @@ -0,0 +1,134 @@ +# coding=utf-8 +# Storage Management Providers +# +# Copyright (C) 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 Synacek <jsynacek@redhat.com> +# +""" +Thin Logical Volume management. + +Usage: + %(cmd)s list [ <tp> ...] + %(cmd)s create <tp> <name> <size> + %(cmd)s delete <tlv> ... + %(cmd)s show [ <tlv> ...] + +Commands: + list List available thin logical volumes on given thin pools. + If no thin pools are provided, all thin logical volumes are + listed. + + create Create a thin logical volume on given thin pool. + + delete Delete given thin logical volume. + + show Show detailed information about given Thin Logical Volumes. If no + Thin Logical Volumes are provided, all of them are displayed. + +Options: + tp Name of the thin pool, with or without `/dev/` prefix. + + size Size of the new logical volume, by default in bytes. + 'T', 'G', 'M' or 'K' suffix can be used to specify other + units (TiB, GiB, MiB and KiB) - '1K' specifies 1 KiB + (= 1024 bytes). + The suffix is case insensitive, i.e. 1g = 1G = 1073741824 + bytes. +""" + +from lmi.shell.LMIUtil import lmi_isinstance +from lmi.scripts.common import command +from lmi.scripts.common.formatter import command as fcmd +from lmi.scripts.storage import show, lvm +from lmi.scripts.storage.common import size2str, str2device, str2size, str2vg + +class ThinLVList(command.LmiLister): + COLUMNS = ("Name", "Thin Pool", "Size") + ARG_ARRAY_SUFFIX = 's' + + def execute(self, ns, tps=None): + """ + Implementation of 'thinlv list' command. + """ + for tlv in lvm.get_tlvs(ns, tps): + size = size2str(tlv.NumberOfBlocks * tlv.BlockSize, + self.app.config.human_friendly) + tp = lvm.get_lv_vg(ns, tlv) + yield (tlv.ElementName, tp.ElementName, size) + + +class ThinLVCreate(command.LmiCheckResult): + EXPECT = None + + def execute(self, ns, tp, name, size): + """ + Implementation of 'thinlv create' command. + """ + tp = str2vg(ns, tp[0]) + lvm.create_tlv(ns, tp, name, str2size(size)) + +class ThinLVDelete(command.LmiCheckResult): + EXPECT = None + ARG_ARRAY_SUFFIX = 's' + + def execute(self, ns, tlvs): + """ + Implementation of 'thinlv delete' command. + """ + for tlv in tlvs: + lvm.delete_lv(ns, tlv) + + +class ThinLVShow(command.LmiLister): + COLUMNS = ('Name', 'Value') + ARG_ARRAY_SUFFIX = 's' + + def execute(self, ns, tlvs=None): + """ + Implementation of 'thinlv show' command. + """ + if not tlvs: + tlvs = lvm.get_tlvs(ns) + + for tlv in tlvs: + tlv = str2device(ns, tlv) + cmd = fcmd.NewTableCommand(title=tlv.DeviceID) + yield cmd + for line in show.tlv_show(ns, tlv, self.app.config.human_friendly): + yield line + +class ThinLV(command.LmiCommandMultiplexer): + OWN_USAGE = __doc__ + COMMANDS = { + 'list' : ThinLVList, + 'create' : ThinLVCreate, + 'delete' : ThinLVDelete, + 'show' : ThinLVShow, + } + diff --git a/commands/storage/lmi/scripts/storage/cmd/thinpool.py b/commands/storage/lmi/scripts/storage/cmd/thinpool.py new file mode 100644 index 0000000..460e2bc --- /dev/null +++ b/commands/storage/lmi/scripts/storage/cmd/thinpool.py @@ -0,0 +1,136 @@ +# Storage Management Providers +# +# Copyright (C) 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 Synacek <jsynacek@redhat.com> +# +""" +Thin Pool management. + +Usage: + %(cmd)s list + %(cmd)s create <name> <vg> <size> + %(cmd)s delete <tp> ... + %(cmd)s show [ <tp> ...] + +Commands: + list List all thin pools on the system. + + create Create Thin Pool with given name and size from a Volume Group. + + delete Delete given Thin Pools. + + show Show detailed information about given Thin Pools. If no + Thin Pools are provided, all of them are displayed. + +Options: + vg Name of the volume group, with or without `/dev/` prefix. + + tp Name of the thin pool, with or without `/dev/` prefix. + + size Requested extent size of the new volume group, by default in + bytes. 'T', 'G', 'M' or 'K' suffix can be used to specify + other units (TiB, GiB, MiB and KiB) - '1K' specifies 1 KiB + (=1024 bytes). + The suffix is case insensitive, i.e. 1g = 1G = 1073741824 bytes. +""" + +from lmi.shell.LMIUtil import lmi_isinstance +from lmi.scripts.common import command +from lmi.scripts.common.formatter import command as fcmd +from lmi.scripts.storage import show, lvm +from lmi.scripts.storage.common import size2str, str2size, str2vg + +class ThinPoolList(command.LmiLister): + COLUMNS = ('ElementName', "ExtentSize", "Total space", "Free space") + + def execute(self, ns): + """ + Implementation of 'thinpool list' command. + """ + for vg in lvm.get_tps(ns): + extent_size = size2str(vg.ExtentSize, + self.app.config.human_friendly) + total_space = size2str(vg.TotalManagedSpace, + self.app.config.human_friendly) + remaining_space = size2str(vg.RemainingManagedSpace, + self.app.config.human_friendly) + yield (vg.ElementName, + extent_size, + total_space, + remaining_space) + + +class ThinPoolCreate(command.LmiCheckResult): + EXPECT = None + + def execute(self, ns, name, vg, size): + """ + Implementation of 'thinpool create' command. + """ + lvm.create_tp(ns, name, vg, str2size(size)) + +class ThinPoolDelete(command.LmiCheckResult): + EXPECT = None + ARG_ARRAY_SUFFIX = 's' + + def execute(self, ns, tps): + """ + Implementation of 'thinpool delete' command. + """ + for tp in tps: + lvm.delete_vg(ns, tp) + + +class ThinPoolShow(command.LmiLister): + COLUMNS = ('Name', 'Value') + ARG_ARRAY_SUFFIX = 's' + + def execute(self, ns, tps=None): + """ + Implementation of 'thinpool show' command. + """ + if not tps: + tps = lvm.get_tps(ns) + for tp in tps: + tp = str2vg(ns, tp) + cmd = fcmd.NewTableCommand(title=tp.InstanceID) + yield cmd + for line in show.tp_show(ns, tp, self.app.config.human_friendly): + yield line + +class ThinPool(command.LmiCommandMultiplexer): + OWN_USAGE = __doc__ + COMMANDS = { + 'list' : ThinPoolList, + 'create' : ThinPoolCreate, + 'delete' : ThinPoolDelete, + 'show' : ThinPoolShow, + } + + diff --git a/commands/storage/lmi/scripts/storage/lvm.py b/commands/storage/lmi/scripts/storage/lvm.py index 339c0e3..6c0a464 100644 --- a/commands/storage/lmi/scripts/storage/lvm.py +++ b/commands/storage/lmi/scripts/storage/lvm.py @@ -62,6 +62,17 @@ def get_lvs(ns, vgs=None): if 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 + def create_lv(ns, vg, name, size): """ Create new Logical Volume on given Volume Group. @@ -88,6 +99,16 @@ def create_lv(ns, vg, name, size): % (values.value_name(ret),)) return outparams['TheElement'] +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)) + return outparams['TheElement'] def delete_lv(ns, lv): """ @@ -172,6 +193,16 @@ def create_vg(ns, devices, name, extent_size=None): return outparams['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)) + return outparams['Pool'] def delete_vg(ns, vg): """ @@ -221,3 +252,33 @@ def get_vg_pvs(ns, vg): """ vg = common.str2vg(ns, vg) return vg.associators(AssocClass="LMI_VGAssociatedComponentExtent") + +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 + """ + vg = common.str2vg(ns, vg) + return vg.associators(AssocClass="LMI_VGAllocatedFromStoragePool") + +def get_tps(ns): + """ + Retrieve list of all thin pools on the system. + + :rtype: list of LMIInstance/LMI_VGStoragePool + """ + LOG().debug("get_vgs: Loading list of all thin pools.") + for vg in ns.LMI_VGStoragePool.instances(): + if vg.SpaceLimitDetermination: + yield vg + +def get_tp_vgs(ns, tp): + """ + Return Volume Groups of given Thin Pool. + + Alias for get_vg_tps. + """ + return get_vg_tps(ns, tp) diff --git a/commands/storage/lmi/scripts/storage/show.py b/commands/storage/lmi/scripts/storage/show.py index 7c35591..133b80a 100644 --- a/commands/storage/lmi/scripts/storage/show.py +++ b/commands/storage/lmi/scripts/storage/show.py @@ -176,6 +176,30 @@ def vg_show(ns, vg, human_friendly): lvnames = [lv.Name for lv in lvs] yield("Logical Volumes", " ".join(lvnames)) + tps = lvm.get_vg_tps(ns, vg) + tpnames = [tp.Name for tp in tps] + yield("Thin Pools", " ".join(tpnames)) + +def tp_show(ns, tp, human_friendly): + yield("Type", "Thin Pool") + tp = common.str2vg(ns, tp) + yield("InstanceID", tp.InstanceID) + yield("ElementName", tp.ElementName) + yield("Extent Size", common.size2str(tp.ExtentSize, human_friendly)) + yield("Total Size", common.size2str(tp.TotalManagedSpace, human_friendly)) + yield("Total Extents", tp.TotalExtents) + yield("Free Space", common.size2str(tp.RemainingManagedSpace, + human_friendly)) + yield("Free Extents", tp.RemainingExtents) + + vgs = lvm.get_tp_vgs(ns, tp) + vgnames = [vg.Name for vg in vgs] + yield("Volume Group", " ".join(vgnames)) + + lvs = lvm.get_vg_lvs(ns, tp) + lvnames = [lv.Name for lv in lvs] + yield("Logical Volumes", " ".join(lvnames)) + def lv_show(ns, lv, human_friendly): """ Print extended information about the Logical Volume. @@ -197,6 +221,25 @@ def lv_show(ns, lv, human_friendly): for line in device_show_data(ns, lv, human_friendly): yield line +def tlv_show(ns, tlv, human_friendly): + """ + Print extended information about the Thin Logical Volume. + + :type tlv: LMIInstance/LMI_LVStorageExtent or string + :param tlv: Thin Logical Volume to show. + """ + tlv = common.str2device(ns, tlv) + yield("Type", "Thin Logical Volume") + for line in device_show_device(ns, tlv, human_friendly): + yield line + + tp = lvm.get_lv_vg(ns, tlv) + yield("Thin Pool", tp.ElementName) + + vgs = lvm.get_tp_vgs(ns, tp) + vgnames = [vg.Name for vg in vgs] + yield("Volume Group", " ".join(vgnames)) + def device_show_device(ns, device, human_friendly): """ Print basic information about storage device, common to all device types. diff --git a/commands/storage/lmi/scripts/storage/storage_cmd.py b/commands/storage/lmi/scripts/storage/storage_cmd.py index a0f7373..f8945cf 100644 --- a/commands/storage/lmi/scripts/storage/storage_cmd.py +++ b/commands/storage/lmi/scripts/storage/storage_cmd.py @@ -43,6 +43,8 @@ Usage: %(cmd)s partition-table <cmd> [<args> ...] %(cmd)s raid <cmd> [<args> ...] %(cmd)s vg <cmd> [<args> ...] + %(cmd)s thinpool <cmd> [<args> ...] + %(cmd)s thinlv <cmd> [<args> ...] %(cmd)s depends [ --deep ] [ <device> ...] %(cmd)s list [ <device> ...] %(cmd)s provides [ --deep ] [ <device> ...] @@ -66,6 +68,10 @@ Commands: vg Volume Group management. + thinpool Thin Pool management. + + thinlv Thin Logical Volume management. + list List short information about given device. If no devices are given, all devices are listed. @@ -133,6 +139,8 @@ import lmi.scripts.storage.cmd.partition import lmi.scripts.storage.cmd.partition_table import lmi.scripts.storage.cmd.raid import lmi.scripts.storage.cmd.vg +import lmi.scripts.storage.cmd.thinpool +import lmi.scripts.storage.cmd.thinlv LOG = get_logger(__name__) @@ -403,6 +411,8 @@ Storage = command.register_subcommands( 'partition-table': lmi.scripts.storage.cmd.partition_table.PartitionTable, 'raid' : lmi.scripts.storage.cmd.raid.Raid, 'vg' : lmi.scripts.storage.cmd.vg.VG, + 'thinpool': lmi.scripts.storage.cmd.thinpool.ThinPool, + 'thinlv' : lmi.scripts.storage.cmd.thinlv.ThinLV, }, ) |