system-config-kickstart源码阅读(四)引导程序grub篇

按照此系列文章的
《二》
中的“功能篇”,安从上到下,或是理解为按照首字母顺序来一一解析。
顾名思义,bootloader.py即是linux系统引导程序,现在lilo基本消失了,grbu独占此领域。对于安装程序anaconda来说,解析、处理kickstart生成的文件中,此项绝对重要,一个系统若是安装了却不能引导,那其实等于什么也没有做。
先来看下其类的UML视图:

此文要比我们以前所见到的类要好多,而且还将继承关系体现了出来,这就是OOP,既然GRUB不是全部,那就定义个类似的,其他的任何来了继承就解决了。抽象不能解决问题,尽管它可以提供一些思考的方向。
import gtk
import gtk.glade
import string
import random
import crypt
#模块就不用解释了,均在上几篇文章解释过的。
##
## I18N
##
import gettext
gtk.glade.bindtextdomain("system-config-kickstart")
_ = lambda x: gettext.ldgettext("system-config-kickstart", x)
import kickstartGui
class AbstractBootloader:     //高级类定义,具体的grub来继承这个类。
    def __init__(self, xml, notebook, ksHandler):
        self.xml = xml
        self.notebook = notebook
        self.ks = ksHandler
    def applyKickstart(self):
        pass
    def enableUpgrade(self, boolean):
        pass
    def formToKickstart(self):
        return 0
    def hide(self):
        pass
    def show(self, platform):
        pass
    def toggled_bootloader(self, args):
        pass
class GrubBootloader(AbstractBootloader):  //继承了!
    def __init__(self, xml, notebook, ksHandler):
        AbstractBootloader.__init__(self, xml, notebook, ksHandler)
        self.bootloader_vbox = xml.get_widget("bootloader_vbox")
        self.bootloader_label = xml.get_widget("bootloader_label")
        self.install_bootloader_radio = xml.get_widget("install_bootloader_radio")
        self.upgrade_bootloader_radio = xml.get_widget("upgrade_bootloader_radio")
        self.no_bootloader_radio = xml.get_widget("no_bootloader_radio")
        self.mbr_radiobutton = xml.get_widget("mbr_radiobutton")
        self.firstsector_radiobutton = xml.get_widget("firstsector_radiobutton")
        self.parameters_label = xml.get_widget("parameters_label")
        self.parameters_entry = xml.get_widget("parameters_entry")
        self.linear_checkbutton = xml.get_widget("linear_checkbutton")
        self.lba32_checkbutton = xml.get_widget("lba32_checkbutton")
        self.grub_options_label = xml.get_widget("grub_options_label")
        self.grub_password_checkbutton = xml.get_widget("grub_password_checkbutton")
        self.grub_password_hbox = xml.get_widget("grub_password_hbox")
        self.grub_password_entry = xml.get_widget("grub_password_entry")
        self.grub_password_confirm = xml.get_widget("grub_password_confirm")
        self.grub_password_encrypt_checkbutton = xml.get_widget("grub_password_encrypt_checkbutton")
#获取glade文件的widget,这点有点难度了,因为在glade编辑器中难以做到所写即所得。非熟悉gtk+的人是做不来的,也说明了此处技艺的高超。
        self.install_bootloader_radio.connect("toggled", self.toggled_bootloader)//定义触发按钮信号,以及相应的处理函数,下同。
        self.grub_password_checkbutton.connect("toggled", self._toggled_grub_password)
    def _toggled_grub_password(self, args):
        self.grub_password_hbox.set_sensitive(self.grub_password_checkbutton.get_active()) //可选框是否激活?
    def applyKickstart(self):    //每个功能篇中的都有的方法,局部生效。也就是默认选项。
        if self.ks.bootloader.location == "none":  //判断是否选择安装引导程序?如果选择了不安装,则激活不安装按钮。
            self.no_bootloader_radio.set_active(True)
        elif self.ks.bootloader.location == "mbr":  //否则,默认安装到MBR
            self.mbr_radiobutton.set_active(True)
        elif self.ks.bootloader.location == "partition":  //否则,默认安装到分区上
            self.firstsector_radiobutton.set_active(True)
        if self.ks.bootloader.password != "":
            self.grub_password_entry.set_text(self.ks.bootloader.password)
            self.grub_password_confirm.set_text(self.ks.bootloader.password)
        self.parameters_entry.set_text(self.ks.bootloader.appendLine)//内核参数。
        if self.ks.bootloader.md5pass != "": //是否选择给grub密码加密?
            self.grub_password_encrypt_checkbutton.set_active(True)
        else:
            self.grub_password_encrypt_checkbutton.set_active(False)
        if self.ks.bootloader.upgrade == True:  升级现有的引导程序?
            self.upgrade_bootloader_radio.set_active(True)
        else:
            self.upgrade_bootloader_radio.set_active(False)
    def enableUpgrade(self, boolean):   
        self.upgrade_bootloader_radio.set_sensitive(not boolean)
    def formToKickstart(self):  //来自文件的设置
        if self.install_bootloader_radio.get_active():
            buf = ""
            if self.mbr_radiobutton.get_active():
                self.ks.bootloader.location = "mbr"
            elif self.firstsector_radiobutton.get_active():
                self.ks.bootloader.location = "partition"
            params = string.strip (self.parameters_entry.get_text())
            self.ks.bootloader.appendLine = params
