1
  
  s355 c   s<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<p>Additionally, a 404 Not Found
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
  
  u355 c   u<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
<p>Additionally, a 404 Not Found
error was encountered while trying to use an ErrorDocument to handle the request.</p>
</body></html>
  "  wli~h
nbѿl"k    w#!/usr/bin/env python2
#
# Copyright (C) 2017 Red Hat, Inc.
# 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, see <http://www.gnu.org/licenses/>.
#
# Author: Gris Ge <fge@redhat.com>
#

import os
import errno
import json
import sys
from lsm import Client, LsmError, ErrorNumber, LocalDisk


def print_stderr(msg):
    sys.stderr.write(msg)
    sys.stderr.write("\n")


def is_free_disk(blk_path):
    """
    The manpage of open(2):
        There is one exception: on Linux 2.6 and later, O_EXCL can be used
        without O_CREAT if pathname refers to a block device.  If the block
        device is in use by the system (e.g., mounted), open() fails with the
        error EBUSY.
    Even when disk has partitions, when all partitions are not used, this
    function still treats it as free disk.
    When specific disk or its partition is used by LVM, if there is no data
    stored in it, this function still treats it as free disk.
    """
    try:
        fd = os.open(blk_path, os.O_EXCL)
        os.close(fd)
        return True
    except OSError as err:
        if err.errno == errno.EBUSY:
            return False
        elif err.errno == errno.EACCES:
            raise LsmError(ErrorNumber.PERMISSION_DENIED,
                           "Permission deny, try sudo or run as root")
        else:
            raise


def get_mpath(blk_path):
    """
    Use `/sys/block/sdX/holders/dm-0/dm/name` to get mpath name,
    use `/sys/block/sdf/holders/dm-0/dm/uuid` to check whether holder is
    multipath.
    """
    blk_name = blk_path[len("/dev/"):]
    sysfs_holder_folder = "/sys/block/%s/holders" % blk_name
    try:
        holders = os.listdir(sysfs_holder_folder)
    except FileNotFoundError:
        return None
    if len(holders) != 1:
        return None

    holder_name = holders[0]
    sysfs_dm_name_path = "/sys/block/%s/dm/name" % holder_name
    sysfs_dm_uuid_path = "/sys/block/%s/dm/uuid" % holder_name
    with open(sysfs_dm_uuid_path) as f:
        if not f.read().startswith("mpath-"):
            return None
    with open(sysfs_dm_name_path) as f:
        return f.read().strip()


def is_free_multipath(blk_path):
    mpath_name = get_mpath(blk_path)
    if mpath_name:
        return is_free_disk("/dev/mapper/%s" % mpath_name)
    return False


def find_unused_lun(c):
    """
    Return a list of lsm.Volume objects.
    Unused here means the LUN/volume meets one of following conditions:
        * the block device representing LUN/Volume could be opened with O_EXCL,
          which means its block is completely free.
        * The block device is used as PV of LVM, but not been used.
    """
    vols = c.volumes()
    vpd83_to_vol_hash = {}
    free_vol_dict