
from __future__ import absolute_import
from __future__ import division

import json
import logging
import yaml
from six import iteritems

from vdsm.common import cmdutils
from vdsm.common import commands
from vdsm.gluster import exception as ge

from . import gluster_mgmt_api


log = logging.getLogger("Gluster")
_lvsCommandPath = cmdutils.CommandPath("lvs",
                                       "/sbin/lvs",
                                       "/usr/sbin/lvs",)
_pvsCommandPath = cmdutils.CommandPath("pvs",
                                       "/sbin/pvs",
                                       "/usr/sbin/pvs",)
_vdoCommandPath = cmdutils.CommandPath("vdo",
                                       "/bin/vdo",
                                       "/usr/bin/vdo",)


@gluster_mgmt_api
def logicalVolumeList():
    rc, out, err = commands.execCmd([_lvsCommandPath.cmd,
                                     "--reportformat", "json",
                                     "--units", "b",
                                     "--nosuffix",
                                     "-o",
                                     "lv_size,data_percent,"
                                     "lv_name,vg_name,pool_lv"])
    if rc:
        raise ge.GlusterCmdExecFailedException(rc, out, err)

    volumes = []
    for lv in json.loads("".join(out))["report"][0]["lv"]:
        lv["lv_size"] = int(lv["lv_size"])
        if not lv["pool_lv"] and lv["data_percent"]:
            lv["lv_free"] = int(
                (1 - float(lv.pop("data_percent")) / 100) * lv["lv_size"]
            )
        else:
            lv["lv_free"] = 0
            lv.pop("data_percent")
        volumes.append(lv)
    return volumes


@gluster_mgmt_api
def physicalVolumeList():
    rc, out, err = commands.execCmd([_pvsCommandPath.cmd,
                                     "--reportformat", "json",
                                     "--units", "b",
                                     "--nosuffix",
                                     "-o", "pv_name,vg_name"])
    if rc:
        raise ge.GlusterCmdExecFailedException(rc, out, err)
    return json.loads("".join(out))["report"][0]["pv"]


@gluster_mgmt_api
def vdoVolumeList():
    rc, out, err = commands.execCmd([_vdoCommandPath.cmd, "status"], raw=True)
    if rc:
        raise ge.GlusterCmdExecFailedException(rc, out, err)
    vdoData = yaml.safe_load(out)

    result = []
    for vdo, data in iteritems(vdoData["VDOs"]):
        entry = {}
        entry["device"] = data["Storage device"]
        for mapper, stats in iteritems(data["VDO statistics"]):
            blockSize = stats["block size"]
            entry["name"] = mapper
            entry["size"] = stats["1K-blocks"] * 1024
            entry["free"] = stats["1K-blocks available"] * 1024
            entry["logicalBytesUsed"] = (
                stats["logical blocks used"] * blockSize
            )
            entry["physicalBytesUsed"] = (
                stats["data blocks used"] * blockSize
            )
        result.append(entry)

    return result
