summaryrefslogtreecommitdiffstats
path: root/commands/storage/lmi
diff options
context:
space:
mode:
authorJan Synacek <jsynacek@redhat.com>2014-02-20 14:47:14 +0100
committerJan Synacek <jsynacek@redhat.com>2014-02-20 14:47:14 +0100
commit56ee83625009261963a20f1c793d25ed1c50c111 (patch)
treef8ef95786fdcc8eca1cc686b6c565e4565ffe176 /commands/storage/lmi
parentac4fcb7869b927fe633e4d040d94eff9790128b7 (diff)
downloadopenlmi-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.py134
-rw-r--r--commands/storage/lmi/scripts/storage/cmd/thinpool.py136
-rw-r--r--commands/storage/lmi/scripts/storage/lvm.py61
-rw-r--r--commands/storage/lmi/scripts/storage/show.py43
-rw-r--r--commands/storage/lmi/scripts/storage/storage_cmd.py10
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,
},
)