//加密很精彩?
            if self.grub_password_checkbutton.get_active() == True:
                gp = string.strip (self.grub_password_entry.get_text())
                cp = string.strip (self.grub_password_confirm.get_text())
                if len(gp) > 0:
                    if gp == cp:
                        if self.grub_password_encrypt_checkbutton.get_active():
                            salt = "$1$"
                            saltLen = 8
                            for i in range(saltLen):
                                salt = salt + random.choice (string.letters + string.digits + './')//此处的东西,我得去寻找anaconda的源码来确认解密的过程。。
                            self.passwd = crypt.crypt (gp, salt)
                            self.ks.bootloader.md5pass = unicode(self.passwd, 'iso-8859-1')
                        else:
                            self.ks.bootloader.password = gp
                            self.ks.bootloader.md5pass = ""
                    else:
                        dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
                                                (_("Grub passwords do not match.  Please try again.")))
                        dlg.set_position(gtk.WIN_POS_CENTER)
                        dlg.set_modal(True)
                        dlg.set_icon(kickstartGui.iconPixbuf)
                        dlg.run()
                        dlg.destroy()
                        self.grub_password_entry.set_text("")
                        self.grub_password_confirm.set_text("")
                        self.notebook.set_current_page(2)
                        self.grub_password_entry.grab_focus()
                        return None
            else:
                self.ks.bootloader.password = ""
                self.ks.bootloader.md5pass = ""
        elif self.upgrade_bootloader_radio.get_active():
            self.ks.bootloader.upgrade = True
        else:
            self.ks.bootloader.location = "none"
            self.ks.bootloader.password = ""
            self.ks.bootloader.md5pass = ""
        return 0
    def hide(self):     
        self.bootloader_vbox.hide()
    def show(self, platform):   更本就不显示设置项。
        self.bootloader_vbox.show()
    def toggled_bootloader (self, args): //触发信号的调用函数。
        status = self.install_bootloader_radio.get_active()
        self.parameters_label.set_sensitive(status)
        self.parameters_entry.set_sensitive(status)
        self.mbr_radiobutton.set_sensitive(status)
        self.firstsector_radiobutton.set_sensitive(status)
        self.grub_options_label.set_sensitive(status)
        self.grub_password_checkbutton.set_sensitive(status)
        self.grub_password_entry.set_sensitive(status)
        self.grub_password_confirm.set_sensitive(status)
        self.grub_password_encrypt_checkbutton.set_sensitive(status)
class UnknownBootloader(AbstractBootloader):
    def __init__(self, xml, notebook, ksHandler):
        AbstractBootloader.__init__(self, xml, notebook, ksHandler)
        self.bootloader_label = xml.get_widget("bootloader_label")
    def hide(self):
        self.bootloader_label.hide()
    def show(self, platform):
        self.bootloader_label.set_text(_("Bootloader options are not applicable to "
                                         "the %s platform" % platform))
        self.bootloader_label.show()
class bootloader:   //供kickstartGui类使用的类。
    def __init__(self, xml, notebook, ksHandler):
        self.default = UnknownBootloader(xml, notebook, ksHandler)
        self.blDict = {"x86, AMD64, or Intel EM64T": GrubBootloader(xml, notebook, ksHandler)}
        self._setBl(ksHandler.platform)
    def _setBl(self, platform):
        try:
            self.bl = self.blDict[platform]
        except:
            self.bl = self.default
    def applyKickstart(self):
        self.bl.applyKickstart()
    def enableUpgrade(self, boolean):
        self.bl.enableUpgrade(not boolean)
    def formToKickstart(self):
        return self.bl.formToKickstart()
    def platformTypeChanged(self, platform):
        self.bl.hide()
        self._setBl(platform)
        self.bl.show(platform)
    def updateKS(self, ksHandler)  //使bootload生效。:
        self.ks = ksHandler
        self.default.ks = ksHandler
        for bl in self.blDict.values():
            bl.ks = ksHandler
此时,我真的迷了!无所适从了,恰如我现在的生活。当去全局考虑,不明白细节;当去探求细节时,忘了全局。
顺序程序设计而已,总是在按照某种规定的方式走的,无论它有多少次if-else,假如不是这样,这个程序就没有任何的意义,一如人生,但人生似乎都把握不住岔路!