[Kimchi-devel] [PATCH] Moved disks.py file from kimchi plugin to gingerbase plugin

Suresh Babu Angadi sureshab at linux.vnet.ibm.com
Thu Nov 19 13:09:22 UTC 2015



On 11/19/2015 06:04 PM, Rodrigo Trujillo wrote:
> Why is this change necessary ??
> This is going to make Kimchi requires ginger-base when projects splits.
Going by the community decision in mail thread  Re: [Kimchi-devel] [RFC] 
The new ginger-basic plugin
point 3 states : 3) Add ginger-basic plugin as a Kimchi dependency.

As per my knowledge, gingerbase was formed since some of the host 
functionality
was part of kimchi, which should have also been in ginger.
So I suppose it is okay to move disks functionality to gingerbase since 
it is used by both kimchi and ginger.

> I think that this was not expected.
>
> Rodrigo Trujillo
>
> On 11/19/2015 08:22 AM, pkulkark at linux.vnet.ibm.com wrote:
>> From: Pooja Kulkarni <pkulkark at linux.vnet.ibm.com>
>>
>> Signed-off-by: Pooja Kulkarni <pkulkark at linux.vnet.ibm.com>
>> ---
>>   src/wok/plugins/gingerbase/disks.py  | 196 
>> +++++++++++++++++++++++++++++++++++
>>   src/wok/plugins/kimchi/model/host.py |   2 +-
>>   2 files changed, 197 insertions(+), 1 deletion(-)
>>   create mode 100644 src/wok/plugins/gingerbase/disks.py
>>
>> diff --git a/src/wok/plugins/gingerbase/disks.py 
>> b/src/wok/plugins/gingerbase/disks.py
>> new file mode 100644
>> index 0000000..eb40e3a
>> --- /dev/null
>> +++ b/src/wok/plugins/gingerbase/disks.py
>> @@ -0,0 +1,196 @@
>> +#
>> +# Project Kimchi
>> +#
>> +# Copyright IBM, Corp. 2013-2015
>> +#
>> +# This library is free software; you can redistribute it and/or
>> +# modify it under the terms of the GNU Lesser General Public
>> +# License as published by the Free Software Foundation; either
>> +# version 2.1 of the License, or (at your option) any later version.
>> +#
>> +# This library is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> +# Lesser General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU Lesser General Public
>> +# License along with this library; if not, write to the Free Software
>> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
>> 02110-1301 USA
>> +
>> +import os.path
>> +import re
>> +import subprocess
>> +from parted import Device as PDevice
>> +from parted import Disk as PDisk
>> +
>> +from wok.exception import OperationFailed
>> +from wok.utils import wok_log
>> +
>> +
>> +def _get_dev_node_path(maj_min):
>> +    """ Returns device node path given the device number 'major:min' 
>> """
>> +
>> +    dm_name = "/sys/dev/block/%s/dm/name" % maj_min
>> +    if os.path.exists(dm_name):
>> +        with open(dm_name) as dm_f:
>> +            content = dm_f.read().rstrip('\n')
>> +        return "/dev/mapper/" + content
>> +
>> +    uevent = "/sys/dev/block/%s/uevent" % maj_min
>> +    with open(uevent) as ueventf:
>> +        content = ueventf.read()
>> +
>> +    data = dict(re.findall(r'(\S+)=(".*?"|\S+)', 
>> content.replace("\n", " ")))
>> +
>> +    return "/dev/%s" % data["DEVNAME"]
>> +
>> +
>> +def _get_lsblk_devs(keys, devs=[]):
>> +    lsblk = subprocess.Popen(
>> +        ["lsblk", "-Pbo"] + [','.join(keys)] + devs,
>> +        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>> +    out, err = lsblk.communicate()
>> +    if lsblk.returncode != 0:
>> +        raise OperationFailed("KCHDISKS0001E", {'err': err})
>> +
>> +    return _parse_lsblk_output(out, keys)
>> +
>> +
>> +def _get_dev_major_min(name):
>> +    maj_min = None
>> +
>> +    keys = ["NAME", "MAJ:MIN"]
>> +    dev_list = _get_lsblk_devs(keys)
>> +
>> +    for dev in dev_list:
>> +        if dev['name'].split()[0] == name:
>> +            maj_min = dev['maj:min']
>> +            break
>> +    else:
>> +        raise OperationFailed("KCHDISKS0002E", {'device': name})
>> +
>> +    return maj_min
>> +
>> +
>> +def _is_dev_leaf(devNodePath):
>> +    try:
>> +        # By default, lsblk prints a device information followed by 
>> children
>> +        # device information
>> +        childrenCount = len(
>> +            _get_lsblk_devs(["NAME"], [devNodePath])) - 1
>> +    except OperationFailed as e:
>> +        # lsblk is known to fail on multipath devices
>> +        # Assume these devices contain children
>> +        wok_log.error(
>> +            "Error getting device info for %s: %s", devNodePath, e)
>> +        return False
>> +
>> +    return childrenCount == 0
>> +
>> +
>> +def _is_dev_extended_partition(devType, devNodePath):
>> +    if devType != 'part':
>> +        return False
>> +    diskPath = devNodePath.rstrip('0123456789')
>> +    device = PDevice(diskPath)
>> +    try:
>> +        extended_part = PDisk(device).getExtendedPartition()
>> +    except NotImplementedError as e:
>> +        wok_log.warning(
>> +            "Error getting extended partition info for dev %s type 
>> %s: %s",
>> +            devNodePath, devType, e.message)
>> +        # Treate disk with unsupported partiton table as if it does not
>> +        # contain extended partitions.
>> +        return False
>> +    if extended_part and extended_part.path == devNodePath:
>> +        return True
>> +    return False
>> +
>> +
>> +def _parse_lsblk_output(output, keys):
>> +    # output is on format key="value",
>> +    # where key can be NAME, TYPE, FSTYPE, SIZE, MOUNTPOINT, etc
>> +    lines = output.rstrip("\n").split("\n")
>> +    r = []
>> +    for line in lines:
>> +        d = {}
>> +        for key in keys:
>> +            expression = r"%s=\".*?\"" % key
>> +            match = re.search(expression, line)
>> +            field = match.group()
>> +            k, v = field.split('=', 1)
>> +            d[k.lower()] = v[1:-1]
>> +        r.append(d)
>> +    return r
>> +
>> +
>> +def _get_vgname(devNodePath):
>> +    """ Return volume group name of a physical volume. If the device 
>> node path
>> +    is not a physical volume, return empty string. """
>> +    pvs = subprocess.Popen(
>> +        ["pvs", "--unbuffered", "--nameprefixes", "--noheadings",
>> +         "-o", "vg_name", devNodePath],
>> +        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>> +    out, err = pvs.communicate()
>> +    if pvs.returncode != 0:
>> +        return ""
>> +
>> +    return re.findall(r"LVM2_VG_NAME='([^\']*)'", out)[0]
>> +
>> +
>> +def _is_available(name, devtype, fstype, mountpoint, majmin):
>> +    devNodePath = _get_dev_node_path(majmin)
>> +    # Only list unmounted and unformated and leaf and (partition or 
>> disk)
>> +    # leaf means a partition, a disk has no partition, or a disk not 
>> held
>> +    # by any multipath device. Physical volume belongs to no volume 
>> group
>> +    # is also listed. Extended partitions should not be listed.
>> +    if (devtype in ['part', 'disk', 'mpath'] and
>> +            fstype in ['', 'LVM2_member'] and
>> +            mountpoint == "" and
>> +            _get_vgname(devNodePath) == "" and
>> +            _is_dev_leaf(devNodePath) and
>> +            not _is_dev_extended_partition(devtype, devNodePath)):
>> +        return True
>> +    return False
>> +
>> +
>> +def get_partitions_names(check=False):
>> +    names = set()
>> +    keys = ["NAME", "TYPE", "FSTYPE", "MOUNTPOINT", "MAJ:MIN"]
>> +    # output is on format key="value",
>> +    # where key can be NAME, TYPE, FSTYPE, MOUNTPOINT
>> +    for dev in _get_lsblk_devs(keys):
>> +        # split()[0] to avoid the second part of the name, after the
>> +        # whiteline
>> +        name = dev['name'].split()[0]
>> +        if check and not _is_available(name, dev['type'], 
>> dev['fstype'],
>> +                                       dev['mountpoint'], 
>> dev['maj:min']):
>> +            continue
>> +        names.add(name)
>> +
>> +    return list(names)
>> +
>> +
>> +def get_partition_details(name):
>> +    majmin = _get_dev_major_min(name)
>> +    dev_path = _get_dev_node_path(majmin)
>> +
>> +    keys = ["TYPE", "FSTYPE", "SIZE", "MOUNTPOINT"]
>> +    try:
>> +        dev = _get_lsblk_devs(keys, [dev_path])[0]
>> +    except OperationFailed as e:
>> +        wok_log.error(
>> +            "Error getting partition info for %s: %s", name, e)
>> +        return {}
>> +
>> +    dev['available'] = _is_available(name, dev['type'], dev['fstype'],
>> +                                     dev['mountpoint'], majmin)
>> +    if dev['mountpoint']:
>> +        # Sometimes the mountpoint comes with [SWAP] or other
>> +        # info which is not an actual mount point. Filtering it
>> +        regexp = re.compile(r"\[.*\]")
>> +        if regexp.search(dev['mountpoint']) is not None:
>> +            dev['mountpoint'] = ''
>> +    dev['path'] = dev_path
>> +    dev['name'] = name
>> +    return dev
>> diff --git a/src/wok/plugins/kimchi/model/host.py 
>> b/src/wok/plugins/kimchi/model/host.py
>> index 96f4bea..4a1cff1 100644
>> --- a/src/wok/plugins/kimchi/model/host.py
>> +++ b/src/wok/plugins/kimchi/model/host.py
>> @@ -24,7 +24,7 @@ from wok.exception import InvalidParameter
>>   from wok.exception import NotFoundError
>>   from wok.xmlutils.utils import xpath_get_text
>>
>> -from wok.plugins.kimchi import disks
>> +from wok.plugins.gingerbase import disks
>>   from wok.plugins.kimchi.model import hostdev
>>   from wok.plugins.kimchi.model.config import CapabilitiesModel
>>   from wok.plugins.kimchi.model.vms import VMModel, VMsModel
>
> _______________________________________________
> Kimchi-devel mailing list
> Kimchi-devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/kimchi-devel
>

-- 
Regards,
Suresh Babu Angadi




More information about the Kimchi-devel mailing list