#!/usr/bin/python3

# Copyright (c) 2014, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
# Written by Christopher J. Morrone <morrone2@llnl.gov>
# LLNL-CODE-468512
#
# This file is part of lustre-tools-llnl.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License (as published by the
# Free Software Foundation) version 2, dated June 1991.
#
# This program 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
# terms and conditions of the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

# Given a zfs dataset for a Lustre OST and the object number of a file
# in that dataset, this script will call zdb to retreive the Lustre FID
# and print it out in standard Lustre FID format.

import sys
import subprocess

def from_bytes(data):
    return hex(sum(data[i] << i * 8 for i in range(len(data))))

def main():
    if len(sys.argv) != 3:
        print('Usage:', sys.argv[0], '<dataset>', '<object>')
        return 1

    cmd = ['zdb', '-e', '-vvv', sys.argv[1], sys.argv[2]]
    process = subprocess.Popen(cmd,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               universal_newlines=True)
    stdout, stderr = process.communicate()
    result = process.returncode

    if result != 0:
        msg = 'Error %d on %s: %s %s' % (result, cmd, stdout, stderr)
        raise RuntimeError(msg)

    lines = stdout.splitlines()
    data = bytearray()
    found_fid = False

    for line in lines:
        part = line.split()
        if not part or part[0] != 'trusted.fid':
            continue
        fid = part[2]
        found_fid = True
        while len(fid) > 0:
            val = fid[0]
            fid = fid[1:]
            if val == '\\':
                val = fid[0:3]
                fid = fid[3:]
                data.append(int(val, 8))
            else:
                data.append(ord(val))
        break

    if not found_fid:
        print('FID not found on', sys.argv[1], sys.argv[2])
        return 1

    print('[%s:%s:%s]' % (from_bytes(data[0:8]),
                          from_bytes(data[8:12]),
                          from_bytes(data[12:16])))
    return 0

if __name__ == '__main__':
    sys.exit(main())
