diff options
Diffstat (limited to 'abs/core/LinHES-system/add_storage.py')
-rw-r--r-- | abs/core/LinHES-system/add_storage.py | 555 |
1 files changed, 489 insertions, 66 deletions
diff --git a/abs/core/LinHES-system/add_storage.py b/abs/core/LinHES-system/add_storage.py index 28d679c..93a67c7 100644 --- a/abs/core/LinHES-system/add_storage.py +++ b/abs/core/LinHES-system/add_storage.py @@ -11,40 +11,55 @@ import pickle import commands import sys,os import random, string +import ConfigParser +from ConfigParser import SafeConfigParser +import glob + from MythTV import MythDB, MythBE, Recorded, MythError from socket import timeout, gethostname +storage_dir = "/etc/storage.d" +pickle_file = "%s/storage.pkl" %storage_dir + -pickle_file="/usr/LH/etc/storage.pkl" +SG_MAP_BE={ 'Default' :'media/tv', +'LiveTV' :'media/tv/live', +'DB Backups' :'backup/mythtv_backups/'} +SG_MAP_FE={ + 'Videos' :'media/video', + 'Trailers' :'media/video_stuff/trailers', + 'Coverart' :'media/video_stuff/coverart', + 'Fanart' :'media/video_stuff/fanart', + 'Banners' :'media/video_stuff/banners', + 'Screenshots':'media/video_stuff/screenshots', + } -SG_MAP={ 'Default' :'tv', - 'LiveTV' :'live_tv', - 'Videos' :'video', - 'Trailers' :'video/trailers', - 'Coverart' :'video/converart', - 'Fanart' :'video/fanart', - 'Banners' :'video/banners', - 'Screenshots':'video/screenshots', - 'DB Backups' :'db_backups'} -FS_LIST=[] -for key in SG_MAP.keys(): - FS_LIST.append(SG_MAP[key]) +FS_LIST_BE=[] +for key in SG_MAP_BE.keys(): + FS_LIST_BE.append(SG_MAP_BE[key]) +FS_LIST_FE=[] +for key in SG_MAP_FE.keys(): + FS_LIST_FE.append(SG_MAP_FE[key]) class disk_device: - def __init__(self,device): + def __init__(self,device,storage_dir): device_obj = bus.get_object("org.freedesktop.UDisks", device) device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE) + self.storage_dir = storage_dir + self.top_mount_dir = "/data/storage" + self.config = ConfigParser.RawConfigParser() self.fs_map = self.get_fsmap() self.is_device = self.get_is_device(device_props) self.vendor = self.get_vendor(device_props) self.model = self.get_model(device_props) - self.mount_path = self.get_mounts(device_props) + self.mmount = False + self.f = self.get_mounts(device_props) self.is_mounted = self.get_is_mounted(device_props) self.parition_size = self.get_partition_size(device_props) @@ -57,7 +72,18 @@ class disk_device: self.device_file_path = self.get_device_file_path(device_props) self.block_partition="%s1" %self.block_path self.in_use = self.get_in_use() + self.uuid='' + self.new_mount_point='' + self.disk_num='' + + def set_partition(self,partition): + self.block_partition = "%s%s" %(self.block_path,partition) + def set_mmount(self,flag): + self.mmount = flag + + def set_disk_num(self,num): + self.disk_num=num def get_is_device(self,device_props): return device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsDrive") @@ -74,6 +100,11 @@ class disk_device: def get_is_mounted(self,device_props): return device_props.Get('org.freedesktop.UDisks.Device', "DeviceIsMounted") + def get_name(self): + filename="%s_%s" %(self.model.replace(' ',''), + self.serial_number.replace(' ','')) + return filename + def get_in_use(self): in_use = False for i in self.fs_map: @@ -82,7 +113,6 @@ class disk_device: break return in_use - def get_partition_size(self,device_props): return device_props.Get('org.freedesktop.UDisks.Device', "PartitionSize") @@ -150,8 +180,8 @@ class disk_device: return fs_map def find_fstype(self,moutpoint): - fstype="ext3" - mp=['/myth', '/data/media'] + fstype="xfs" + mp=['/myth', '/data/storage/disk0'] for i in self.fs_map: if i[1] in mp: fstype = i[2] @@ -166,7 +196,10 @@ class disk_device: new_fstype = self.find_fstype(current_media_mount) #do format - cmd = "mkfs -t %s %s " %(new_fstype,self.block_partition) + if new_fstype == "xfs": + cmd = "mkfs -t %s -f %s " %(new_fstype,self.block_partition) + else: + cmd = "mkfs -t %s %s " %(new_fstype,self.block_partition) print " Formating %s with %s" %(self.block_partition,new_fstype) runcmd(cmd) return @@ -181,7 +214,7 @@ class disk_device: if uuid == '': print "Could not find a UUID for device: %s" %partition sys.exit(1) - + self.uuid = uuid.strip() return uuid.strip() def read_fstab(self): @@ -191,7 +224,7 @@ class disk_device: return fstab def find_options_type(self,fstab): - mp=['/myth', '/data/media'] + mp=['/myth', '/data/storage/disk0'] for i in fstab: split_line=i.split() try: @@ -206,24 +239,30 @@ class disk_device: return options,i - def add_fstab(self): + def add_fstab(self,bind=False): new_fstab_list=['UUID=', 'mount_point', 'auto', 'defaults', '0', '1'] fstab=self.read_fstab() + #determine mount_path - self.new_mount_point="/data/media/%s_%s" %(self.model.replace(' ',''),self.serial_number.replace(' ','')) + self.new_mount_point="%s/%s_%s" %(self.top_mount_dir,self.model.replace(' ',''),self.serial_number.replace(' ','')) + if bind: + new_fstab_list=["/data/storage/disk0" , self.new_mount_point , "none" , "rw,bind", '0', '0'] + uuid=self.find_uuid(self.block_partition) + else: #determine options - new_options = self.find_options_type(fstab)[0] - #find blkid - self.block_partition="%s1" %self.block_path - uuid=self.find_uuid(self.block_partition) + new_options = self.find_options_type(fstab)[0] + + #find blkid + #self.block_partition="%s1" %self.block_path + uuid=self.find_uuid(self.block_partition) - #construct new line - new_fstab_list[0]="UUID=%s" %uuid - new_fstab_list[1]=self.new_mount_point - new_fstab_list[3]=new_options + #construct new line + new_fstab_list[0]="UUID=%s" %uuid + new_fstab_list[1]=self.new_mount_point + new_fstab_list[3]=new_options new_fstab_line='\t'.join(new_fstab_list) new_fstab_line="%s\n" %new_fstab_line @@ -238,13 +277,14 @@ class disk_device: f.close() return - def mount_disk(self): + def mount_disk(self,no_mount=False): try: os.stat(self.new_mount_point) except: os.makedirs(self.new_mount_point) - cmd = "mount %s" %self.new_mount_point - runcmd(cmd) + if no_mount == False: + cmd = "mount %s" %self.new_mount_point + runcmd(cmd) return def mkdirs(self,FS_LIST): @@ -260,25 +300,77 @@ class disk_device: cmd="chmod -R 775 /%s" %self.new_mount_point runcmd(cmd) - def add_sg(self,DB,host,SG_MAP): + def add_sg(self,DB,host,SG_MAP,weight='0',install_call=False): print " Adding to storage groups" + sgweight=int(weight) for key in SG_MAP.iterkeys(): #print key," : ", SG_MAP[key] - #try: - gn=key - hn=host - dn="%s/%s" %(self.new_mount_point,SG_MAP[key]) - #print dn - #print gn - #print hn + gn=key + hn=host + dn="%s/%s" %(self.new_mount_point,SG_MAP[key]) + #print dn + #print gn + #print hn + if install_call == True : + print "Will write SG for stuff after the fact" + else: with DB as c: try: c.execute("""insert into storagegroup (groupname,hostname,dirname) values (%s,%s,%s)""",(gn,hn,dn)) print " Adding location: %s to storagegroup %s" %(dn,gn) except: - print " Error inserting %s into storage groups" %dn + print " *Error inserting %s into storage groups" %dn + + if sgweight > 0: + try: + #("SGweightPerDir:server2:/mnt/video", 99, "server2"); + sgw="SGweightPerDir:%s:%s" %(hn,dn) + #print sgw + #print sgweight + #print hn + + c.execute("""insert into settings (value,data,hostname) values (%s,%s,%s)""",(sgw,sgweight,hn)) + print " Adding storage group weight of %s for %s\n" %(sgweight,gn) + except: + print " *Error setting storage group weight %s for %s\n" %(sgweight,gn) + return + def write_config(self): + print " Writing out storage.d conf file" + self.config.add_section('storage') + self.config.set('storage','uuid',self.uuid) + self.config.set('storage','mountpoint',self.new_mount_point) + self.config.set('storage','shareable','True') + self.config.set('storage','mmount',self.mmount) + self.config.set('storage','disk_num',self.disk_num) + + + filename="%s_%s.conf" %(self.model.replace(' ',''), + self.serial_number.replace(' ','')) + + configfile="/etc/storage.d/%s" %filename + print " %s" %configfile + with open(configfile, 'wb') as configfile: + self.config.write(configfile) + return + + def symlink_disk(self): + print " Creating symlink for disk number" + disk_ln="%s/disk%s" %(self.top_mount_dir,self.disk_num) + cmd = "ln -s %s %s" %(self.new_mount_point,disk_ln) + print cmd + runcmd(cmd) + + def symlink(self): + pass + print " Creating symlink" + cmd = "ln -s %s/media /myth " %(self.new_mount_point) + runcmd(cmd) + + + +#end of class def runcmd(cmd): @@ -300,7 +392,7 @@ def scan_system(): ud_manager = dbus.Interface(ud_manager_obj, 'org.freedesktop.UDisks') current_drive_list=[] for dev in ud_manager.EnumerateDevices(): - drive = disk_device(dev) + drive = disk_device(dev,storage_dir) if drive.is_device and drive.device_size > 5000 and not drive.is_optical : current_drive_list.append(drive) @@ -333,7 +425,7 @@ def search_for_match(system_drive,known_drive_list): y_drive_hash = "%s_%s_%s" %(y.model,y.parition_size,y.device_file_path) if system_drive_hash == y_drive_hash : match_drive = True - print "No serial number was found, matched using hash method: %s" %system_drive.model + print "\n* No serial number was found, matched using hash method: %s" %system_drive.model break elif y.serial_number == system_drive.serial_number: @@ -347,7 +439,7 @@ def search_for_match(system_drive,known_drive_list): def prompt_to_add(current_drive): loop = True while loop: - str1 = raw_input(" Adding the drive will remove all contents on the drive. \n\nDo you wish enable this drive for MythTV storage(Y/N)?:") + str1 = raw_input("\n Adding the drive will remove all contents on the drive. \n Do you wish enable this drive for MythTV storage(Y/N)?:") if str1 in ['Y','N','y','n']: loop = False @@ -359,18 +451,42 @@ def prompt_to_add(current_drive): rc = False return rc +def prompt_to_continue(): + loop = True + #while loop: + str1 = raw_input("\n Ready to start, press Y to continue, anything else to abort:") + + #if str1 in ['Y','N','y','n']: + # loop = False + # break + #print "\n" + if str1 == 'Y' or str1 == 'y': + rc = True + else: + rc = False + return rc + + + def remove_pickle(): try: - print "Resetting list of known drives." - + print "* Resetting list of known drives." os.remove(pickle_file) except: pass - +def last_disk_num(): + parser = SafeConfigParser() + num_list = [] + for conf_file in glob.glob('%s/*.conf' %storage_dir): + parser.read(conf_file) + disk_num = parser.get('storage', 'disk_num') + num_list.append(int(disk_num)) + num_list.sort() + return num_list[-1] #-------------------------------------------- -def main(scan_only): +def main(scan_only, destruction, no_mount, install_call , dir_fe_only): global bus bus = dbus.SystemBus() @@ -378,7 +494,7 @@ def main(scan_only): known_drive_list=[] known_drive_list = read_known_list() process_list=[] - + no_process_list=[] for i in system_drive_list: @@ -390,23 +506,29 @@ def main(scan_only): #print "--" if search_for_match(i,known_drive_list) or i.in_use : - print " Storage is already in use or previously skipped: %s location: %s size: %s" %(i.model,i.block_path,i.device_size) + print "\n" + print " Storage is already in use or previously skipped:%s" %i.model + print " location: %s" %i.block_path + print " size: %s" %i.device_size continue else: - print "\n" if not scan_only: print "\n" print "-------------------------------------------------------------" - - print "Found new hard drive: %s location: %s size: %s \n" %(i.model,i.block_path,i.device_size) + print " Found new hard drive: %s" %i.model + print " location: %s" %i.block_path + print " size: %s " %i.device_size if prompt_to_add(i) : - print "\nDisk will be added to the storage pool!" + print "\n Disk will be added to the storage pool!" process_list.append(i) + else: + no_process_list.append(i) else: process_list.append(i) - + print " End of scan" + print "---------------------------------------" if scan_only: if len(process_list) > 0: f = open('/tmp/scan_report', 'w') @@ -416,31 +538,309 @@ def main(scan_only): f.close() sys.exit(0) + for i in no_process_list: + system_drive_list.append(i) + if len(process_list) > 0: DB = MythDB() host=gethostname() + for y in process_list: + system_drive_list.remove(y) + write_known_drive_list(system_drive_list) else: print "\nDid not find any new storage to add.\n" + write_known_drive_list(system_drive_list) #BE = MythBE(db=DB) #save new list to disk_device - write_known_drive_list(system_drive_list) + #write_known_drive_list(system_drive_list) + #disk_num = last_disk_num() + + + if len(process_list) > 0: + print "\n Adding storage: \n" + if prompt_to_continue() == True: + write_known_drive_list(system_drive_list) + disk_num = last_disk_num() + for i in process_list: + print " Drive: %s" %(i.get_name()) + disk_num = disk_num + 1 + if destruction == True: + i.partition_disk() + i.format_disk() + i.add_fstab() + i.mount_disk(no_mount) + if destruction == True: + if dir_fe_only != True: + i.mkdirs(FS_LIST_BE) + i.mkdirs(FS_LIST_FE) + i.set_disk_num(disk_num) + i.write_config() + system_drive_list.append(i) + write_known_drive_list(system_drive_list) + + i.symlink_disk() + #always create the FE groups(video)..do not need to create Be + if dir_fe_only != True: + i.add_sg(DB,host,SG_MAP_BE) + + i.add_sg(DB,host,SG_MAP_FE) + + print "-----" + cmd = "systemconfig.py -m fileshare" + runcmd(cmd) + #i.add_sg(DB,host,SG_MAP) + +def myth_main(no_mount,install_call,dir_fe_only): + global bus + bus = dbus.SystemBus() + #search for root + f = open('/etc/fstab', 'r') + fstab=f.readlines() + f.close() + for i in fstab: + split_line=i.split() + if not split_line: + continue + + try: + if split_line[1] == "/" : + uuid_device = split_line[0] + break + except: + print "Couldn't find / in fstab" + sys.exit(1) + if uuid_device.startswith("UUID"): + uuid_device = uuid_device.split("=")[1] + cmd = "blkid -U %s" %uuid_device + device = runcmd(cmd)[1] + else: + device = uuid_device.strip() + #should have something like /dev/sda1 + #remove all the digits + device = ''.join([letter for letter in device if not letter.isdigit()]) + + + system_drive_list = scan_system() + for i in system_drive_list: + if i.block_path == device: + break + else: + print "Could'nt find root device in block list" + sys.exit(1) + if not install_call == True: + DB = MythDB() + host=gethostname() + else: + DB = None + host=gethostname() + + + print " Drive: %s" %(i.get_name()) + i.set_mmount(True) + i.set_partition("7") + i.set_disk_num(0) + i.add_fstab(True) + #if not install_call: + i.mount_disk(no_mount) + i.write_config() + #always create the FE groups(video)..do not need to create Be + if dir_fe_only != True: + i.add_sg(DB,host,SG_MAP_BE,'99',install_call) - for i in process_list: - i.partition_disk() - i.format_disk() - i.add_fstab() - i.mount_disk() - i.mkdirs(FS_LIST) - i.add_sg(DB,host,SG_MAP) + i.add_sg(DB,host,SG_MAP_FE,'99',install_call) + + i.symlink() + cmd = "systemconfig.py -m fileshare" + runcmd(cmd) + +class reconstruct_path: + def __init__(self,conf_file): + self.conf_file = conf_file + parser = SafeConfigParser() + parser.read(self.conf_file) + + + self.uuid = parser.get('storage', 'uuid') + self.mount_point = parser.get('storage', 'mountpoint') + self.shareable = parser.get('storage', 'shareable') + self.myth_mount = parser.get('storage', 'mmount') + self.bind = self.myth_mount + self.disk_num = parser.get('storage', 'disk_num') + self.top_mount_dir = os.path.dirname(self.mount_point) + + def get_conf(self): + return self.conf_file + + def get_uuid(self): + return self.uuid + + def get_mount_point(self): + return self.mount_point + + def get_shareable(self): + return self.shareable + + def get_is_myth_mount(self): + return self.myth_mount + + def get_disk_num(self): + return self.disk_num + + def create_mount_point(self): + try: + os.stat(self.mount_point) + except: + os.makedirs(self.mount_point) + + def find_options_type(self,fstab): + mp=['/myth', '/data/storage/disk0'] + for i in fstab: + split_line=i.split() + try: + if split_line[1] in mp: + options = split_line[3] + break + else: + options = "defaults" + mount_point = i + except: + options = "defaults" + return options,i + + def read_fstab(self): + f = open('/etc/fstab', 'r') + fstab=f.readlines() + f.close() + return fstab + + def check_in_fstab(self,fstab,check_path): + + for line in fstab: + if line.find(check_path) > -1: + return True + return False + + def append_fstab(self,line): + new_fstab_line='\t'.join(line) + new_fstab_line="%s\n" %new_fstab_line + + f = open('/etc/fstab', 'a') + #f = open('/tmp/fstab', 'a') + f.write(new_fstab_line) + f.write("\n") + f.close() + + def symlink(self): + print " Creating symlink" + if not os.path.exists("/myth"): + cmd = "ln -s %s/media /myth " %(self.mount_point) + runcmd(cmd) + else: + print " Skipping symlink, path already present" + + def symlink_disk(self): + print " Creating symlink for disk number" + disk_ln="%s/disk%s" %(self.top_mount_dir,self.disk_num) + cmd = "ln -s %s %s" %(self.mount_point,disk_ln) + runcmd(cmd) + + + def add_fstab(self): + new_fstab_list=['UUID=', 'mount_point', 'auto', 'defaults', '0', '1'] + fstab=self.read_fstab() + + if self.bind == "True": + self.symlink() + + if self.check_in_fstab(fstab,self.uuid) == True: + print " Found storage in fstab, will not add it" + else: + print " Adding storage to fstab" + if self.bind == "True" : + print " Bind mount" + new_fstab_list=["/data/storage/disk0" , self.mount_point , "none" , "rw,bind", '0', '0'] + if self.check_in_fstab(fstab,self.mount_point) == False: + self.append_fstab(new_fstab_list) + else: + print " Found bind storage in fstab, will not add it" + + else: + #construct new line + new_options = self.find_options_type(fstab)[0] + new_fstab_list[0]="UUID=%s" %self.uuid + new_fstab_list[1]=self.mount_point + new_fstab_list[3]=new_options + self.append_fstab(new_fstab_list) + + def mount_disk(self,no_mount=False): + try: + os.stat(self.mount_point) + except: + os.makedirs(self.mount_point) + if no_mount == False : + cmd = "mount %s" %self.mount_point + runcmd(cmd) + return + +def reconstruct_mounts(no_mount): + print "Recreating devices based on contents of /etc/storage.d" + for conf_file in glob.glob('%s/*.conf' %storage_dir): + print "\n" + cf = reconstruct_path(conf_file) + + #print cf.get_conf() + #print cf.get_uuid() + print " %s" %cf.get_mount_point() + #print cf.get_shareable() + #print cf.get_is_myth_mount() + #print cf.get_disk_num() + + cf.create_mount_point() + cf.add_fstab() + cf.symlink_disk() + cf.mount_disk(no_mount) + + pass + + +def usage(): + help='''\n + Add storage is designed to find and setup new disks for mythtv usage. + It's a powerfull that could destroy data if not used correctly, so please be careful. + Normal operations include (in this order): + Partition the disk + Format the disk + Add disk to /etc/fstab + Mount the disk + Create the directory + Write out the config file to /etc/storage.d + Add new locations to mythtv storage groups + + options: + + --no_mount : Do not mount the disk, only add it to /etc/fstab and create the dir. + --no_destruction: Will not partition or format the disk + --new_init : Erase the list of new disks and rescan. + --report : will scan the disks and print out if it found new storage. + --fe_only : Will only create the storage group dir for videos..excludes tv + ''' + print help + sys.exit(0) if __name__ == "__main__": scan_only = False + myth_mount = False + no_mount = False + destruction = True + install_call = False + dir_fe_only = False + reconstruct = False try: os.remove("/tmp/scan_report") except: @@ -449,13 +849,36 @@ if __name__ == "__main__": if not os.geteuid()==0: sys.exit("\nRoot access is required to run this program\n") + if "--help" in sys.argv: + usage() + + if "--install_call" in sys.argv: + install_call = True + + if "--no_mount" in sys.argv : + no_mount = True + + if "--no_destruction" in sys.argv: + destruction = False + if "--new_init" in sys.argv : remove_pickle() if "--report" in sys.argv : scan_only = True - main(scan_only) + if "--fe_only" in sys.argv: + dir_fe_only = True + + if "--reconstruct" in sys.argv: + reconstruct = True + + if "--double_myth" in sys.argv: + myth_main(no_mount,install_call,dir_fe_only) + elif reconstruct == True: + reconstruct_mounts(no_mount) + else: + main(scan_only,destruction,no_mount, install_call, dir_fe_only) |