#!/usr/bin/python
#remove_storage.py removes disks that were added using add_storage.py
#
#Only disks that have a conf file in /etc/storage.d/ are presented
#as choices to remove.
# Version 2.0.0

import os,sys,subprocess
import configparser
from configparser import ConfigParser
import glob
from socket import gethostname
from MythTV import MythDB

storage_dir = "/etc/storage.d"

def runcmd(cmd):
    if True :
        pass
    else:
        cmd = "echo "+cmd
    #print cmd
    cmdout = subprocess.getstatusoutput(cmd)
    #logging.debug("    %s", cmdout)
    return cmdout

def read_fstab():
    f = open('/etc/fstab', 'r')
    fstab=f.readlines()
    f.close()
    return fstab

def unmount_disk(conf):
    if os.path.ismount(conf[1]):
        print("Unmounting " + conf[1] + ".")
        cmd = "umount %s" %conf[1]
        runcmd(cmd)

def remove_fstab_entry(conf):
    fstab=read_fstab()
    f = open('/etc/fstab', 'w')
    for line in fstab:
        if not line.startswith("#"):
            if line.find(conf[1]) > -1 and line.find(conf[2]) > -1 :
                print("Removing " + conf[1] + " from fstab.")
            else:
                f.write(line)
        else:
            f.write(line)
    f.close()

def remove_SG_entries(conf):
    DB = MythDB()
    host=gethostname()
    with DB as c:
        print("Removing " + conf[1] + " storage group\n    paths from MythTV database.")
        c.execute("""delete from storagegroup where hostname = %s and dirname like %s""", (host,conf[1] + '%'))
        c.execute("""delete from settings where hostname = %s and value like %s""", (host,'SGweightPerDir:' + host + ':' + conf[1] + '%'))

def remove_disk_link(conf):
    if os.path.islink("/data/storage/disk" + str(conf[0])):
        print("Removing link /data/storage/disk%s." %(conf[0]))
        cmd = "rm -f /data/storage/disk%s" %(conf[0])
        runcmd(cmd)

def remove_disk_mount(conf):
    print("Removing mountpoint %s." %(conf[1]))
    cmd = "rm -rf %s" %(conf[1])
    runcmd(cmd)

def update_conf_file(conf):
    print("Updating %s file." %(conf[4]))
    parser = ConfigParser()
    parser.read(conf[4])
    parser.set('storage','shareable',"False")
    parser.set('storage','removed',"True")
    with open(conf[4], 'w') as conf[4]:
        parser.write(conf[4])

def usage():
    help='''
    remove_storage.py removes disks that were added using add_storage.py.
    Only disks that have a conf file in /etc/storage.d/ are presented
    as choices to remove.

    Disks removed from the system are not erased or formatted.

    Normal operations include (in this order):
        Ask which disk to remove
        Unmount the disk if mounted
        Remove disk from /etc/fstab
        Remove MythTV storage group paths in MythTV database
        Remove disk# symlink at /data/storage/
        Remove disk name mountpoint at /data/storage/
        Make shareable = False in /etc/storage.d/DISKNAME.conf
        Add removed = True in /etc/stoarge.d/DISKNAME.conf

    Options:
    -h, --help:         Show this help message.
    '''
    print(help)
    sys.exit(0)

#--------------------------------------------

def main():
    all_confs = []

    # get conf files that are not disk0 or not removed
    for conf_file in glob.glob('%s/*.conf' %storage_dir):
        this_conf = []
        parser = ConfigParser()
        parser.read(conf_file)
        mounted = ""
        try:
            disk_num = parser.get('storage', 'disk_num')
        except:
            print("\nSkipping: " + conf_file + " is missing disk_num")
            continue
        try:
            removed = parser.get('storage', 'removed')
        except:
            removed = False
        if disk_num == "0" or removed:
            continue
        this_conf.append(int(disk_num)) #0
        this_conf.append(parser.get('storage', 'mountpoint')) #1
        this_conf.append(parser.get('storage', 'uuid')) #2
        if os.path.ismount(this_conf[1]):
            this_conf.append("(mounted)") #3
        else:
            this_conf.append("") #3
        this_conf.append(conf_file) #4
        all_confs.append(this_conf)

    # sort confs on disk num
    all_confs.sort(key=lambda x: x[0])

    # exit if no disks found
    if len(all_confs) == 0:
        print("\nThere are no disks to remove. Exiting.")
        sys.exit(0)

    print("\nDisks found in /etc/storage.d/:\n")

    # print list of disks to remove
    for i,conf in enumerate(all_confs):
        print(str(i+1) + ": " + conf[1] + " (disk" + str(conf[0]) + ") " + conf[3])

    # get user input of disk to remove
    try:
        conf_select=input("\nEnter the number of the disk to remove: ")
        conf_select=int(conf_select)
        if conf_select > len(all_confs) or conf_select < 1:
            conf_select=int("e")
    except ValueError:
        print("You must enter a number between 1 and " + str(len(all_confs)) + ". Exiting.")
        sys.exit(0)

    selected_conf = all_confs[conf_select-1]

    # confirm selection
    confirm_select=input("\nDisk " + selected_conf[1] + " (disk" + str(selected_conf[0]) + ") will be removed.\nAre you sure you want to remove it (yes/no)? ")
    if confirm_select != "yes":
        print("Exiting.")
        sys.exit(0)

    print("")
    unmount_disk(selected_conf)
    remove_fstab_entry(selected_conf)
    remove_SG_entries(selected_conf)
    remove_disk_link(selected_conf)
    remove_disk_mount(selected_conf)
    update_conf_file(selected_conf)

    print("\nDisk " + selected_conf[1] + " has been removed.")

if __name__ == "__main__":
    if not os.geteuid()==0:
        sys.exit("\nRoot access is required to run this program.\n")

    if "--help" in sys.argv or "-h" in sys.argv:
        usage()
    else:
        main()
