diff --git a/interface/check_oldconf.py b/interface/check_oldconf.py new file mode 100644 index 0000000..886fa7b --- /dev/null +++ b/interface/check_oldconf.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +#! coding: utf-8 + +ins_xml = './install.xml' +import Tkinter +import sys +import subprocess + +message = {} +message['english'] = 'The system detects the presence of the last\n \ +installation to retain the configuration file, whether to use' +message['chinese'] = '系统检测到存在上次安装保留的配置文件,是否使用它' + + +def ok(): + root.destroy() + +def cancel(): + cmd='rm -rf ' + ins_xml + subprocess.Popen(cmd,shell=True) + root.destroy() + +def init(language): + global root + root = Tkinter.Tk() + root.geometry("%sx%s+%d+%d" % (root.winfo_screenwidth()/2,\ + root.winfo_screenheight()/2,\ + root.winfo_screenwidth()/4, + root.winfo_screenheight()/4)) + txt = message[language] + lab = Tkinter.Label(root,text=txt) + lab.grid(row=1,column=1) + btn1 = Tkinter.Button(root,text='OK',command=sys.modules[__name__].ok) + btn2 = Tkinter.Button(root,text='Cancle',command=sys.modules[__name__].cancel) + btn1.grid(row=2,column=0,padx=40,pady=100,ipadx=20) + btn2.grid(row=2,column=2,padx=20,pady=100,ipadx=15) + root.rowconfigure(1,weight=2) + root.columnconfigure(1,weight=1) + root.rowconfigure(2,weight=1) + root.mainloop() + +init(sys.argv[1]) + diff --git a/interface/ri_cmd.py b/interface/ri_cmd.py index 7c0e2b1..a717802 100644 --- a/interface/ri_cmd.py +++ b/interface/ri_cmd.py @@ -2,6 +2,7 @@ ''' handle commands.''' import ri_widget +import os def quit(): ''' correspond to quit button ''' @@ -32,8 +33,9 @@ def next(): ri_widget.Widget.dict[wid_name].show() else: - ri_widget.MessageBox.dict["next"].show() - + code = ri_widget.MessageBox.dict["next"].show() + if code == True: + os.execl('/usr/bin/python','python','ri_install.py', "-d","tk") from ri_tk_cmd import * diff --git a/interface/ri_data.py b/interface/ri_data.py index 7420ee3..296dd9e 100644 --- a/interface/ri_data.py +++ b/interface/ri_data.py @@ -10,7 +10,7 @@ install_xml = '../xml/install.xml' config_xml = '../xml/config.xml' def to_xml_attr(doc, node, cls, name): - ''' This method is called by to_xml. Its function is to create an attribute, and set its value based on Network data member + ''' This method is called by to_xml. Its function is to create an attribute, and set its value based on Network data member doc - xml document node - xml node cls - python class/python instance @@ -29,7 +29,7 @@ class SerialNumber: @staticmethod def to_xml(doc, p_node): - ''' write SerialNumber into xml + ''' write SerialNumber into xml doc - xml document instance p_node - xml node (parent node)''' sn = doc.createElement('serial-number') @@ -40,88 +40,119 @@ p_node - xml node (parent node)''' class Partition: ''' disk partition ''' unit='' + label='' list=[] - def __init__(self, dev, st, sz, id, fr): + def __init__(self, dev, st, sz, tp, fs, fg, fr): ''' Partition init function ''' - self.device = dev - self.start = st - self.size = sz - self.id = id - self.from_os = fr + self.device = dev + self.start = st + self.size = sz + self.type = tp + self.filesystem = fs + self.flags = fg + self.from_os = fr Partition.list.append(self) @staticmethod def init_from_os(): ''' create a Partition instance from hardware info''' -# cmd = 'sfdisk -d' - # has problem on raid detection - cmd = 'cat /home/zhi/work/new_install/python/mine/sfdisk.txt' - st, o = commands.getstatusoutput(cmd) + device_list=[] + Partition.unit='GB' + cmd_cat = 'cat /proc/partitions' + st,o = commands.getstatusoutput(cmd_cat) if st: + print "Error cat : command not found or /proc/partitions dosen't exsit" return - p0 = re.compile(r'unit:\s*(\w+)') - p = re.compile(r''' -\s*(\w+)\s*: # device -\s*start=\s*(\d+)\s*, # start -\s*size=\s*(\d+)\s*, # size -\s*Id=\s*(\d+) # id -''', re.VERBOSE) + p = re.compile(r"\s*") for s in o.splitlines(): - res0 = p0.search(s) - if res0: - Partition.unit = res0.groups()[0] - res = p.search(s) - if res: - dev, start, size, id = res.groups() - Partition(dev.split('/')[-1], start, size, id, True) + ret = re.search(r".+([sh][a-zA-Z]+)\s*",s) + if ret: + if ret.group(1) in device_list: + continue + device_list.append(ret.group(1)) + for d in device_list: + st,o=commands.getstatusoutput('parted /dev/%s unit %s print'%(d,Partition.unit)) + if st: + print "Error parted :command not found" + return + for s in o.splitlines(): + ret = p.split(s) + if ret[0]=='Partition': + Partition.label=ret[-1] + if len(ret)>=5 and ret[0] == '': + # Not enough to prevent of ret + tmp =[] + ret=ret+['','',''] + for l in ret[7].split(","): + tmp.append(l.strip()) + if "raid" in tmp: + ret[7]="yes" + else: + ret[7]="no" + Partition(d+ret[1],ret[2],ret[4],ret[5],ret[6][:10] == "linux-swap" and "swap" or ret[6] ,ret[7],'yes') + + @staticmethod def init_from_xml(node): ''' create Partition instances from xml node ''' Partition.unit = node.attributes['unit'].value.encode('ascii') + Partition.label = node.attributes['label'].value.encode('ascii') for p in node.childNodes: if p.nodeType == node.ELEMENT_NODE and p.nodeName == 'partition': Partition(p.attributes['device'].value.encode('ascii'),\ - p.attributes['start'].value.encode('ascii'), \ - p.attributes['size'].value.encode('ascii'), \ - p.attributes['id'].value.encode('ascii'), \ - p.attributes['from_os'].value.encode('ascii')) + p.attributes['start'].value.encode('ascii'),\ + p.attributes['size'].value.encode('ascii'),\ + p.attributes['type'].value.encode('ascii'),\ + p.attributes['file-system'].value.encode('ascii'),\ + p.attributes['flags'].value.encode('ascii'),\ + p.attributes['from_os'].value.encode('ascii')) + @staticmethod def to_xml(doc, p_node): - ''' write all Partition instance into xml + ''' write all Partition instance into xml doc - xml document instance p_node - xml node (parent node)''' pts = doc.createElement("partitions") unit_attr = doc.createAttribute('unit') unit_attr.value = Partition.unit pts.setAttributeNode(unit_attr) + label_attr = doc.createAttribute('label') + label_attr.value = Partition.label + pts.setAttributeNode(label_attr) for p in Partition.list: pt = doc.createElement('partition') - dev_attr = doc.createAttribute('device') - start_attr = doc.createAttribute('start') - size_attr = doc.createAttribute('size') - id_attr = doc.createAttribute('id') - from_attr = doc.createAttribute('from_os') - dev_attr.value = p.device - start_attr.value = p.start - size_attr.value = p.size - id_attr.value = p.id - from_attr.value = p.from_os + dev_attr = doc.createAttribute('device') + start_attr = doc.createAttribute('start') + size_attr = doc.createAttribute('size') + type_attr = doc.createAttribute('type') + fs_attr = doc.createAttribute('file-system') + flags_attr = doc.createAttribute('flags') + from_attr = doc.createAttribute('from_os') + dev_attr.value = p.device + start_attr.value = p.start + size_attr.value = p.size + type_attr.value = p.type + fs_attr.value = p.filesystem + flags_attr.value = p.flags + from_attr.value = p.from_os pt.setAttributeNode(dev_attr) pt.setAttributeNode(start_attr) pt.setAttributeNode(size_attr) - pt.setAttributeNode(id_attr) + pt.setAttributeNode(type_attr) + pt.setAttributeNode(fs_attr) + pt.setAttributeNode(flags_attr) pt.setAttributeNode(from_attr) pts.appendChild(pt) p_node.appendChild(pts) - + # ri_tk_cmd.py use @staticmethod def get_size(dev): for p in Partition.list: if p.device == dev: return p.size - + class Raid: ''' raid information ''' list = [] @@ -137,20 +168,20 @@ class Raid: @staticmethod def init_from_os(): - #cmd = 'cat /proc/mdstat' - cmd = 'cat /home/zhi/work/new_install/python/mine/raid.txt' + cmd = 'cat /proc/mdstat' st, o = commands.getstatusoutput(cmd) if st: return dev_p = re.compile(r''' -^(md\d+)\s*: # md device -\s*active\s* # "active" -(\w+)\s* # raid type -''', re.VERBOSE) + ^(md\d+)\s*: # md device + \s*active\s* # "active" + (\w+)\s* # raid type + ''', re.VERBOSE) size_p = re.compile(r''' -^\s*(\d+) # block number -\s*blocks''', re.VERBOSE) + ^\s*(\d+) # block number + \s*blocks + ''', re.VERBOSE) for s in o.splitlines(): @@ -166,13 +197,12 @@ class Raid: spr_cmpts.append(ss[:ss.index('[')]) else: act_cmpts.append(ss[:ss.index('[')]) - continue - - if size_p.match(s).groups(): - raid_size = size_p.match(s).groups()[0] + size = size_p.match(s) + if size is not None: + raid_size = size.groups()[0] # if already detect a raid dev if raid_dev: - Raid(raid_dev, True, raid_level, raid_size, act_cmpts, spr_cmpts) + Raid(raid_dev, "yes", raid_level, raid_size, act_cmpts, spr_cmpts) # clear raid dev raid_dev='' @@ -251,7 +281,7 @@ p_node - xml node (parent node) ''' raids.appendChild(rd) p_node.appendChild(raids) - + #ri_tk_cmd.py use @staticmethod def get_size(dev): for r in Raid.list: @@ -286,6 +316,7 @@ class MountPoint: mp.directory = dir mp.filesystem = fs mp.format = fm + def device(self): return self.device @@ -293,14 +324,23 @@ class MountPoint: @staticmethod def init_from_internal(): ''' init MountPoint from internal class Partition and class Raid ''' + # add raid device in dev_in_raid + dev_in_raid = set() + for r in Raid.list: + dev_in_raid.update(r.active_components) + dev_in_raid.update(r.spare_components) + devs = [ m.device for m in MountPoint.list ] for p in Partition.list: - if p.id != 'fd' and p.device not in devs: - MountPoint(p.device, sz=p.size) + if p.device not in devs and p.device not in dev_in_raid : + MountPoint(p.device,fs=p.filesystem,sz=p.size) for r in Raid.list: - if r.device not in devs: - MountPoint(r.device, sz=r.size) + if r.device not in devs and r.from_os == 'yes': + f_s = [p.filesystem for p in Partition.list if p.device == r.active_components[0]] + MountPoint(r.device, fs=f_s[0],sz=r.size) + elif r.device not in devs: + MountPoint(r.device,sz=r.size) # now process whether a partition or raid was removed s1 = set([ m.device for m in MountPoint.list ]) @@ -321,7 +361,8 @@ class MountPoint: MountPoint(m.attributes['device'].value.encode('ascii'), \ m.attributes['directory'].value.encode('ascii'), \ m.attributes['file-system'].value.encode('ascii'), \ - m.attributes['format'].value.encode('ascii') ) + m.attributes['format'].value.encode('ascii'),\ + m.attributes['size'].value.encode('ascii')) @staticmethod def to_xml(doc, p_node): @@ -335,17 +376,20 @@ p_node - xml node (parent node)''' dir_attr = doc.createAttribute('directory') fs_attr = doc.createAttribute('file-system') fm_attr = doc.createAttribute('format') + sz_attr = doc.createAttribute('size') dev_attr.value = m.device dir_attr.value = m.directory fs_attr.value = m.filesystem fm_attr.value = m.format + sz_attr.value = m.size mp.setAttributeNode(dev_attr) mp.setAttributeNode(dir_attr) mp.setAttributeNode(fs_attr) mp.setAttributeNode(fm_attr) + mp.setAttributeNode(sz_attr) mps.appendChild(mp) p_node.appendChild(mps) - + class Network: ''' network ''' hostname ='' @@ -571,6 +615,12 @@ p_node - xml node (parent node)''' srvs.appendChild(srv) p_node.appendChild(srvs) +def install_information(): + to_xml() + xmldoc = minidom.parse(install_xml) + root = xmldoc.firstChild + return root.toxml() + def init(): ''' initialize ''' Partition.init_from_os() diff --git a/interface/ri_inst_cli.py b/interface/ri_inst_cli.py new file mode 100644 index 0000000..8efca03 --- /dev/null +++ b/interface/ri_inst_cli.py @@ -0,0 +1,46 @@ +#!/usr/bin/python +# DESCRIPTION: display module for install (cli) +# +# SCRIPT NAME: ri_inst_cli.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 +# + +from ri_oper import language, Rate +def set_task(task_name): + print task_name + +def set_sub_task(sub_task): + print sub_task + +def set_task_scale(): + print '%', Rate.value + +def set_task_over(): + string = raw_input("Rocky system install success,plase reboot now![Y?]") + if string.lower() == "y": + return True + return False + +def root_destroy(): + pass + +def error(oper, ret): + if language == 'chinese': + print "%s:\n Error number: %d\n %s"%(oper.chinese_name, ret, oper.return_value[ret][1]) + else: + print "%s:\n Error number: %d\n %s"%(oper.english_name, ret, oper.return_value[ret][0]) + + +def start(func): + func() diff --git a/interface/ri_inst_tk.py b/interface/ri_inst_tk.py new file mode 100644 index 0000000..130e978 --- /dev/null +++ b/interface/ri_inst_tk.py @@ -0,0 +1,99 @@ +#!/usr/bin/python +#coding: utf-8 +# DESCRIPTION: display module for install (tk) +# +# SCRIPT NAME: ri_inst_tk.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 +# + +from Tkinter import * +import tkMessageBox +import os +from ri_oper import language, Rate + +def set_task(task_name): + lab_operation.configure(text=task_name) + lab_operation.update() + +def set_sub_task(sub_task): + txt_suboperation.insert(END,sub_task) + txt_suboperation.see(END) + +def set_task_scale(): + scl_progress.set(Rate.value) + scl_progress.update() + +def set_task_over(): + ret = tkMessageBox.askokcancel(title="Install",message="%s"%(language=='chinese' and "凝思磐石系统安装完成,请重新启动系统"or "Rocky system install completed,plase reboot")) + return ret + +def root_destroy(): + root.destroy() + +def error(oper, ret): + if language == 'chinese': + tkMessageBox.showerror('Error',u"%s:\n 错误值: %d\n %s"%(oper.chinese_name, ret, oper.return_value[ret][1])) + else: + tkMessageBox.showerror('Error',"%s:\n Error number: %d\n %s"%(oper.english_name, ret, oper.return_value[ret][0])) + +def start(func): + root.protocol('WM_TAKE_FOCUS', func) + root.mainloop() + +#root widget +root = Tk() +root.geometry("%sx%s+0+0" %(root.winfo_screenwidth(),root.winfo_screenheight())) +root.title('Linx') + +# root subwidget +stringvar_bar=StringVar() + +#label +lab_task=Label(root,text='%s:'%(language=="chinese" and u"任务" or "Task")) +lab_progress_bar=Label(root,text='%s:'%(language=="chinese" and u"进度" \ + or 'Progress bar')) +lab_operation=Label(root,text="") +lab_linx=Label(root,text="Linx") + +txt_suboperation=Text(root,width=70,height=10) + +#operation lable and taskname +lab_task.grid (row=1, column=0, sticky='SEW') +lab_operation.grid (row=1, column=1, columnspan=2,sticky="S") +txt_suboperation.grid(row=2, column=1,columnspan=2) +lab_progress_bar.grid(row=3, column=0, sticky='NEW') +lab_linx.grid (row=4, column=1, sticky='E') + +#logo +photo_bm = PhotoImage(file="%s/../data/linxlogo.gif"\ + %os.path.split(os.path.realpath(__file__))[0]) +logo_label=Label(root,image=photo_bm) +logo_label.grid(row=0,column=0,padx=50,pady=50,sticky='NW') + +#progress bar +scl_progress=Scale(root,orient=HORIZONTAL,resolution=0.01,digits=4,from_=0,to=100,variable=stringvar_bar,label='%') +scl_progress.grid(row=3,column=1,columnspan=2,sticky='NEW') + +#root +root.rowconfigure(0,weight=1) +root.rowconfigure(1,weight=1) +root.rowconfigure(2,weight=1) +root.rowconfigure(3,weight=1) +root.rowconfigure(4,weight=1) +root.columnconfigure(0,weight=1) +root.columnconfigure(1,weight=1) +root.columnconfigure(2,weight=1) +root.columnconfigure(3,weight=1) + + diff --git a/interface/ri_install.py b/interface/ri_install.py new file mode 100644 index 0000000..7812a6c --- /dev/null +++ b/interface/ri_install.py @@ -0,0 +1,72 @@ +#!/usr/bin/python +# coding: utf-8 +# +# DESCRIPTION: install for OS +# +# SCRIPT NAME: ri_install.py +# +# Input: +# [-d|--display display-mode ] install display (tk or cli) +# [-l|--language language] insatll display language (chinese or english) +# +# MENTOR: Li Zhi +# +# AUTHOR: Ling Fen +# +# EMAIL: fling@linx-info.com +# +# DATE: 2010-09-20 +import sys +import getopt +import ri_oper +import os +def install_over(ret): + if ri_oper.Rate.value == 100 and ret == 0: + if display.set_task_over(): + print "reboot ..." + os.system("reboot") + else: + display.root_destroy() + +def main(): + global has_run + if has_run: return + has_run = True + for instance in oper_list: + ret = instance.install() + if ret: + display.error(instance, ret) + break + else: + ri_oper.display_sub_operation((ri_oper.language=='chinese' \ + and instance.chinese_name or instance.english_name)+\ + (ri_oper.language=='chinese' and u' 成功' or ' success')) + install_over(ret) + +has_run = False + +oper_list = [ri_oper.MakeRaid(5),ri_oper.Format(5),ri_oper.Mount(5),ri_oper.InstallPkg(40),ri_oper.MakeRaidConfigure(5),ri_oper.ConfigureFstab(5),ri_oper.GenerateIssue(5),ri_oper.ConfigureNetwork(5),ri_oper.MakeServiceAutoBoot(5),ri_oper.CopyKernel(5),ri_oper.ConfigureBootloader(5),ri_oper.BootLoader(5),ri_oper.ExecFinishInstall(5)] + +def print_usages(): + print 'Usages: %s [-l|--language language] [-d|--display display-mode]' %sys.argv[0] + +try: + opts, args = getopt.getopt(sys.argv[1:], "l:d:", ["language=", "display="]) +except getopt.GetoptError: + print_usages() + sys.exit(1) + +ri_oper.language='english' +disp = 'ri_inst_cli' +for opt,arg in opts: + if opt in ("-l","--language"): + ri_oper.language=arg.lower() + elif opt in ("-d", "--display"): + disp = 'ri_inst_%s' %arg.lower() +exec 'import %s as display' %disp + +ri_oper.display_operation = display.set_task +ri_oper.display_sub_operation = display.set_sub_task +ri_oper.display_scale = display.set_task_scale + +display.start(main) diff --git a/interface/ri_oper.py b/interface/ri_oper.py new file mode 100644 index 0000000..ae202a8 --- /dev/null +++ b/interface/ri_oper.py @@ -0,0 +1,312 @@ +#!/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 os +import subprocess + +if os.path.isfile("../xml/install.xml"): + ri_data.init_from_xml() + +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 + 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 scipt + 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 do not exist',u'设备节点不存在'),\ + 3:('filesystem no implement',u'文件系统没有实现'),\ + } + self.english_name = e + self.chinese_name = c + self.script = s + self.score = scr + self.steps = 1 + self.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, \ + 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.step < self.steps: + self.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 get_arguments(self): + return [] + def get_stdin(self): + return '' + +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] = ('format partition utils not found', u'没有格式化硬盘功能') + + def get_stdin(self): + format='' + n = 0 + for instance in ri_data.MountPoint.list: + if instance.format == "yes" and instance.filesystem != '': + format+="/dev/%s %s\n"%(instance.device,instance.filesystem) + n += 1 + self.steps += n + return format + +class MakeRaid(Operation): + """class for make raid""" + flag=False + def __init__(self,scr): + Operation.__init__(self,"make RAID",u"正在制作RAID磁盘阵列","mkraid_wrapper.sh",scr) + def get_stdin(self): + args = '' + n = 0 + for instance in ri_data.Raid.list: + if instance.from_os == 'no': + MakeRaid.flag=True + args += '-n /dev/%s -l %s -s %s -a %s\n' %(instance.device, instance.level, \ + ','.join([ '/dev/%s' %sp for sp in instance.spare_components]), \ + ','.join([ '/dev/%s' %ac for ac in instance.active_components])) + n += 1 + self.steps += n + return args + +class MakeRaidConfigure(Operation): + """class for make raid configure""" + def __init__(self,scr): + Operation.__init__(self,"make raid configure file",u"配置raid配置文件","mkraidconf.sh",scr) + def install(self): + if MakeRaid.flag: + 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""" + def __init__(self,scr): + Operation.__init__(self,'mount partition',u'挂载分区','mount_partition.sh',scr) + self.return_value[1]=("device node doesn't exist",u"设备结点不存在") + self.return_value[32]=("mount failure",u"挂载失败") + + def get_stdin(self): + mount='' + n = 0 + for instance in ri_data.MountPoint.list: + if instance.directory != '' and instance.filesystem !='': + mount+="/dev/%s %s %s\n"%(instance.device,instance.directory,instance.filesystem) + 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]=("source directory pkg_source_dir doesn't exist",u"软件包所在目录不存在") + self.return_value[3]=("package in source doesn't exist",u"软件包不存在") + + def get_stdin(self): + pkgname=[] + for i in ri_data.Group.dict.values(): + if i.install=='no': + continue + else: + pkgname+=i.mandatory + if i.selection=='all': + pkgname += [ j[0] for j in i.optional ] + else: + pkgname += [ j[0] for j in i.optional if j[1] == 'yes' ] + + self.steps += len(pkgname) + return '\n'.join(pkgname) + + def get_arguments(self): + return ["-s","/Rocky/packages"] + +class ConfigureFstab(Mount): + """class for configure /etc/fstab""" + def __init__(self,scr): + Operation.__init__(self,'configure fstab',u'配置/etc/fstab文件','configure_fstab.sh',scr) + self.return_value[1]=("fstab doesn't exist",u"/etc/fstab文件不存在") + +class GenerateIssue(Operation): + """class for generate /etc/issue""" + def __init__(self,scr): + Operation.__init__(self,'generate 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[0][5:]]+["-a"]+[list[1]]+["-r"]+[list[2]]+['-d']+['-'.join(list[3:])] + 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 or netmask or geteway address incorrect",u"ip或子网掩码或网关不正确") + self.return_value[3]=("hosts/resolv.conf/ifcfg-eth0/network doesn't exist",u"文件hosts、resolv.conf、ifcfg-eht0、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 is not '': + 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 kernle",u"拷贝内核","copy_kernels.sh",scr) + self.return_value[1]=("kernel directory/modules directory/initrd.gz/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",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 doesn't specify",u"没有指定引导程序的类型") + self.return_value[3]=("bootloader no implement",u"没有执行bootloader") + self.return_value[127]=("bootloader utils not found",u"没发现bootloader的utils") + + def get_arguments(self): + # only grub? + return ["-t grub"] + +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 doesn't specify",u"没有指定引导程序的类型") + self.return_value[3]=("bootloader configure file doesn't exist",u"引导程序配置文件不存在") + self.return_value[4]=("bootloader configuration file doesn't exist",u"引导程序配置文件不存在") + + def get_arguments(self): + bootloader=[] + # FIXME if tag file format is error? + if os.path.isfile("/tag"): + fd = open("/tag","r") + string = fd.read() + list = string.split('-') + for instance in ri_data.MountPoint.list: + if instance.directory == '/': + # only grub? + bootloader=['-t','grub','-r',instance.device,'-k',ri_data.SerialNumber.value,'-o',list[0][5:].split('.')[0]+'.'+list[0][5:].split('.')[1]] + break + return bootloader diff --git a/interface/ri_tk.py b/interface/ri_tk.py index ed449f8..773213b 100644 --- a/interface/ri_tk.py +++ b/interface/ri_tk.py @@ -103,7 +103,7 @@ def create_widget_sub(w, p_win): # process action init if 'action' in dir(w) and 'init' in w.action.dict: - getattr(sys.modules['ri_cmd'], w.action.dict['init'])() + getattr(sys.modules['ri_cmd'], w.action.dict['init'])(w_win) # handle scroll bar for sub_widgets if 'action' in dir(w): @@ -162,7 +162,8 @@ def create_message_box(w): ''' display MessageBox w - MessageBox instance''' disp = getattr(tkMessageBox, w.tp) - disp(translate_text(w.title), translate_text(w.message)) + code = disp(translate_text(w.title), translate_text(w.message)) + return code def create_top_window(w): ''' display TopWindow diff --git a/interface/ri_tk_cmd.py b/interface/ri_tk_cmd.py index affa4c4..40aae63 100644 --- a/interface/ri_tk_cmd.py +++ b/interface/ri_tk_cmd.py @@ -9,13 +9,13 @@ import re import copy import sys -def serial_no_init(): +def serial_no_init(w=''): display.var_dict['serial_no.number'].set(value=ri_data.SerialNumber.value) def serial_no_quit(): ri_data.SerialNumber.value = display.var_dict['serial_no.number'].get() -def mount_list_init(): +def mount_list_init(w=''): ''' initialize mount list ''' ri_data.MountPoint.init_from_internal() l = [] @@ -33,7 +33,7 @@ def mount_list_modify(*args): tw = ri_widget.TopWindow.dict['mount_list_modify'] tw.show() -def mp_top_init(): +def mp_top_init(w=''): ''' mount dir top window initialize ''' ml_win = ri_widget.Widget.dict['mount.list'].tk_widget idxs = ml_win.curselection() @@ -90,7 +90,7 @@ def mp_top_cancel(): ri_widget.TopWindow.dict['mount_list_modify'].hide() pass -def network_init(): +def network_init(w=''): ''' network initialize ''' display.var_dict['network_host_name']. set(value=ri_data.Network.hostname) ri_widget.Widget.dict['network_config_%s' %(ri_data.Network.configuration and ri_data.Network.configuration or 'static')].tk_widget.invoke() @@ -146,7 +146,7 @@ class GroupCheck(GroupButton): if v.get() == 'yes': display.SoftwarePackageWindow.dict[self.name].show() -def software_group_mandatory_construct(w): +def software_group_mandatory_construct(w=''): ''' construct widgets based actual data w - Widget instance ''' mdt = [ m for m in ri_data.Group.dict.values() if m.install == 'mandatory' ] @@ -163,7 +163,7 @@ w - Widget instance ''' wi.attr['command'] = vn w.add_sub_widget(wi) -def software_group_optional_construct(w): +def software_group_optional_construct(w=''): ''' construct widgets based actual data w - Widget instance ''' opt = [ o for o in ri_data.Group.dict.values() if o.install != 'mandatory' ] @@ -191,7 +191,7 @@ def software_group_optional_quit(): i.install = display.var_dict[vn].get() print i.name, i.install -def dependency_list_init(): +def dependency_list_init(w=''): ''' init function for list in dependency step ''' ri_dep.construct_depending() ri_dep.resolve_recursive_depending() @@ -200,7 +200,7 @@ def dependency_list_init(): l = [ k.ljust(20) + ': ' + ' '.join(dep_dict[k]) for k in dep_dict.keys()] display.var_dict['dependency.list'].set(value=tuple(l)) -def service_construct(w): +def service_construct(w=''): ''' construct service widget based on actual data w - Widget instance ''' @@ -220,7 +220,7 @@ w - Widget instance ''' wi.grid_location.dict['row'] = idx / int(w.grid_management.columns) w.add_sub_widget(wi) -def service_init(): +def service_init(w=''): ''' initialize service checkboxes, based on package selection ''' # first refresh service state ri_data.Service.change_state() @@ -238,7 +238,7 @@ def service_quit(): vn = "service_%s" %(i.name) i.start = display.var_dict[vn].get() -def raid_raw_init(): +def raid_raw_init(w=''): ''' initialize raid raw devices (parttion with id 'fd' ''' global raid_raw_initialized if not raid_raw_initialized: @@ -250,7 +250,7 @@ def raid_raw_init(): dev_in_raid.update(r.spare_components) raw_devs = [ p.device for p in ri_data.Partition.list - if p.id == 'fd' and p.device not in dev_in_raid ] + if p.flags=='yes' and p.device not in dev_in_raid ] display.var_dict['raid_raw_devs'].set(value=tuple(raw_devs)) def list_to_list(list_from, var_from, var_to): @@ -263,8 +263,11 @@ def list_to_list(list_from, var_from, var_to): itm = l_fr[idx] del l_fr[idx] display.var_dict[var_from].set(value=tuple(l_fr)) - l_to = list(eval(display.var_dict[var_to].get())) - l_to.append(itm) + if display.var_dict[var_to].get(): + l_to = list(eval(display.var_dict[var_to].get())) + l_to.append(itm) + else: + l_to = [ itm ] display.var_dict[var_to].set(value=tuple(l_to)) def raid_raw_to_active(): @@ -283,7 +286,7 @@ def raid_spare_to_raw(): ''' move device from spare to raw ''' list_to_list('raid_spare.list', 'raid_spare_devs', 'raid_raw_devs') -def raid_device_init(): +def raid_device_init(w=''): ''' initialize raid device list ''' raid_devs = [ r.device for r in ri_data.Raid.list ] display.var_dict['raid_devs'].set(value=tuple(raid_devs)) @@ -356,3 +359,9 @@ def raid_device_list_detail(*args): display.var_dict['raid_detail_level'].set(value='level: %s' %(str(r.level))) raid_raw_initialized = False + +def install_information_init(w=''): + '''install information initialize''' + ins_info = ri_data.install_information() + w.insert(1.0,ins_info) + diff --git a/interface/ri_widget.py b/interface/ri_widget.py index fd2d87c..674f869 100644 --- a/interface/ri_widget.py +++ b/interface/ri_widget.py @@ -106,7 +106,8 @@ class MessageBox: def show(self): ''' display dialog''' - display.create_message_box(self) + code = display.create_message_box(self) + return code class TopWindow: ''' implement top_window in interface.xml - top_window corresponds to Toplevel in Tkinter ''' diff --git a/operation/configure_bootloader_cnf.sh b/operation/configure_bootloader_cnf.sh new file mode 100755 index 0000000..57de7e5 --- /dev/null +++ b/operation/configure_bootloader_cnf.sh @@ -0,0 +1,218 @@ +#!/bin/bash +# +# DESCRIPTION: configure configuration file of bootloader +# +# SCRIPT NAME: configure_bootloader_cnf.sh +# +# Input: +# argument: +# [-r|--root] partition mount by root +# <-b|--boot> partition mount by boot (optional,if the boot is not mount by stand alone) +# [-k|--kparameter] kernel parameter +# [-o|--osversion] OS version +# +# Output: +# NULL +# Return value: +# 1 argument error +# 2 bootloader type doesn't specify +# 3 bootloader no implement +# 4 bootloader configuration file doesn't exist +# +# +# AUTHOR: Qin Bo +# +# EMAIL: bqin@linx-info.com +# +# DATE: 2010-09-07 +# +# HISTORY: +# REVISOR DATE MODIFICATION +# Qin Bo 2010-09-07 create +# +# +# + +source ./functions + +usage () +{ + if [ "$1" == "-n" ];then + cmd="info" + ret=0 + else + cmd="err" + ret=1 + fi + $cmd " +This script will install boot loader for system + +Usage: $0 options + +options: + [--help] show this message + [-t|--type ] boot loader type:grub,etc. + [-r|--root] partition mount by root + <-b|--boot> partition mount by boot (optional,if the boot is not mount by stand alone) + [-k|--kparameter] kernel parameter + [-o|--osversion] OS version + " + return $ret +} + +configure_grub_cnf () +{ + + local root_hd + local part_num + local root + local hd_dev + local devname + local root_dev + + if [ ! -e "$GRUBCNF" ];then + err "$GRUBCNF doesn't exist" + return 4 + fi + + # get the boot directory in which hard disk + if [ -n "$BOOT_PARTITION" ];then + root_hd=$(echo "$BOOT_PARTITION"|sed 's/[0-9]//g') + part_num=${BOOT_PARTITION##*[a-z]} + let $((part_num-=1)) + else + root_hd=$(echo "$ROOT_PARTITION"|sed 's/[0-9]//g') + part_num=${ROOT_PARTITION##*[a-z]} + let $((part_num-=1)) + fi + + if [ ! -e "$DEVICEMAP" ];then + warn "$DEVICEMAP doesn't exist, creat it" +# generate device.map +grub --batch --no-floppy --device-map="$DEVICEMAP" << EOF 1>>"$DEV_LOG" 2>&1 +quit +EOF + fi + + hd_dev=$(grep "$root_hd" "$DEVICEMAP" | awk '{print $1}' | sed 's/(//' | sed 's/)//') #e.g. hd_dev=hd0 + info "hd_dev: $hd_dev part_num: $part_num" + root="($hd_dev,$part_num)" + info "root: $root" + + # use UUID in menu.lst except md, + # because when I use UUID of raid device in menu.lst, + # initrd can't switch root . + devname=$(basename $ROOT_PARTITION) + if [[ "$devname" =~ ^md[0-9]*$ ]];then + root_dev="$ROOT_PARTITION" + else + by_uuid=$(get_disk_sym $devname "by-uuid") + if [ -n "$by_uuid" ];then + root_dev="UUID=$(echo $by_uuid|sed 's/.*\///')" + else + root_dev="$ROOT_PARTITION" + fi + fi + info "root_dev: $root_dev" + + # modify grub.conf.sample from here + # modify root + sed "/^splashimage / s/(hd0,0)/$root/ + /^kernel / s/(hd0,0)/$root/" "$GRUBCNF" >"$GRUBMENU" + + # modify boot directory + # boot directory mount stand alone + if [ -n "$BOOT_PARTITION" ];then + sed -i "/^kernel / s@/boot@@ + /^initrd / s@/boot@@" "$GRUBMENU" + fi + + # modify OS version + sed -i "/^title / s/Secure System/Secure Operating System Version $OSVERSION/" "$GRUBMENU" + # modify root partition + sed -i "/^kernel / s@root=/dev/hda1@root=$root_dev@" "$GRUBMENU" + # append kernel parameter + sed -i "s/^kernel .*$/& $KPARAMETER/g" $GRUBMENU +} + +main () +{ + if [ $# -eq 0 ];then + usage; erv + fi + + tmp=$(getopt -o t:r:b:k:o: --long type:,root:,boot:,kparameter:,osversion:,help -- "$@" 2>>$DEV_LOG) + if [ $? -ne 0 ];then + usage; erv + fi + + # set all argument to arg variable + eval set -- "$tmp" + + while true ;do + case "$1" in + -t|--type) TYPE="$2" + info "bootloader type: $TYPE" + shift 2 + ;; + -r|--root) ROOT_PARTITION="$2" + info "root partition: $ROOT_PARTITION" + shift 2 + ;; + -b|--boot) BOOT_PARTITION="$2" + info "boot partition: $BOOT_PARTITION" + shift 2 + ;; + -k|--kparameter) KPARAMETER="$2" + info "kernel parameter: $KPARAMETER" + shift 2 + ;; + -o|--osversion) OSVERSION="$2" + info "version of opterating system: $OSVERSION" + shift 2 + ;; + --help) usage -n; exit 0 ;; + # shift the last "--", this dash is define by getopt (more information see man getopt) + --) shift; break;; + *) usage; erv ;; + esac + done + + if [ -n "$TYPE" ];then + case "$TYPE" in + grub) + if [ -z "$ROOT_PARTITION" ]; then + err "configure grub configuration file root partition can't be empty" + exit 1 + fi + configure_grub_cnf + erv + ;; + *) + err "$TYPE bootloader no implement yet !" + exit 3 + ;; + esac + else + err "bootloader type doesn't specify" + exit 2 + fi + +} + + +TYPE="" +ROOT_PARTITION="" +BOOT_PARTITION="" +KPARAMETER="" +OSVERSION="" +GRUB_DIR="$TARGET/boot/grub" +GRUBMENU="$GRUB_DIR/menu.lst" +GRUBCNF="$GRUB_DIR/grub.conf.sample" +DEVICEMAP="$GRUB_DIR/device.map" + +# The quotes around '$@' are essential! +# in this way we can accept whitespace as parameter. +main "$@" + + diff --git a/operation/configure_fstab.sh b/operation/configure_fstab.sh index f762a6a..051ba79 100755 --- a/operation/configure_fstab.sh +++ b/operation/configure_fstab.sh @@ -3,6 +3,8 @@ # DESCRIPTION: configure fstab # this script will modify $TARGT/etc/fstab, # append the mountpoint to $TARGET/etc/fstab. +# mountpoint, swap use by-id, other device use by-uuid. +# if can't get by-id or by-uuid use device name. # # SCRIPT NAME: configure_fstab.sh # @@ -19,9 +21,9 @@ # 6. fs_passno # # Output: +# NULL +# Returne value: # 1 fstab doesn't exist -# 2 lack input (reserve) -# 3 device node doesn't exist # # AUTHOR: Qin Bo # @@ -38,32 +40,39 @@ source ./functions -# -# if you redirect to /etc/fstab, don't print redundant to stdout in this function -# configure_fstab () { - local devname="$1" + local device="$1" local mountpoint="$2" local fs_type="$3" - local fs_mntops="$4" local fs_freq="$5" local fs_passno="$6" + # store uuid of by-id + local devname="" - if [ ! -e "$devname" ];then - err "$devname node doesn't exist !" - return 3 - fi - # if partition is not swap, md, /, we use uuid instead device node - # / and swap partition use device node is decide by mkinitrd, this - # fstab will use by mkinitrd first ,if use UUID in fstab, mkinitrd will dead loop. - if [ "$mountpoint" != "/" -a "$(echo $devname | grep md)" = "" -a "$fs_type" != "swap" ];then - DEV_UUID=$(vol_id "$devname" | grep "ID_FS_UUID=" | cut -d "=" -f2) - devname="UUID=$DEV_UUID" + # in Rocky4.2 udev-117: udevinfo couldn't get by-id of raid, + # also couldn't get by-uuid of swap, raid and swap can't unification , + # so get device's uuid expect swap, only get device's by-id for swap. + # if partition not exist, or couldn't get partition information + # set $devname as default + + partition=$(echo $device|sed 's/.*\///') + if [ "$mountpoint" == "swap" -a "$fs_type" == "swap" ];then + by_id=$(get_disk_sym $partition "by-id") + if [ -n "$by_id" ];then + devname="/dev/$by_id" + else + devname="$device" + fi else - devname="$devname" + by_uuid=$(get_disk_sym $partition "by-uuid") + if [ -n "$by_uuid" ];then + devname="UUID=$(echo $by_uuid|sed 's/.*\///')" + else + devname="$device" + fi fi # configure fstab options here @@ -85,29 +94,34 @@ configure_fstab () [ -z "$fs_passno" ] && fs_passno=1 ;; esac - printf "%-60s %-10s %-10s %-25s %-1s %-1s\n" $devname $mountpoint $fs_type $fs_mntops $fs_freq $fs_passno + info "$devname $mountpoint $fs_type $fs_mntops $fs_freq $fs_passno" + printf "%-60s %-10s %-10s %-25s %-1s %-1s\n" $devname $mountpoint $fs_type $fs_mntops $fs_freq $fs_passno >>"$TARGET/etc/fstab" } main () { + local line + if [ -e "$TARGET/etc/fstab" ];then sed -i '/^#devpts/ s/#// /^#sysfs/ s/#// /^#shm/ s/#shm /tmpfs/ ' "$TARGET/etc/fstab" + info "configure fstab" while read line;do if [ -n "$line" ];then - configure_fstab $line >> "$TARGET/etc/fstab" + configure_fstab $line erv fi done + info "configure fstab success" else err "$TARGET/etc/fstab doesn't exist" exit 1 fi } -main $@ +main "$@" diff --git a/operation/configure_network.sh b/operation/configure_network.sh index 11c8885..54dd372 100755 --- a/operation/configure_network.sh +++ b/operation/configure_network.sh @@ -6,23 +6,26 @@ # # Input: argument # [--help] show usage -# [-t|--type] \"manual\" or \"dynamic\" -# manual argument: +# [-t|--type] "static" or "dynamic" +# static argument: # [-h|--hostname] hostname -# [-d|--domainname] domainname # [-i|--ip] ip address # [-n|--netmask] netmask # [-g|--gateway] gateway -# [-p|--pdns] priamaryDNS -# [-s|--sdns] secondaryDNS +# <-d|--domainname> domainname +# <-p|--pdns> priamaryDNS +# <-s|--sdns> secondaryDNS # <-e|--device> network device. if no configure, default is eth0. # dynamic argument: # [-h|--hostname] hostname # <-e|--device> network device. if no configure, default is eth0. # # Output: +# NULL +# Return value: # 1 argument error # 2 ip/netmask/gateway address incorrect +# 3 hosts/resolv.conf/ifcfg-eth0/network doesn't exist # # AUTHOR: Qin Bo # @@ -56,15 +59,15 @@ Usage: $0 options: options: [--help] show this message - [-t|--type] \"manual\" or \"dynamic\" - manual argument: + [-t|--type] \"static\" or \"dynamic\" + static argument: [-h|--hostname] hostname - [-d|--domainname] domainname [-i|--ip] ip address [-n|--netmask] netmask [-g|--gateway] gateway - [-p|--pdns] priamaryDNS - [-s|--sdns] secondaryDNS + <-d|--domainname> domainname + <-p|--pdns> priamaryDNS + <-s|--sdns> secondaryDNS <-e|--device> network device. if no configure, default is eth0. dynamic argument: [-h|--hostname] hostname @@ -88,24 +91,29 @@ check_ip () if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then # IFS is a separator for read builtin command, we save old IFS - OIFS=$IFS - IFS='.' + OIFS=$IFS + IFS='.' # set $ip to ip array - ip=($ip) + ip=($ip) # restore IFS - IFS=$OIFS - [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ - && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] - ret=$? - fi + IFS=$OIFS + [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ + && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] + ret=$? + fi - return $ret + return $ret } parse_arg () { - tmp=$(getopt -o t:h:d:i:n:g:p:s:e:? --long type:,hostname:,ip:,netmask:,gateway:,pdns:,sdns:,device:,help -- "$@" 2>$dev_LOG) + if [ $# -eq 0 ];then + usage + return 1 + fi + + tmp=$(getopt -o t:h:d:i:n:g:p:s:e:? --long type:,hostname:,domainname:,ip:,netmask:,gateway:,pdns:,sdns:,device:,help -- "$@" 2>>$DEV_LOG) if [ $? -ne 0 ];then usage return 1 @@ -116,23 +124,23 @@ parse_arg () while true ; do case $1 in - -t|--type) type="$2" ; - info "network configure type: $type" ; + -t|--type) TYPE="$2" ; + info "network configure type: $TYPE" ; shift 2;; - -h|--hostname) hostname="$2"; - info "hostname: $hostname" ; + -h|--hostname) HOSTNAME="$2"; + info "hostname: $HOSTNAME" ; shift 2 ;; - -d|--domainname) domainname="$2"; - info "domainname: $domainname" ; + -d|--domainname) DOMAINNAME="$2"; + info "domainname: $DOMAINNAME" ; shift 2 ;; - -i|--ip) ip="$2"; - info "ip: $ip" ; + -i|--ip) IP="$2"; + info "ip: $IP" ; shift 2 ;; - -n|--netmask) netmask="$2"; - info "netmask: $netmask" ; + -n|--netmask) NETMASK="$2"; + info "netmask: $NETMASK" ; shift 2 ;; - -g|--gateway) gateway="$2"; - info "gateway: $gateway" ; + -g|--gateway) GATEWAY="$2"; + info "gateway: $GATEWAY" ; shift 2 ;; -p|--pdns) primaryDNS="$2"; info "primaryDNS: $primaryDNS" ; @@ -141,8 +149,8 @@ parse_arg () info "secondaryDNS: $secondaryDNS" ; shift 2 ;; # may be have mulit-network devices - -e|--device) device="$2"; - info "device: $device" ; + -e|--device) DEVICE="$2"; + info "device: $DEVICE" ; shift 2 ;; # shift the last "--", this dash is define by getopt (more information see man getopt) --) shift ;break;; @@ -151,47 +159,54 @@ parse_arg () esac done - - if [ "$type" != "manual" -a "$type" != "dynamic" ];then - usage + if [ "$TYPE" != "static" -a "$TYPE" != "dynamic" ];then + err "configure network must be static or dynamic" return 1 fi - if [ -z "$hostname" ];then - err "you must specify hostname" + if [ -z "$HOSTNAME" ];then + err "HOSTNAME can't be empty" return 1 fi # default device is eth0 - if [ -z "$device" ];then - device="eth0" + if [ -z "$DEVICE" ];then + DEVICE="eth0" fi - if [ "$type" == "manual" ];then - if [ -z "$ip" ];then - err "manual configure network, IP address can't be empty" + if [ "$TYPE" == "static" ];then + if [ -z "$DOMAINNAME" ];then + err "static configure network, DOMAINNAME can't be empty" + return 1 + fi + + if [ -z "$IP" ];then + err "static configure network, IP address can't be empty" return 1 else - info "checking ip: $ip" - if ! check_ip "$ip"; then + info "checking ip: $IP" + if ! check_ip "$IP"; then + err "ip: $IP incorrect" return 2 fi fi - if [ -z "$netmask" ];then - err "manual configure network, netmask address can't be empty" + if [ -z "$NETMASK" ];then + err "static configure network, netmask address can't be empty" return 1 else - info "checking netmask: $netmask" - if ! check_ip "$netmask"; then + info "checking netmask: $NETMASK" + if ! check_ip "$NETMASK"; then + err "netmask: $NETMASK incorrect" return 2 fi fi - if [ -z "$gateway" ];then - err "manual configure network, gateway address can't be empty" + if [ -z "$GATEWAY" ];then + err "static configure network, gateway address can't be empty" return 1 else - info "checking gateway: $gateway" - if ! check_ip "$gateway"; then + info "checking gateway: $GATEWAY" + if ! check_ip "$GATEWAY"; then + err "gateway: $GATEWAY incorrect" return 2 fi fi @@ -201,55 +216,111 @@ parse_arg () configure_network () { - if [ "$type" == "manual" ];then + if [ "$TYPE" == "static" ];then # configure /etc/hosts - printf "%s %s.%s %s\n" $ip $hostname $domainname $hostname >>"$TARGET/etc/hosts" + if [ -e "$TARGET/etc/hosts" ];then + sed -i "s/^#/$IP/ + s//$HOSTNAME\.$DOMAINNAME/ + s//$HOSTNAME/" "$TARGET/etc/hosts" + else + err "$TARGET/etc/hosts doesn't exist" + return 3 + fi # configure /etc/resolv.conf - printf "search %s\n" $domainname >>"$TARGET/etc/resolv.conf" - if [ -n "$primaryDNS" ];then - printf "nameserver %s\n" $primaryDNS >>"$TARGET/etc/resolv.conf" + if [ -e "$TARGET/etc/resolv.conf" ];then + sed -i "s/^#search $/search $DOMAINNAME/ + s/^#domain $/domain $DOMAINNAME/" "$TARGET/etc/resolv.conf" + if [ -n "$primaryDNS" ];then + sed -i "s/^#nameserver $/nameserver $primaryDNS/" "$TARGET/etc/resolv.conf" + fi + if [ -n "$secondaryDNS" ];then + sed -i "/nameserver/a\nameserver $secondaryDNS" "$TARGET/etc/resolv.conf" + fi + else + err "$TARGET/etc/resolv.conf doesn't exist" + return 3 fi - if [ -n "$secondaryDNS" ];then - printf "nameserver %s\n" $secondaryDNS >> "$TARGET/etc/resolv.conf" - fi - printf "domainname %s\n" $domainname >> "$TARGET/etc/resolv.conf" # configure /etc/sysconfig/network-devices/ifcfg-eth0 - broadcast=$(./ipcalc.pl -n $ip/$netmask| grep Broadcast|awk '{ print $2 }') - sed -i '/IPADDR/ c\IPADDR='$ip' - /NETMASK/ c\NETMASK='$netmask' - /DEVICE/ c\DEVICE='$device' - /GATEWAY/ c\GATEWAY='$gateway' - /BROADCAST/ c\BROADCAST='$broadcast'' "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0" + if [ -e "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0" ];then + broadcast=$(./ipcalc.pl -n $IP/$NETMASK| grep Broadcast|awk '{ print $2 }') + sed -i '/IPADDR/ c\IPADDR='$IP' + /NETMASK/ c\NETMASK='$NETMASK' + /DEVICE/ c\DEVICE='$DEVICE' + /GATEWAY/ c\GATEWAY='$GATEWAY' + /BROADCAST/ c\BROADCAST='$broadcast'' "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0" + else + err "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0 doesn't exist" + return 3 + fi - sed -i '/HOSTNAME/ c\HOSTNAME='$hostname'' "$TARGET/etc/sysconfig/network" - - else [ "$type" == "dynamic" ] - printf "%s\n" $hostname >> "$TARGET/etc/hosts" + # configure /etc/sysconfig/network + if [ -e "$TARGET/etc/sysconfig/network" ];then + sed -i '/HOSTNAME/ c\HOSTNAME='$HOSTNAME'' "$TARGET/etc/sysconfig/network" + printf "DOMAIN=%s\n" "$DOMAINNAME" >>"$TARGET/etc/sysconfig/network" + else + err "$TARGET/etc/sysconfig/network doesn't exist" + return 3 + fi + else [ "$TYPE" == "dynamic" ] + # configure /etc/hosts + if [ -e "$TARGET/etc/hosts" ];then + printf "%s\n" $HOSTNAME >> "$TARGET/etc/hosts" + else + err "$TARGET/etc/hosts doesn't exist" + return 3 + fi - sed -i '/BOOTPROTO/ c\BOOTPROTO=dhcp - /DEVICE/ c\DEVICE='$device' - /SERVICE/ c\SERVICE=dhcpcd - /IPADDR/ c\IPADDR= - /NETMASK/ c\NETMASK= - /GATEWAY/ c\GATEWAY= - /BROADCAST/ c\BROADCAST=' "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0" + # configure /etc/sysconfig/network-devices/ifcfg-eth0 + if [ -e "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0" ];then + sed -i '/BOOTPROTO/ c\BOOTPROTO=dhcp + /DEVICE/ c\DEVICE='$DEVICE' + /SERVICE/ c\SERVICE=dhcpcd + /IPADDR/ c\IPADDR= + /NETMASK/ c\NETMASK= + /GATEWAY/ c\GATEWAY= + /BROADCAST/ c\BROADCAST=' "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0" + else + err "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0 doesn't exist" + return 3 + fi - sed -i '/HOSTNAME/ c\HOSTNAME='$hostname'' "$TARGET/etc/sysconfig/network" + # configure /etc/sysconfig/network + if [ -e "$TARGET/etc/sysconfig/network" ];then + sed -i '/HOSTNAME/ c\HOSTNAME='$HOSTNAME'' "$TARGET/etc/sysconfig/network" + else + err "$TARGET/etc/sysconfig/network doesn't exist" + return 3 + fi fi - if [ "$device" != "eth0" ];then - mv "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0" "$TARGET/etc/sysconfig/network-devices/ifcfg-$device" + if [ "$DEVICE" != "eth0" ];then + mv "$TARGET/etc/sysconfig/network-devices/ifcfg-eth0" "$TARGET/etc/sysconfig/network-devices/ifcfg-$DEVICE" fi } main () { - parse_arg $@ + info "configure network" + parse_arg "$@" erv configure_network + erv + info "configure network success" } -main $* +TYPE="" +HOSTNAME="" +DOMAINNAME="" +IP="" +NETMASK="" +GATEWAY="" +primaryDNS="" +secondaryDNS="" +DEVICE="" + +# The quotes around '$@' are essential! +# in this way we can accept whitespace as parameter. +main "$@" diff --git a/operation/copy_kernels.sh b/operation/copy_kernels.sh index af5e53a..dcda936 100755 --- a/operation/copy_kernels.sh +++ b/operation/copy_kernels.sh @@ -9,8 +9,9 @@ # 2. # # Output: -# 1 -# 2 +# NULL +# Return value: +# 1 kernel directory/modules directory/initrd.gz/makeinitrd doesn't exist # # AUTHOR: Qin Bo # @@ -29,11 +30,42 @@ source ./functions main () { - cp -r /Rocky/kernels/* $TARGET/boot/ 2>$dev_LOG - cp -r /Rocky/modules/* $TARGET/lib/modules/ 2>$dev_LOG - cp /Rocky/initrd/initrd.gz $TARGET/boot/initrd.gz.old 2>$dev_LOG + info "copy $KERNELS/* to $TARGET/boot/" + if [ -d "$KERNELS" ];then + cp -r "$KERNELS"/* "$TARGET/boot/" 2>>$DEV_LOG + else + err "$KERNELS directory doesn't exist " + exit 1 + fi - ./makeinitrd + info "copy $MODULES/* to $TARGET/lib/modules/" + if [ -d "$MODULES" ];then + cp -r "$MODULES"/* "$TARGET/lib/modules/" 2>>$DEV_LOG + else + err "$MODULES directory doesn't exist " + exit 1 + fi + + info "copy $INITRD/initrd.gz to $TARGET/boot/initrd.gz.old" + if [ -e "$INITRD/initrd.gz" ];then + cp "$INITRD/initrd.gz" "$TARGET/boot/initrd.gz.old" 2>>$DEV_LOG + else + err "$INITRD/initrd.gz doesn't exist " + exit 1 + fi + + info "runing makeinitrd" + if [ -e ./makeinitrd ];then + ./makeinitrd 2>>$DEV_LOG + else + err "makeinitrd doesn't exist " + exit 1 + fi } -main $@ +KERNELS="/Rocky/kernels" +MODULES="/Rocky/modules" +INITRD="/Rocky/initrd" + +main "$@" + diff --git a/operation/exec_finish_install.sh b/operation/exec_finish_install.sh index 3de0c39..6e1b951 100755 --- a/operation/exec_finish_install.sh +++ b/operation/exec_finish_install.sh @@ -11,8 +11,9 @@ # 1. script name which need run after installation # # Output: -# 1 -# 2 +# NULL +# Return value: +# dependency return value of execute script, if 0 is success. # # AUTHOR: Qin Bo # @@ -31,8 +32,10 @@ source ./functions prep () { - if [ ! -d $finish_install_dir ];then - mkdir -p $finish_install_dir + local mp + + if [ ! -d $FINISH_INSTALL_DIR ];then + mkdir -p $FINISH_INSTALL_DIR fi for mp in /dev /proc /sys @@ -41,23 +44,31 @@ prep () done } +# copy the script to $TARGET/opt, and chroot execute it exec_script () { + local src + local src_name + src="$1" src_name=$(basename $src) cp $src "$TARGET/opt" - chroot $TARGET "/opt/$src_name" >$dev_LOG 2>&1 && rm -f "$TARGET/opt/$src_name" + chroot $TARGET "/opt/$src_name" >>$DEV_LOG 2>&1 && rm -f "$TARGET/opt/$src_name" } main () { + local line + local base + local script + prep while read line ;do if [ -n "$line" ];then - cp $line $finish_install_dir/ + cp $line $FINISH_INSTALL_DIR/ else break fi @@ -65,7 +76,7 @@ main () # run all the script in /var/finish_install, # execute sequence through number of script name - for script in "$finish_install_dir"/*; do + for script in "$FINISH_INSTALL_DIR"/*; do base=$(basename $script | sed 's/[0-9]*//') if [ -x "$script" ];then info "Running $base" @@ -75,9 +86,12 @@ main () warn "Unable to execute $script" fi done + info "Running finish install success" + [ ! -c "$LOG_FILE" ] && cp $LOG_FILE "$TARGET/var/log" + [ ! -c "$DEV_LOG" ] && cp $DEV_LOG "$TARGET/var/log" } -finish_install_dir="/var/finish_install" +FINISH_INSTALL_DIR="/var/finish_install" -main $@ +main "$@" diff --git a/operation/format_partition.sh b/operation/format_partition.sh index c4fcaff..99253a8 100755 --- a/operation/format_partition.sh +++ b/operation/format_partition.sh @@ -1,7 +1,7 @@ #!/bin/bash # # DESCRIPTION: formating partition with a filesystem -# NOTICE: if have duplicate partition, it will format the final filesystem type. +# if have duplicate partition, it will format the finally filesystem type. # # SCRIPT NAME: format_partition.sh # @@ -10,14 +10,14 @@ # Input: stdin # 1. partition # 2. filesystem type -# 1,2 separate with space # # Output: -# 0 success +# success: +# @ format $devname success +# Return value: # 1 argument error -# 2 lack input (reserve) -# 3 deivce node doesn't exist -# 4 filesystem no implement +# 2 deivce node doesn't exist +# 3 filesystem no implement # 127 format partition utils not found # # AUTHOR: Qin Bo @@ -43,64 +43,68 @@ format_partition () return 1 fi - devname="$1" - fs_type="$2" + local devname="$1" + local fs_type="$2" if [ ! -e "$devname" ];then err "$devname node doesn't exist !" - return 3 + return 2 fi # partition may be used to swap, or has already mounted if grep -q "^$devname " /proc/swaps ;then swapoff "$devname" elif grep -q "^$devname " /proc/mounts;then - reumount $devname >"$dev_LOG" 2>&1 + reumount $devname 1>>"$DEV_LOG" 2>&1 fi info "formating device "$devname" as "$fs_type" filesystem" case ${fs_type} in ext2) - mkfs.ext2 -F "$devname" 1>"$dev_LOG" 2>&1 + mkfs.ext2 -F "$devname" 1>>"$DEV_LOG" 2>&1 ;; ext3) - mkfs.ext3 -F "$devname" 1>"$dev_LOG" 2>&1 + mkfs.ext3 -F "$devname" 1>>"$DEV_LOG" 2>&1 ;; reiserfs) - yes | mkfs.reiserfs -f "$devname" 1>"$dev_LOG" 2>&1 + yes | mkfs.reiserfs -f "$devname" 1>>"$DEV_LOG" 2>&1 ;; xfs) - yes | mkfs.xfs -f "$devname" 1>"$dev_LOG" 2>&1 + yes | mkfs.xfs -f "$devname" 1>>"$DEV_LOG" 2>&1 ;; jfs) - yes | mkfs.jfs -q "$devname" 1>"$dev_LOG" 2>&1 + yes | mkfs.jfs -q "$devname" 1>>"$DEV_LOG" 2>&1 ;; swap) - mkswap -f "$devname" 1>"$dev_LOG" 2>&1 + mkswap -f "$devname" 1>>"$DEV_LOG" 2>&1 swapon "$devname" ;; fat) - mkfs.vfat "$devname" 1>"$dev_LOG" 2>&1 + mkfs.vfat "$devname" 1>>"$DEV_LOG" 2>&1 ;; *) err ""$fs_type" filesystem no implement yet !" - return 4 + return 3 ;; esac } main () { + local line + while read line;do if [ -n "$line" ];then # Notice: don't use "$line" format_partition $line erv + info "format $(echo $line|awk '{print $1}') success" stdout + fi done } -main $@ +main "$@" # vim:set ts=4 sw=4; diff --git a/operation/functions b/operation/functions index 7751b54..f008532 100644 --- a/operation/functions +++ b/operation/functions @@ -1,37 +1,59 @@ -LOG_FILE="/var/log/install.log" -dev_LOG="/dev/tty6" -TARGET="/mnt" -TMP_DIR="/tmp" +# LOG_FILE, LOG, DEV_LOG, TARGET is global variable, +# they can export from environment variable, +# if not definition, will configure default value. -# just for debug, also can use in run time -LOG="stdout" -#PKG_SOURCE_DIR="/Rocky/packages" +# installation log file +[ -z "$LOG_FILE" ] && LOG_FILE="/var/log/install.log" + +# LOG have two value, true and stdout +# true: log will record to $LOG_FILE +# stdout: log will print to stand out, very usefull for debug +[ -z "$LOG" ] && LOG="true" + +# the log of command operation +# ex: stdout of command: mkfs.ext3 /dev/hda2 +[ -z "$DEV_LOG" ] && DEV_LOG="/dev/tty8" + +# the root directory of hardisk mount +[ -z "$TARGET" ] && TARGET="/mnt" -DATE=$(date "+%Y/%m/%d %T") +mkdir -p $(dirname $LOG_FILE) +mkdir -p $(dirname $DEV_LOG) +mkdir -p "$TARGET" + +stdout () +{ + printf "$*\n" +} log () { + local DATE=$(date "+%Y/%m/%d %T") + case "$LOG" in true) printf "$DATE $*\n" >>"$LOG_FILE" ;; - stdout) printf "$DATE $*\n" ;; + stdout) stdout "$DATE $*" ;; *) : ;; esac } err () { - log "error: $0: $*" >&2 + log "error: $(basename $0): $*" >&2 } warn () { - log "warning: $0: $*" >&2 + log "warning: $(basename $0): $*" >&2 } info () { - log "info: $0: $*" + log "info: $(basename $0): $1" + if [ "$2" == "stdout" ];then + stdout "@ $1" + fi } # erv stands for "Evaluate Return Value" @@ -43,86 +65,10 @@ erv () fi } -cleanup () -{ - rm -f $* -} - -# -# check mountpoint whether is duplicate -# -check_duplicate_mountpoint () -{ - if [ -s "$MOUNTPOINT_CONF" ];then - dup=$(awk '{print $2}' "$MOUNTPOINT_CONF" | sort | uniq -d) - - if [ -n "$dup" ];then - err "mountpoint: \""$(echo $dup|tr " " "," )"\" is duplicate !" - return 4 - fi - return 0 - else - err "$MOUNTPOINT_CONF file is empty or doesn't exist !" - return 8 - fi -} - -# -# check partition whether is duplicate -# -check_duplicate_partition () -{ - if [ -s "$MOUNTPOINT_CONF" ];then - dup=$(awk '{print $1}' "$MOUNTPOINT_CONF" | sort | uniq -d) - - if [ -n "$dup" ];then - err "partition: \""$(echo $dup|tr " " "," )"\" is duplicate !" - return 5 - fi - return 0 - else - err "$MOUNTPOINT_CONF file is empty or doesn't exist !" - return 8 - fi -} - -# -# check root whether will mounted -# -check_root () -{ - if [ -s "$MOUNTPOINT_CONF" ];then - if ! grep -q "[[:space:]]/[[:space:]]" $MOUNTPOINT_CONF;then - err "\"/\" partition can not be empty!" - return 6 - fi - return 0 - else - err "$MOUNTPOINT_CONF file is empty or doesn't exist !" - return 8 - fi -} - -# -# check /boot partition whether exist, if root partition is mounted by raid device -# -check_boot () -{ - if [ -s "$MOUNTPOINT_CONF" ];then - if grep " / " $MOUNTPOINT_CONF|grep -q "md" && ! grep -q " /boot " $MOUNTPOINT_CONF; then - err "boot parition mustn't mount alone, when root partition mount at raid devices !" - return 7 - fi - return 0 - else - err "$MOUNTPOINT_CONF file is empty or doesn't exist !" - return 8 - fi -} - - -# recursively umount -# arg can is a device node or mountpoint +# recursively umount directory, +# argument can be a device node or mountpoint. +# if argument is a device node can umount a device which mounted multi-directory, +# if argument is a mountpoint can't umount a device recursively, only recursively directory. # ex: 1.reumount /dev/hda5 # 2.reumount /mnt/ reumount () @@ -132,16 +78,70 @@ reumount () return 1 fi - local arg="$1" + local arg + arg="$1" local mountpoint # if arg is a device node if [ ! -d "$arg" ];then - mountpoint=$(dirname `grep "^$arg " /proc/mounts|awk '{print $2}'`) + mountpoint=$(grep "^$arg " /proc/mounts|awk '{print $2}') else mountpoint="$arg" fi - for mp in $(grep "$mountpoint" /proc/mounts|sort -k2 -r |awk '{print $2}');do - umount $mp 1>"$dev_LOG" 2>&1 + + # delete last "/" in mountpoint + # mountpoint in /proc/mounts don't have "/" at last + multi_mountpoint=$(echo $mountpoint|sed "s%/$%%") + + # may be a device has been mounted in multi-mountpoint. + # ex: /dev/hda5 mount at /mnt and /cdrom at the same time, + # this case appear when $TARGET has been changed, when mount paritions. + for mmp in $multi_mountpoint; do + # sort -k2 -r ensure long mountpoint sort at front of short mountpoint, + # so, we can umount long mountpoint before short mountpoint. + # ex: /usr/lib, /, /usr, after sort is /usr/lib, /usr, / + # this mean that /usr/lib is umounted first, then umount /usr, finally umount / + for mp in $(grep "$mmp" /proc/mounts|sort -k2 -r |awk '{print $2}');do + umount $mp 1>>"$DEV_LOG" 2>&1 + done done } + +update_udev() +{ + killall udevd + start_udev +} + +# +# get device uuid/by-id/by-path info +# if not found return NULL +# ex: get_disk_sym sda1 by-uuid +# +get_disk_sym () +{ + if [ $# -ne 2 ];then + err "$FUNCNAME function argument error, it must be 2 !" + return 1 + fi + + local partition="$1" + local type="$2" + local devname="" + + # we find partition in /sys/block/, + # "*" in oder to c0d0p1 match cciss!c0d0p1 + local path=$(find /sys/block/ -maxdepth 2 -name *$partition) + + # scsci's by-id may be have multi-links, we get first link + if [ -n "$path" -a -d "$path" ];then + # update hard disk informations. + # if not update udev, uuid or by-id may use old one. + update_udev + devname=$(udevinfo -q symlink -p $path|tr " " "\n"|grep "$type"|head -n 1) + fi + echo "$devname" + +} + + diff --git a/operation/generate_issue.sh b/operation/generate_issue.sh index b31aa3a..9ffe403 100755 --- a/operation/generate_issue.sh +++ b/operation/generate_issue.sh @@ -5,10 +5,11 @@ # SCRIPT NAME: generate_issue.sh # # Input: argument -# 1.version -# 2.arch -# 3.release -# 4.date +# [--help] show this message +# [-v|--version] version of OS +# [-a|--arch] architecture of OS +# [-r|--release] release of OS +# [-d|--date] date of generate OS # # Output: # 1 argument error @@ -44,10 +45,10 @@ Usage: $0 options options: [--help] show this message - [-v | --version] version of OS - [-a | --arch] architecture of OS - [-r | --release] release of OS - [-d | --date] date of generate OS + [-v|--version] version of OS + [-a|--arch] architecture of OS + [-r|--release] release of OS + [-d|--date] date of generate OS " return $ret @@ -69,8 +70,13 @@ generate_issue () { main() { + local tmp + + if [ $# -eq 0 ];then + usage;erv + fi - tmp=$(getopt -o v:a:r:d: --long version:,arch:,release:,date:,help -- "$@" 2>$dev_LOG) + tmp=$(getopt -o v:a:r:d: --long version:,arch:,release:,date:,help -- "$@" 2>>$DEV_LOG) if [ "$?" -ne 0 ];then usage erv @@ -92,15 +98,13 @@ main() esac done - if [ -z "$version" -a -z "$arch" -a -z "$release" -a -z "$date" ];then - usage - erv - fi - + info "generate issue" generate_issue "$version" "$arch" "$release" "$date" >"$TARGET/etc/issue" + erv + info "generate issue sucess" } -main $@ +main "$@" diff --git a/operation/install.txt b/operation/install.txt new file mode 100644 index 0000000..39bd09f --- /dev/null +++ b/operation/install.txt @@ -0,0 +1,226 @@ +1.格式化分区: +swap,linux(ext3、ext2、jfs、xfs、reiserfs),fat +format_partition.sh +输入: + stdin + 1)partition:分区 + 2)filesystem:文件系统类型 +输出: + success: + @ format $devname success +返回值: + 1 argument error + 2 deivce node doesn't exist + 3 filesystem no implement + 127 format partition utils not found +Usage: +单个处理: echo "/dev/sda1 ext2" | ./format_partition.sh +批量处理:文件格式和单个处理一致 +说明:需要处理swap分区。 + +2.挂载分区 +mount_partition.sh +输入: + stdin + 1)partition:块设备 + 2)mountpoint:挂载点 + 3)filesystem:文件系统类型 + 4)filsystem options:文件系统选项 + (这个为可选参数,不传这个参数会有默认的选项:文件系统是ext2|ext3|reiserfs,会以acl的选项挂载,其他则为defaults) +输出: + success: + @ mount $devname success +返回值: + 1 device node doesn't exist + 32 mount failure +Usage: +单个处理:echo "/dev/sda1 / ext3" |./mount_partition.sh +批量处理:文件格式和单个处理一致 +说明:不处理swap分区。 + +3.安装软件包:install_pkg.sh +输入: + stdin + 1. pkgname + argument: + [--help] show usage + <-s|--source> package source directory, if not specify, default is /Rocky/packages. +输出: sucess: + @ install $pkgname success. +返回值: + 1 argument error + 2 source directory $PKG_SOURCE_DIR doesn't exist + 3 pkgname doesn't exist in source directory + +Usage: +单个处理:echo "acl" |./install_pkg.sh -s /Rocky/packages +批量处理:文件格式和单个处理一致 +说明: + 1.由安装程序生成/var/lib/pkg/db的空文件; + 2.默认用/Rocky/packages下面的软件包,如果不指定-s参数。 + +4.配置、生成系统文件: + +配置fstab,configure_fstab.sh +输入: + stdin + 1)block devices:块设备,(swap则用by-id,其他都用by-uuid) + 2)mount point:挂载点 + 3)filesystem type:文件系统类型 + 以下参数为可选参数,如果不指定,会有默认的配置,如果指定5)那么4)也需要指定,依次类推 + 4)fs_mntops: ext2|ext3|reiserfs的默认配置是acl,其他都是defaults。 + 5)fs_freq:默认配置:swap是0,其他都是1 + 6)fs_passno:默认配置:swap是0,其他都是1 +输出: + 无 +返回值: + 1 fstab doesn't exist +Usage: +单个处理:echo "/dev/hda2 /home ext3"|./configure_fstab.sh +批量处理:文件格式和单个处理一致 +说明: + 1.需要处理swap; + 2.块设备:如果是swap则转成by-id,其他都转成by-uuid, +这个是因为udev-117的udevinfo不能查出查出raid的by-id,也不能查出swap的uuid。 + +生成issue文件 +generate_issue.sh +输入: + argument: + [--help] show usage + [-v|--version] version of OS + [-a|--arch] architecture of OS + [-r|--release] release of OS(base or security) + [-d|--date] date of generate OS +输出: + 无 +返回值: + 1 argument error +说明: + 1.生成$TARGET/etc/issue文件,一般TARGET=/mnt; + 2.可以只给一个参数,但是这样其他参数则为空值。 + +配置网络: +configure_network.sh +输入: + argument: + [-t|--type] "static" or "dynamic" + static argument: + [-h|--hostname] hostname + + [-i|--ip] ip address + [-n|--netmask] netmask + [-g|--gateway] gateway + <-d|--domainname> domainname + <-p|--pdns> priamaryDNS + <-s|--sdns> secondaryDNS + <-e|--device> network device. if no configure, default is eth0. + dynamic argument: + [-h|--hostname] hostname + <-e|--device> network device. if no configure, default is eth0. +输出: + 无 +返回值: + 1 argument error + 2 ip/netmask/gateway address incorrect + 3 hosts/resolv.conf/ifcfg-eth0/network doesn't exist +Usage: +./configure_network.sh -t static -h QinBo -d in.linx -i 192.168.1.110 -n 255.255.255.0 -g 192.168.1.254 -p 172.16.0.254 +说明: + 1.type必须为static或者dynamic; + 2.不管哪种type,hostname是必须的; + 3.type=static的时候IP、域名、子网掩码、网关是必须的; + 4.device:多网卡的时候,可以指定用哪个网卡,默认用的是eth0。 + +做自启服务: +mk_serv_autoboot.sh +输入: + stdin + 1)package name:软件包名字(自启动服务所在软件包) + 2)boot script:启动脚本 + 3)boot service:需要启动的服务 + 4)boot number:启动号 +输出: + 无 +返回值: + 1:argument error + 2:boot script doesn't exist +Usage: +单个处理:echo "netkit-base inetd rsh S310"|./mk_serv_autoboot.sh +批量处理:文件格式和单个处理一致 +说明: + 默认在/etc/rc.d/{rc3.d,rc5.d}建立链接。 + +5.拷贝kernel、modules和生成initrd +copy_kernels.sh +输入: + 无 +输出: + 无 +返回值: + 1 kernel directory/modules directory/initrd.gz/makeinitrd doesn't exist +说明: + 1.此脚本从 /Rocky/kernels和/Rocky/modules目录下拷贝kernel和modules, + 2.把/Rocky/initrd/initrd.gz,拷贝到硬盘上的/boot/initrd.gz.old, + 3.生成initrd调用原来的makeinitrd脚本生成。 + +6.生成bootloader对应的配置文件,安装bootloader +configure_bootloader_cnf.sh +配置bootloader配置文件 +输入: + arguments: + [--help] show this message + [-t|--type ] boot loader type:grub,etc. + [-r|--root] partition mount by root + <-b|--boot> partition mount by boot (optional,if the boot is not mount by stand alone) + [-k|--kparameter] kernel parameter + [-o|--osversion] OS version +输出: + 无 +返回值: + 1 argument error + 2 bootloader type doesn't specify + 3 bootloader no implement + 4 bootloader configuration file doesn't exist +说明: + grub:对grub软件包里面的grub.conf.sample($TARGET/boot/grub/)进行相应的修改, + 产生新的文件:$TARGET/boot/grub/menu.lst + +install_bootloader.sh +安装bootloader +输入: + arguments: + [--help] show this message + [-t|--type] boot loader type:grub,etc. +输出: + 无 +返回值: + 1 argument error + 2 bootloader type doesn't specify + 3 bootloader no implement + 127 bootloader utils not found +说明: + 此脚本把grub装在第一块硬盘上面,因为bios默认会从第一块硬盘启动, +这样bios就能找到我们的装上去的gurb,从而正确引导系统。 + + + +7.安装完成执行的脚本 +exec_finish_install.sh +输入: + stdin + 1)脚本的名字 +输出: + 无 +返回值: + 根据具体执行脚本的返回值来确定,0是成功 +Usage: +单个处理:echo "99finish_install.sh"| ./exec_finish_install.sh +批量处理:文件格式和单个处理一致 +说明: + 此脚本把99finish_install.sh拷贝到/var/finish_install目录下, +然后根据/var/finish_install目录下面的脚本名字前面的数字顺序,从小 +到大依次拷贝到硬盘系统里面执行。 + +99finish_install.sh +原来的firstboot.sh diff --git a/operation/install_bootloader.sh b/operation/install_bootloader.sh new file mode 100755 index 0000000..1e771aa --- /dev/null +++ b/operation/install_bootloader.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# +# DESCRIPTION: install bootloader for OS +# +# SCRIPT NAME: install_bootloader.sh +# +# Input: +# [--help] show this message +# [-t|--type] boot loader type:grub,etc. +# Output: +# NULL +# Return value: +# 1 argument error +# 2 bootloader type doesn't specify +# 3 bootloader no implement +# 127 bootloader utils not found +# +# AUTHOR: Qin Bo +# +# EMAIL: bqin@linx-info.com +# +# DATE: 2010-09-02 +# +# HISTORY: +# REVISOR DATE MODIFICATION +# Qin Bo 2010-09-02 create +# +# +# + +source ./functions + +usage () +{ + if [ "$1" == "-n" ];then + cmd="info" + ret=0 + else + cmd="err" + ret=1 + fi + $cmd " +This script will install boot loader for system + +Usage: $0 options + +options: + [--help] show this message + [-t|--type] boot loader type:grub, etc. + + " + return $ret +} + +install_grub () +{ + +# generate device.map +grub --batch --no-floppy --device-map="$DEVICEMAP" << EOF 1>>"$DEV_LOG" 2>&1 +quit +EOF + # in order to let bios to load grub correct, + # we install grub to first hard disk by default, + # so even though OS install in secondary hard disk, + # the OS still can be loaded from first hard disk. + + f_hd=$(grep "(hd0)" "$DEVICEMAP"|awk '{print $NF}') + + grub-install --no-floppy --root-directory=$TARGET $f_hd 1>>$DEV_LOG 2>&1 +} + +main () +{ + if [ $# -eq 0 ];then + usage; erv + fi + + tmp=$(getopt -o t: --long type:,help -- "$@" 2>>$DEV_LOG) + if [ $? -ne 0 ];then + usage; erv + fi + + # set all argument to arg variable + eval set -- "$tmp" + + while true ;do + case "$1" in + -t|--type) + type="$2" + shift 2 + ;; + --help) usage -n; exit 0 ;; + # shift the last "--", this dash is define by getopt (more information see man getopt) + --) shift; break;; + *) usage; erv ;; + esac + done + + if [ -n "$type" ];then + case "$type" in + grub) + install_grub + erv + ;; + *) + err "$type bootloader no implement yet !" + exit 3 + ;; + esac + else + err "bootloader type doesn't specify" + exit 2 + fi +} + +GRUB_DIR="$TARGET/boot/grub" +DEVICEMAP="$GRUB_DIR/device.map" + +main "$@" + + diff --git a/operation/install_pkg.sh b/operation/install_pkg.sh index 516b8c2..06cd776 100755 --- a/operation/install_pkg.sh +++ b/operation/install_pkg.sh @@ -1,6 +1,7 @@ #!/bin/bash # -# DESCRIPTION: install package +# DESCRIPTION: install package, if -s options not given, +# get package from /Rocky/packages by default. # # SCRIPT NAME: install_pkg.sh # @@ -10,16 +11,20 @@ # 1. pkgname # argument: # [--help] show usage -# [-s|--source] Package source directory +# <-s|--source> package source directory, if not specify, default is /Rocky/packages. # # Output: +# sucess: +# @ install $pkgname success. +# Return value: # 1 argument error -# 2 pkgname doesn't exist in source directory +# 2 source directory $PKG_SOURCE_DIR doesn't exist +# 3 pkgname doesn't exist in source directory # # TODO: # 1. need handle more case for install package (use pkgadd utils) # 1). if package has already installed. -# 2). if devices near no spaces left. +# 2). if devices nearly no spaces left. # # 2. add install package from below media: # 1). install from network. @@ -61,8 +66,8 @@ This script will install a package Usage: $0 options options: - [--help] Show this message - [-s | --source] Package source directory + [--help] show this message + <-s|--source> package source directory, if not specify, default is /Rocky/packages. (ex: echo make|install_pkg.sh -s /Rocky/packages) " @@ -79,11 +84,12 @@ get_pkg_file () local pkg_name="$1" + # get the first package if have multi-package in source directory if [ -e "$PKG_SOURCE_DIR"/"$pkgname"'#'*tar.gz ]; then ls "$PKG_SOURCE_DIR"/"$pkgname"'#'*tar.gz|head -n 1 else err "package \"$pkgname\" doesn't exist in "$PKG_SOURCE_DIR" " - return 2 + return 3 fi } @@ -95,7 +101,8 @@ add_pkg () fi local pkg_src=$1 - pkgadd -f -r $TARGET $pkg_src 1>$dev_LOG 2>&1 + + pkgadd -f -r $TARGET $pkg_src 1>>$DEV_LOG 2>&1 } install_pkg () @@ -105,7 +112,12 @@ install_pkg () return 1 fi - local pkgname="$1" + local pkgname + local db_dir + local db + local pkg_src + + pkgname="$1" # create db for pkgutils db_dir="/var/lib/pkg" @@ -117,20 +129,23 @@ install_pkg () touch "$db" fi - local pkg_src=$(get_pkg_file $pkgname) + pkg_src=$(get_pkg_file $pkgname) erv - info "install $pkgname to $TARGET" + info "installing $pkg_src to $TARGET" add_pkg $pkg_src erv } main () { - tmp=$(getopt -o s: --long source:,help -- "$@" 2>$dev_LOG) + local line + local tmp + local pkgname + + tmp=$(getopt -o s: --long source:,help -- "$@" 2>>$DEV_LOG) if [ $? -ne 0 ];then - usage - erv + usage; erv fi # set all argument to arg variable @@ -149,12 +164,9 @@ main () esac done - if [ -z "$PKG_SOURCE_DIR" ];then - usage - erv - elif [ ! -e "$PKG_SOURCE_DIR" ];then - err "$PKG_SOURCE_DIR doen't exist !" - exit 1 + if [ ! -e "$PKG_SOURCE_DIR" ];then + err "source directory: $PKG_SOURCE_DIR doen't exist !" + exit 2 fi while read line ;do @@ -164,12 +176,13 @@ main () if [ -n "$pkgname" ];then install_pkg "$pkgname" erv + info "install $pkgname success" stdout fi done } -PKG_SOURCE_DIR="" +PKG_SOURCE_DIR="/Rocky/packages" main "$@" diff --git a/operation/makeinitrd b/operation/makeinitrd index 39aeca5..a6ae753 100755 --- a/operation/makeinitrd +++ b/operation/makeinitrd @@ -1,4 +1,7 @@ #!/bin/bash +source ./functions + modules=$(ls /Rocky/modules/|grep -v .bak|grep -v .old) -mkinitrd /mnt/boot/initrd.gz $modules --without-usb --without-multipath --fstab=/mnt/etc/fstab -f +mkTmpfstab.sh -f "$TARGET/etc/fstab" -t "/tmp/fstab" +mkinitrd "$TARGET"/boot/initrd.gz $modules --without-usb --without-multipath --fstab="/tmp/fstab" -f diff --git a/operation/mk_serv_autoboot.sh b/operation/mk_serv_autoboot.sh index 4dd588f..db48946 100755 --- a/operation/mk_serv_autoboot.sh +++ b/operation/mk_serv_autoboot.sh @@ -1,9 +1,9 @@ - #!/bin/bash # -# DESCRIPTION: this script use for start system autoboot services. -# have to make a sysmbol link to script of autotboot services, -# and generate $pkgname-serv.conf, this configure file use by post_add. +# DESCRIPTION: this script use for system autoboot services. +# function: +# 1.make a sysmbol link to script of autotboot services, +# 2.generate $pkgname-serv.conf, this configure file use by post_add. # # Usage: echo "netkit-base inetd rsh S310"|./mk_serv_autoboot.sh # @@ -16,6 +16,8 @@ # 4. boot number # # Output: +# NULL +# Return value: # 1 argument error # 2 boot script doesn't exist # @@ -45,9 +47,9 @@ make_sysmbol_link () local script="$1" local number="$2" - for dir in $rc_dir; do - pushd $dir >$dev_LOG && - if [ -e $init_dir/$script ];then + for dir in $RC_DIR; do + pushd $dir >>$DEV_LOG && + if [ -e $INIT_DIR/$script ];then if [ -L "$dir/$number$script" ];then # may be the symbol link has already exist, skip it, # mulit-services, may have common script to boot it. @@ -57,10 +59,10 @@ make_sysmbol_link () ln -sf ../init.d/$script ./$number$script fi else - err "$script doesn't exist in $init_dir" + err "$script doesn't exist in $INIT_DIR" return 2 fi - popd >$dev_LOG + popd >>$DEV_LOG done } @@ -76,17 +78,18 @@ gen_serv_cnf () local pkgname="$1" local service="$2" - # may be some boot services needn't configure also generate pkgname-serv.conf - # ex: at service, if it need autoboot, it also generate at-serv.conf, - # although it needn't configure - if [ -e "$serv_cfg_dir/$pkgname-serv.conf" ];then + # may be some boot services needn't configure, + # it also generate pkgname-serv.conf. + # ex: at service, if it need autoboot, + # it also generate at-serv.conf, although it needn't configure. + if [ -e "$SERV_CFG_DIR/$pkgname-serv.conf" ];then # to avoid duplicate-line in $pkgname-serv.conf, we only append it when $service=yes # not exist in $pkgname-serv.conf - if [ -z "$(grep "$service=yes" "$serv_cfg_dir/$pkgname-serv.conf")" ];then - printf "%s=yes\n" $service >> "$serv_cfg_dir"/"$pkgname-serv.conf" + if [ -z "$(grep "$service=yes" "$SERV_CFG_DIR/$pkgname-serv.conf")" ];then + printf "%s=yes\n" $service >> "$SERV_CFG_DIR"/"$pkgname-serv.conf" fi else - printf "%s=yes\n" $service > "$serv_cfg_dir"/"$pkgname-serv.conf" + printf "%s=yes\n" $service > "$SERV_CFG_DIR"/"$pkgname-serv.conf" fi } @@ -109,21 +112,25 @@ mk_serv_autoboot () main () { + local line + + info "configure auto boot service" while read line;do if [ -n "$line" ];then mk_serv_autoboot $line erv fi done + info "configure auto boot service success" } -rcd="$TARGET/etc/rc.d" -init_dir="$rcd/init.d" +RCD="$TARGET/etc/rc.d" +INIT_DIR="$RCD/init.d" # according old Rocky installer, make symbol link in rc3.d and rc5.d -rc_dir="$rcd/rc3.d $rcd/rc5.d" -serv_cfg_dir="$TARGET/var/lib/pkg" +RC_DIR="$RCD/rc3.d $RCD/rc5.d" +SERV_CFG_DIR="$TARGET/var/lib/pkg" -main $@ +main "$@" diff --git a/operation/mkraid_wrapper.sh b/operation/mkraid_wrapper.sh new file mode 100755 index 0000000..3c55faa --- /dev/null +++ b/operation/mkraid_wrapper.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# DESCRIPTION: better deal with arguments for mkraid.sh (arguments---> stdin) +# +# SCRIPT NAME: mkraid_wrapper.sh +# +# MENTOR: Li Zhi +# +# AUTHOR: Ling Fen +# +# EMAIL: fling@linx-info.com +# +# DATE: 2010-09-20 +# +# HISTORY: +# REVISOR DATE MODIFICATION +# Ling Fen 2010-09-18 create +# + +# This file is a wrapper to mkraid.sh. + +while read line +do + $(dirname $0)/mkraid.sh "$line" + ret=$? + if [ $ret -ne 0 ];then + exit $ret + fi +done diff --git a/operation/mount_partition.sh b/operation/mount_partition.sh index 40e8689..6f25469 100755 --- a/operation/mount_partition.sh +++ b/operation/mount_partition.sh @@ -12,12 +12,13 @@ # 1. partition # 2. mountpoint # 3. filesystem type -# below input is optional, if not set, we mount default configure, +# below input is optional, if not set, we mount default configure # 4. fs_mntops: set mount options # Output: -# 1 argument error -# 2 lack input (reserve) -# 3 device node doesn't exist +# success: +# @ mount $devname success +# Return value: +# 1 device node doesn't exist # 32 mount failure # # AUTHOR: Qin Bo @@ -37,25 +38,21 @@ source ./functions mount_partition () { + local devname="$1" local mountpoint="$2" local fs_type="$3" local fs_mntops="$4" + local mount_pos="$TARGET$mountpoint" if [ ! -e "$devname" ];then err "$devname node doesn't exist !" - return 3 + return 1 fi - if [ "$mountpoint" == "/" ];then - mount_pos="$TARGET" - else - mount_pos="$TARGET$mountpoint" - fi - - # mount filesystem for default option - # after install will set acl, so we use acl option mount here - # this configure according old Rocky installer + # mount filesystem for default option, + # after installation will set acl, so we use acl option mount here. + # this configuration according old Rocky installer. case $fs_type in ext2|ext3|reiserfs) [ -z "$fs_mntops" ] && fs_mntops="acl" ;; @@ -68,18 +65,31 @@ mount_partition () mkdir -p "$mount_pos" fi + # device node has already mounted on other directory, umount it. + # ex: /dev/hda5 should mount on /mnt, but it has already mounted on /cdrom before, + # so, we umount it + if [ "$(grep "$devname" /proc/mounts|awk '{print $2}')" != "$mount_pos" ];then + reumount $devname + fi + # mountpoint has already mounted, umount it if mountpoint -q $mount_pos;then # may be have mountpoint under the mountpoint directory reumount $mount_pos fi - info "mount $devname on $mount_pos with $fs_type filesystem" - mount -t "$fs_type" -o $fs_mntops "$devname" "$mount_pos" 1>"$dev_LOG" 2>&1 + info "mounting $devname on $mount_pos with $fs_type filesystem" + mount -t "$fs_type" -o $fs_mntops "$devname" "$mount_pos" 1>>"$DEV_LOG" 2>&1 } main() { + local line + + # sort -k 2 ensure let short mountpoint sort at front of long mountpoint, + # in this way, we can mount long mountpoint after short mountpoint. + # ex: /usr/lib, /usr, /, after sort is /, /usr, /usr/lib + # this mean that / is mounted first, then mount /usr, finally mount /usr/lib while read line; do echo $line done|sort -k 2 -u| @@ -87,10 +97,12 @@ main() if [ -n "$line" ];then mount_partition $line erv + info "mount $(echo $line|awk '{print $1}') success" stdout fi done } + main "$@" diff --git a/xml/install_ng.xml b/xml/install_ng.xml index 8b6a5fd..dd26ab0 100644 --- a/xml/install_ng.xml +++ b/xml/install_ng.xml @@ -26,15 +26,23 @@ + + + msdos + gpt + + - + + + diff --git a/xml/interface.xml b/xml/interface.xml index b03dbdf..76835ea 100644 --- a/xml/interface.xml +++ b/xml/interface.xml @@ -722,7 +722,7 @@ row 4 | | - + @@ -815,21 +815,50 @@ row 4 | | - - Copyright 2001-2010 Linx Technology Co., Ltd. - 北京凝思科技有限公司 版权所有 - + + + + + + + + + + + + + + + + + + + + + + + + + You have already been in the first step. 您已到达第一步。 - - You have already been in the last step. - 您已到达最后一步。 - - Network Configuration Management: 网络配置方式 @@ -851,12 +880,15 @@ row 4 | | - Welcome to use -Linx Rocky Secure Operating System v4.2 - 欢迎使用 -凝思磐石安全操作系统 v4.2 + Welcome to useLinx Rocky Secure Operating System v4.2 + 欢迎使用凝思磐石安全操作系统 v4.2 - + + + installation Configuration is completed, press the OK button to start the installation + 安装配置完成,按确定键开始安装 + + Active 活动 @@ -1071,5 +1103,6 @@ Linx Rocky Secure Operating System v4.2 +