#!/usr/bin/env python3
#
# Copyright (C) 2016 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
# published by the Free Software Foundation.
#
# 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
# 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, see <http://www.gnu.org/licenses/>.
#
# File: vyos-show-version
# Purpose:
#    Displays image version and system information.
#    Used by the "run show version" command.


import os
import sys
import subprocess
import argparse
import json

import pystache

import vyos.version
import vyos.limericks


parser = argparse.ArgumentParser()
parser.add_argument("-a", "--all", action="store_true", help="Include individual package versions")
parser.add_argument("-f", "--funny", action="store_true", help="Add something funny to the output")
parser.add_argument("-j", "--json", action="store_true", help="Produce JSON output")

def read_file(name):
    try:
        with open (name, "r") as f:
            data = f.read()
        return data.strip()
    except:
        # This works since we only read /sys/class/* stuff
        # with this function
        return "Unknown"

version_output_tmpl = """
Version:          VyOS {{version}}
Built by:         {{built_by}}
Built on:         {{built_on}}
Build ID:         {{build_id}}

Architecture:     {{system_arch}}
Boot via:         {{boot_via}}
System type:      {{system_type}}

Hardware vendor:  {{hardware_vendor}}
Hardware model:   {{hardware_model}}
Hardware S/N:     {{hardware_serial}}
Hardware UUID:    {{hardware_uuid}}

Copyright:        VyOS maintainers and contributors

"""

if __name__ == '__main__':
    args = parser.parse_args()

    version_data = vyos.version.get_version_data()

    # Get system architecture (well, kernel architecture rather)
    version_data['system_arch'] = subprocess.check_output('uname -m', shell=True).decode().strip()


    # Get hypervisor name, if any
    system_type = "bare metal"
    try:
        hypervisor = subprocess.check_output('hvinfo 2>/dev/null', shell=True).decode().strip()
        system_type = "{0} guest".format(hypervisor)
    except subprocess.CalledProcessError:
        # hvinfo returns 1 if it cannot detect any hypervisor
        pass
    version_data['system_type'] = system_type


    # Get boot type, it can be livecd, installed image, or, possible, a system installed
    # via legacy "install system" mechanism
    # In installed images, the squashfs image file is named after its image version,
    # while on livecd it's just "filesystem.squashfs", that's how we tell a livecd boot
    # from an installed image
    boot_via = "installed image"
    if subprocess.call(""" grep -e '^overlay.*/filesystem.squashfs' /proc/mounts >/dev/null""", shell=True) == 0:
        boot_via = "livecd"
    elif subprocess.call(""" grep '^overlay /' /proc/mounts >/dev/null """, shell=True) != 0:
        boot_via = "legacy non-image installation"
    version_data['boot_via'] = boot_via
    

    # Get hardware details from DMI
    version_data['hardware_vendor'] = read_file('/sys/class/dmi/id/sys_vendor')
    version_data['hardware_model']  = read_file('/sys/class/dmi/id/product_name')

    # These two assume script is run as root, normal users can't access those files
    version_data['hardware_serial'] = read_file('/sys/class/dmi/id/subsystem/id/product_serial')
    version_data['hardware_uuid']   = read_file('/sys/class/dmi/id/subsystem/id/product_uuid')


    if args.json:
        print(json.dumps(version_data))
        sys.exit(0)
    else:
        output = pystache.render(version_output_tmpl, version_data).strip()
        print(output)

        if args.all:
           print("Package versions:")
           os.system("dpkg -l")

        if args.funny:
            print(vyos.limericks.get_random())