#!/usr/bin/python # -*- coding: utf-8 -*- # DESCRIPTION: operation install method # # SCRIPT NAME: ri_oper.py # # MENTOR: Li Zhi # # AUTHOR: Ling Fen # # EMAIL: fling@linx-info.com # # DATE: 2010-09-20 # # HISTORY: # REVISOR DATE MODIFICATION # Ling Fen 2010-09-04 create import ri_data import ri_dep import os,sys,time import subprocess import signal sys.path.append('../new_partition/') import partition_data as p_d display_operation = None display_sub_operation = None display_scale = None language = 'english' class Rate: ''' class for installing progress, value is from 0 to 100''' value = 0 @staticmethod def increase(n, max=100): if Rate.value+n <= max: Rate.value += n @staticmethod def set(n): Rate.value = n class Operation: ''' This is a common base class for all install operations. The instances of its derived class should have the following data members: chinese_name - operation name english_name - operation name script - shell script name return_value - shell script return value score - an abstract value, for example score is 5, steps - the subprocess of the number of runs current_step - the subprocess run one time total is 100, if this operations is completed, 5% work is done. and the following methods: get_arguments - prepare arguments for script get_stdin - prepare stdin for script install - install progress ''' def __init__(self,e,c,s,scr): ''' Operation(base class) init method return_value is a dict, key is return code, value is a tuple, first element is English, second element is Chinese.''' self.return_value = {0:('Success', u'成功'), \ 1:('Argument error',u'参数错误'), \ 2:("Deivce node doesn't exist",u"设备节点不存在"),\ 3:("File system hasn't been implemented",u'文件系统没有实现'),\ } self.english_name = e self.chinese_name = c self.script = s self.score = scr self.steps = 1 self.current_step = 0 def install(self): if display_operation: display_operation(language == 'chinese' and self.chinese_name or self.english_name) max = Rate.value+self.score <100 and Rate.value+self.score or 100 process = subprocess.Popen("./%s " %self.script + ' '.join(self.get_arguments()),\ stdin=subprocess.PIPE,stdout=subprocess.PIPE, shell=True, \ preexec_fn=self.sigpipe_handle, \ cwd="%s/../operation" %os.path.split(os.path.realpath(__file__))[0]) process.stdin.write(self.get_stdin()) process.stdin.close() while True: line = process.stdout.readline() if not line: break if line[0] == '@' and self.current_step < self.steps: self.current_step += 1 if display_sub_operation: display_sub_operation(line[1:]) Rate.increase(float(self.score)/self.steps, max) if display_scale: display_scale() ret = process.wait() Rate.set(max) if display_scale: display_scale() return ret def sigpipe_handle(self): signal.signal(signal.SIGPIPE,signal.SIG_DFL) def get_arguments(self): return [] def get_stdin(self): return '' @staticmethod def getarch(): cmd='uname -m' result = subprocess.Popen(cmd,stdout=subprocess.PIPE,shell=True) arch = result.stdout.readline().rstrip() return arch class MakePartitions(Operation): '''class for make partitions''' def __init__(self, scr): Operation.__init__(self, 'Make partition', u'磁盘分区', 'partition_disks.sh', scr) def get_stdin(self): args = ' ' n = 0 disks = p_d.Partition.dict.keys() disks.sort() for d in disks: if p_d.Partition.dict[d]['partition_table'] == '': continue if p_d.Partition.dict[d]['from_os'] == 'no': args += '%s mklabel %s\n' %(d, p_d.Partition.dict[d]['partition_table']) partitions = p_d.sort_partitions(p_d.Partition.dict, d, 'partition') for p in partitions: fs_type = '' p_type = '' flags = '' set_flg = '' if p_d.Partition.dict[d]['partition'][p]['from_os'] == 'yes': continue #fs_type = p_d.Partition.dict[d]['partition'][p]['filesystem'] end = p_d.Partition.dict[d]['partition'][p]['end'] start = p_d.Partition.dict[d]['partition'][p]['start'] p_type = p_d.Partition.dict[d]['partition'][p]['type'] partition = p_d.Partition.dict[d]['partition'][p]['num'] flags = p_d.Partition.dict[d]['partition'][p]['flags'] #mkpart = "%s mkpart %s %s %s %s" %(d, p_type, fs_type, start, end) mkpart = "%s mkpart %s %s %s" %(d, p_type, start, end) if flags.strip(): set_flg = "set %s %s on" %(partition, flags) n += 1 args += "%s %s\n" %(mkpart, set_flg) self.steps += n return args class Format(Operation): ''' class for format partition ''' def __init__(self, scr): Operation.__init__(self, 'Format partition', u'格式化分区', 'format_partition.sh', scr) self.return_value[127] = ('No tool to format partitions', u'没有格式化硬盘分区的工具') def get_stdin(self): format = '' n = 0 disks = p_d.Partition.dict.keys() disks.sort() mds = ri_data.Raid.dict.keys() mds.sort() for d in disks: partitions = p_d.sort_partitions(p_d.Partition.dict, d, 'partition') for p in partitions: fs_type = p_d.Partition.dict[d]['partition'][p]['filesystem'] fmt = p_d.Partition.dict[d]['partition'][p]['format'] if fmt.strip() == 'yes' and fs_type.strip(): format += "%s %s\n" %(p, fs_type) n += 1 for m in mds: R = ri_data.Raid.dict[m] fs_type = R.filesystem fmt = R.fmt if fmt.strip() == 'yes' and fs_type.strip(): format += "/dev/%s %s\n" %(m, fs_type) n += 1 self.steps += n return format class MakeRaid(Operation): """class for make raid""" def __init__(self,scr): Operation.__init__(self,"Making a RAID", u"正在制作RAID磁盘阵列", "mkraid_wrapper.sh", scr) self.return_value[2] = ('this levelY need more devices',u'制作这个级别的raid需要更多的分区.') self.return_value[3] = ('the raid name has exist',u'这个raid已经存在.') self.return_value[4] = ('this shell not support this RAID level', u'不能做这个级别的raid.') self.return_value[5] = ('level0 donot need spare devices', u'raid0不需要备用分区') self.return_value[6] = ('incorrect active and spare devices name, maybe it has been used', u'这个分区已经被做过raid了.') self.return_value[7] = ('create or assimble raid device lose', u'制作raid不成功') def get_stdin(self): args = '' n = 0 for instance in ri_data.Raid.dict.values(): if instance.from_os == 'no': args += '-n /dev/%s -l %s -a %s' %(instance.device, instance.level,','.join([ '/dev/%s' %ac for ac in instance.active_components])) if instance.spare_components : args += ' -s %s' % ','.join([ '/dev/%s' %sp for sp in instance.spare_components]) args +='\n' n += 1 self.steps += n return args class MakeRaidConfigure(Operation): """class for make raid configure""" def __init__(self,scr): Operation.__init__(self,"Generate /etc/mdadm.conf",u"生成raid配置文件","mkraidconf.sh",scr) def install(self): if ri_data.Raid.dict.values(): return Operation.install(self) else: max = Rate.value+self.score <100 and Rate.value+self.score or 100 Rate.set(max) return 0 def get_arguments(self): return ["/etc/mdadm.conf"] class Mount(Operation): """class for mount partition""" # dict saved only device and mount point dict={} def __init__(self,scr): Operation.__init__(self,'Mount partition', u'挂载分区', 'mount_partition.sh',scr) def get_stdin(self): mount = '' n = 0 disks = p_d.Partition.dict.keys() disks.sort() mds = ri_data.Raid.dict.keys() mds.sort() for d in disks: partitions = p_d.sort_partitions(p_d.Partition.dict, d, 'partition') for p in partitions: mp = p_d.Partition.dict[d]['partition'][p]['mount_point'] fs = p_d.Partition.dict[d]['partition'][p]['filesystem'] if mp.strip() and fs.strip(): mount += "%s %s %s\n" %(p, mp, fs) n += 1 for m in mds: R = ri_data.Raid.dict[m] mp = R.mp fs = R.filesystem if mp.strip() and fs.strip(): mount += "/dev/%s %s %s\n" %(m, mp, fs) n += 1 self.steps += n return mount class InstallPkg(Operation): """class for install packages""" def __init__(self,scr): Operation.__init__(self,'Install packages',u'安装软件包','install_pkg.sh',scr) self.return_value[2]=("Software source directory doesn't exist",u"软件包所在目录不存在") self.return_value[3]=("Software package doesn't exist",u"软件包不存在") def get_stdin(self): pkgname = set(ri_data.Group.get_install_pkgs() + self.get_dependency_pkg()) self.steps += len(pkgname) return '\n'.join(pkgname)+'\n' def get_arguments(self): return ["-s","/Rocky/packages"] def get_dependency_pkg(self): ri_dep.dependency_init() return ri_dep.dependency_init.dep_dict.keys() + ri_dep.dependency_init.func_dep_list class ConfigureFstab(Mount): """class for configure /etc/fstab""" def __init__(self,scr): Operation.__init__(self,'Configure /etc/fstab',u'配置/etc/fstab文件','configure_fstab.sh',scr) self.return_value[2]=("/etc/fstab doesn't exist",u"/etc/fstab文件不存在") def get_stdin(self): fstab='' disks = p_d.Partition.dict.keys() disks.sort() mds = ri_data.Raid.dict.keys() mds.sort() for d in disks: partitions = p_d.sort_partitions(p_d.Partition.dict, d, 'partition') for p in partitions: mp = p_d.Partition.dict[d]['partition'][p]['mount_point'] fs = p_d.Partition.dict[d]['partition'][p]['filesystem'] if fs.strip() == 'linux-swap': fs = 'swap' mp = 'swap' if mp.strip() and fs.strip(): fstab += "%s %s %s\n" %(p, mp, fs) for m in mds: R = ri_data.Raid.dict[m] mp = R.mp fs = R.filesystem if fs.strip() == 'linux-swap': fs = 'swap' mp = 'swap' if mp.strip() and fs.strip(): fstab += "/dev/%s %s %s\n" %(m, mp, fs) # process fstab to sort fstab_new = '' cmd_t = "echo '%s' | sort -k 2" %fstab std_out = os.popen(cmd_t).readlines() for l in std_out: fstab_new += l return fstab_new class GenerateIssue(Operation): """class for generate /etc/issue""" def __init__(self,scr): Operation.__init__(self,'Generate /etc/issue',u'生成/etc/issue文件','generate_issue.sh',scr) def get_arguments(self): args=[] # FIXME if tag file format is error? if os.path.isfile("/tag"): fd=open("/tag","r") string = fd.read() list = string.split('\n')[0].split('-') args = ['-v']+[list[1]]+["-a"]+[list[5]]+["-r"]+[list[6]]+["-d"]+['-'.join(list[2:5])] fd.close() return args class ConfigureNetwork(Operation): """class for configure network""" def __init__(self,scr): Operation.__init__(self,'Configure network',u'配置网络','configure_network.sh',scr) self.return_value[2]=("Ip address, network, or geteway is incorrect",u"Ip地址、子网掩码、网关不正确") self.return_value[3]=("/etc/hosts, /etc/resolv.conf, /etc/sysconfig/network-devices/ifcfg.template, or /etc/sysconfig/network doesn't exist",\ u"文件/etc/hosts,/etc/resolv.conf,/etc/sysconfig/network-devices/ifcfg.template或/etc/sysconfig/network文件不存在") def get_arguments(self): network='' data=ri_data.Network if data.configuration == "static": network+="-t static " if data.hostname is not '': network+="-h %s "%data.hostname if data.domain is not '': network+="-d %s "%data.domain if data.ip is not '': network+="-i %s "%data.ip if data.mask is not '': network+="-n %s "%data.mask if data.gateway is not '': network+="-g %s "%data.gateway if data.primary_dns is not '': network+="-p %s "%data.primary_dns if data.secondary_dns is not '': network+="-s %s "%data.secondary_dns else: network+="-t dynamic " if data.hostname: network+="-h %s "%data.hostname return [network] class MakeServiceAutoBoot(Operation): """class for make service autoboot""" def __init__(self,scr): Operation.__init__(self,"Make service autoboot",u"启动服务器","mk_serv_autoboot.sh",scr) self.return_value[2]=("Boot script doesn't exist",u"引导脚本不存在") def get_stdin(self): serv='' n = 0 for i in ri_data.Service.list: if i.start == "yes": serv+='%s %s %s %s\n'%(i.package,i.script,i.name,i.number) n += 1 self.steps += n return serv class CopyKernel(Operation): """class for copy kernel""" def __init__(self,scr): Operation.__init__(self,"Copy kernel",u"拷贝内核","copy_kernels.sh",scr) self.return_value[1]=("kernel directory, modules directory, initrd.gz, or makeinitrd doesn't exist",u"内核目录、模块目录、initrd.gz文件、makeinitrd指令不存在") class ExecFinishInstall(Operation): """class for exec finish install""" def __init__(self,scr): Operation.__init__(self,"Exec finish_install script",u"安装完成执行的脚本","exec_finish_install.sh",scr) def get_stdin(self): return "99finish_install.sh\n" class BootLoader(Operation): """class for bootloader""" def __init__(self,scr): Operation.__init__(self,"Install bootloader",u"安装引导程序","install_bootloader.sh",scr) self.return_value[2]=("Bootloader type hasn't been specified",u"没有指定引导程序的类型") self.return_value[3]=("Bootloader hasn't been implemented",u"没有实现bootloader") self.return_value[127]=("No tool to bootloader. E.g grub",u"没有安装引导程序的工具。如grub2等") def get_arguments(self): if self.getarch() == "ppc64": pass elif self.getarch() == "ia64": return ["-t elilo"] else: return ["-t grub2"] class ConfigureBootloader(Operation): """class for configure bootloader file""" def __init__(self,scr): Operation.__init__(self,"Configure bootloader",u"配置bootloader","configure_bootloader_cnf.sh",scr) self.return_value[2]=("Bootloader type hasn't specified",u"没有指定引导程序的类型") self.return_value[3]=("Bootloader hasn't been implemented",u"没有实现bootloader") self.return_value[4]=("Bootloader configuration file doesn't exist",u"引导程序配置文件不存在") def get_arguments(self): list=[] if self.getarch() == "ppc64": pass elif self.getarch() == "ia64": tp = "elilo" else: tp = "grub2" # FIXME if tag file format is error? if os.path.isfile("/tag"): fd = open("/tag","r") string = fd.read() list = string.split('-') fd.close() #bootloader=['-t',tp,'-o',list[0][5:].split('.')[0]+'.'+list[0][5:].split('.')[1],'-k','"linx_serial=%s vga=791 quiet"' %ri_data.SerialNumber.value.strip()] bootloader=['-t',tp,'-k','"linx_serial=%s vga=791"' %ri_data.SerialNumber.value.strip()] #for k in Mount.dict.keys(): # if '/' == Mount.dict[k]: # bootloader += ['-r',k] # if '/boot' == Mount.dict[k]: # bootloader += ['-b',k] return bootloader