system-config-kickstart源码阅读(五)安装方法篇
适兕
|
1#
适兕 发表于 2008-11-07 11:17
system-config-kickstart源码阅读(五)安装方法篇
众所周知,Linux支持n种安装方式,例如光盘,本地硬盘,网络安装如NFS,http或ftp等等,当然全自动的也不能例外,我们先从宏观上来观察其类:
除去每个类里均会有的updateKS()、formToKickstart、applyKickstart()方法之外,实现的方法并不复杂,让我们先分析代码,然后画出流程图,也许就是真的理解了一个程序的局部了,整体把握的能力,不仅是积累的过程,还有自我能力的局限。 代码分析:install.py import gtk import gtk.glade import string //一定会有文本处理,呵呵,你不喜欢吗? import kickstartGui class install: def __init__(self, parent_class, xml, store, view, notebook, ksHandler): self.xml = xml self.parent_class = parent_class self.store = store self.view = view self.notebook = notebook self.ks = ksHandler self.install_radiobutton = xml.get_widget("install_radiobutton") self.upgrade_radiobutton = xml.get_widget("upgrade_radiobutton") self.partitioning_frame = xml.get_widget("partitioning_frame") self.pkg_selection_frame = xml.get_widget("pkg_selection_frame") self.install_option_vbox = xml.get_widget("install_option_vbox") //供安装方式选择的单选框 self.cdrom_radiobutton = xml.get_widget("cdrom_radiobutton") self.nfs_radiobutton = xml.get_widget("nfs_radiobutton") self.ftp_radiobutton = xml.get_widget("ftp_radiobutton") self.http_radiobutton = xml.get_widget("http_radiobutton") self.hd_radiobutton = xml.get_widget("hd_radiobutton") //提示用的标签 self.nfsdir_label = xml.get_widget("nfsdir_label") self.nfsserver_label = xml.get_widget("nfsserver_label") self.ftpdir_label = xml.get_widget("ftpdir_label") self.ftpserver_label = xml.get_widget("ftpserver_label") self.ftpuser_label = xml.get_widget("ftpuser_label") self.ftppasswd_label = xml.get_widget("ftppasswd_label") self.hdpart_label = xml.get_widget("hdpart_label") self.hddir_label = xml.get_widget("hddir_label") self.httpserver_label = xml.get_widget("httpserver_label") self.httpdir_label = xml.get_widget("httpdir_label") //需要用户输入的entry widget. self.nfsdir_entry = xml.get_widget("nfsdir_entry") self.nfsserver_entry = xml.get_widget("nfsserver_entry") self.ftpdir_entry = xml.get_widget("ftpdir_entry") self.ftpserver_entry = xml.get_widget("ftpserver_entry") self.ftpuser_entry = xml.get_widget("ftpuser_entry") self.ftppasswd_entry = xml.get_widget("ftppasswd_entry") self.hdpart_entry = xml.get_widget("hdpart_entry") self.hddir_entry = xml.get_widget("hddir_entry") self.httpserver_entry = xml.get_widget("httpserver_entry") self.httpdir_entry = xml.get_widget("httpdir_entry") self.ftpuserpass_checkbutton = xml.get_widget("ftpuserpass_checkbutton") self.install_notebook = xml.get_widget("install_notebook") //这是个好东东,多个note,仅显示当前 //信号的定义,以及触发信号后的调用事件函数 self.install_radiobutton.connect("toggled", self.toggleInstall) self.cdrom_radiobutton.connect("toggled", self.setState) self.nfs_radiobutton.connect("toggled", self.setState) self.ftp_radiobutton.connect("toggled", self.setState) self.http_radiobutton.connect("toggled", self.setState) self.hd_radiobutton.connect("toggled", self.setState) self.ftpuserpass_checkbutton.connect("toggled", self.toggleFtp) self.ftpuser_entry.set_sensitive(False) 默认为空 self.ftppasswd_entry.set_sensitive(False) def updateKS(self, ksHandler): self.ks = ksHandler def toggleFtp (self, args): //响应ftpuserpass_checkbutton按钮的事件方法 userpass = self.ftpuserpass_checkbutton.get_active() self.ftpuser_entry.set_sensitive(userpass) self.ftppasswd_entry.set_sensitive(userpass) def toggleInstall (self, args)://响应install_radiobutton按钮的事件方法 #gray out package selection and partitions if upgrade install = self.install_radiobutton.get_active() self.parent_class.installTypeChanged(install) def setState (self, args): //方法只能选一种! if self.cdrom_radiobutton.get_active(): self.install_notebook.set_current_page(0) return elif self.nfs_radiobutton.get_active(): self.install_notebook.set_current_page(1) return elif self.ftp_radiobutton.get_active(): self.install_notebook.set_current_page(2) return elif self.http_radiobutton.get_active(): self.install_notebook.set_current_page(3) return elif self.hd_radiobutton.get_active(): self.install_notebook.set_current_page(4) def formToKickstart(self): //好多if else阿, self.ks.upgrade(upgrade=self.upgrade_radiobutton.get_active()) if self.cdrom_radiobutton.get_active(): self.ks.method.method = "cdrom" elif self.nfs_radiobutton.get_active(): server = self.nfsserver_entry.get_text() dir = self.nfsdir_entry.get_text() if server == "": 当将nfs的按钮激活时,在保存或预览时的提示信息。 self.showDialog(_("Please enter an NFS server."), self.nfsserver_entry) return None if dir == "": self.showDialog(_("Please enter an NFS directory."), self.nfsdir_entry) return None if server [-1] == "/": server = server[:-1] self.ks.method.method = "nfs" //写入到文件时的格式,也就时传入ks类的参数 self.ks.method.server = server self.ks.method.dir = dir elif self.ftp_radiobutton.get_active()://当将ftp的按钮激活时,在保存或预览时的提示信息。 ftpserver = string.strip(self.ftpserver_entry.get_text()) if ftpserver == "": self.showDialog(_("Please enter an FTP server."), self.ftpserver_entry) return None if ftpserver[:6] == "ftp://": ftpserver = ftpserver[6:] if ftpserver[-1] == "/": ftpserver = ftpserver[:-1] if self.ftpdir_entry.get_text() == "": self.showDialog(_("Please enter an FTP directory."), self.ftpserver_entry) return None buf = "ftp://" if self.ftpuserpass_checkbutton.get_active(): //必须输入用户名和密码 if self.ftpuser_entry.get_text() == "": self.showDialog(_("Please enter an FTP user name."), self.ftpuser_entry) return None if self.ftppasswd_entry.get_text() == "": self.showDialog(_("Please enter an FTP password."), self.ftpuser_entry) return None buf = buf + self.ftpuser_entry.get_text() + ":" + self.ftppasswd_entry.get_text() + "@" //将用户的输入,联合起来:ftp://用户名:密码@ buf = buf + ftpserver //继续联合:ftp://用户名:密码@服务器 directory = self.ftpdir_entry.get_text() if directory[0] == '/': buf = buf + directory else: buf = buf + "/" + directory //最后形成完整的URL表示法。ftp://用户名:密码@服务器/目录 self.ks.method.method = "url" self.ks.method.url = buf elif self.http_radiobutton.get_active(): if self.httpserver_entry.get_text() == "": self.showDialog(_("Please enter an HTTP server."), self.httpserver_entry) return None if self.httpdir_entry.get_text() == "": self.showDialog(_("Please enter an HTTP server directory."), self.httpdir_entry) return None loc = string.strip(self.httpserver_entry.get_text()) if loc[:7] == "http://": #strip the "http://" out loc = loc[7:] if loc [-1] == "/": loc = loc[:-1] buf = "http://" + loc directory = self.httpdir_entry.get_text() if directory[0] == '/': buf = buf + directory else: buf = buf + "/" + directory self.ks.method.method = "url" self.ks.method.url = buf elif self.hd_radiobutton.get_active(): //硬盘安装 if self.hddir_entry.get_text() == "": self.showDialog(_("Please enter a hard drive directory."), self.hddir_entry) return None if self.hdpart_entry.get_text() == "": self.showDialog(_("Please enter a hard drive partition."), self.hdpart_entry) return None //这就是程序的功能缺失了,并没有检查用户的输入。也不清楚是否支持LVM。 self.ks.method.method = "harddrive" self.ks.method.partition = self.hdpart_entry.get_text() self.ks.method.dir = self.hddir_entry.get_text() return 0 def showDialog(self, text, widget): //显示一对话框。 dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, text) dlg.set_title(_("Error")) dlg.set_default_size(100, 100) dlg.set_position (gtk.WIN_POS_CENTER) dlg.set_icon(kickstartGui.iconPixbuf) dlg.set_border_width(2) dlg.set_modal(True) toplevel = self.xml.get_widget("main_window") dlg.set_transient_for(toplevel) dlg.run() dlg.hide() iter = self.store.get_iter_first() iter = self.store.iter_next(iter) self.view.get_selection().select_iter(iter) self.notebook.set_current_page(1) widget.grab_focus() return def splitUrl(self, data): //文本处理开始了。。将URL中的主机地址和目录区分开。 tokens = string.split(data, "/") host = tokens[0] dir = tokens[1:] dir = string.join(dir, '/') dir = "/" + dir return host, dir def applyKickstart(self): //最终传给主类的信息,一系列的判断。。 if not self.ks.upgrade.upgrade: 肯定不选升级?是,全新安装激活了,否,升就升呗。 self.install_radiobutton.set_active(True) else: self.upgrade_radiobutton.set_active(True) if self.ks.method.method == "cdrom": 选择cd ? self.cdrom_radiobutton.set_active(True) 好,那就cd. elif self.ks.method.method == "harddrive": 选择硬盘? self.hd_radiobutton.set_active(True) 好阿 if self.ks.method.partition != "": 用户输入不为空, self.hdpart_entry.set_text(self.ks.method.partition) 接收用户的输入,随别什么都可以。 if self.ks.method.dir != "": self.hddir_entry.set_text(self.ks.method.dir) elif self.ks.method.method == "nfs": NFS? self.nfs_radiobutton.set_active(True) if self.ks.method.server != "": self.nfsserver_entry.set_text(self.ks.method.server) if self.ks.method.dir != "": self.nfsdir_entry.set_text(self.ks.method.dir) elif self.ks.method.method == "url": http?ftp?靠,还得判断协议/ tokens = string.split(self.ks.method.url, "://") 分割。 protocol = tokens[0] tokens就是一list,里面只有两项,这是第一项,不是http就是ftp data = tokens[1] url除去协议的那部分。 if protocol == "ftp": ftp? self.ftp_radiobutton.set_active(True) if "@" in data: 一定得包含用户名和密码,即是是访问匿名服务器。 self.ftpuserpass_checkbutton.set_active(True) loginData, data = string.split(data, "@") username, password = string.split(loginData, ":") self.ftpuser_entry.set_text(username) 因为要满足ks文件固定的格式,也就是必须迎合anaconda. self.ftppasswd_entry.set_text(password) host, dir = self.splitUrl(data) self.ftpserver_entry.set_text(host) self.ftpdir_entry.set_text(dir) else: host, dir = self.splitUrl(data) elif protocol == "http": ftp都分析完了,还说什么http。 host, dir = self.splitUrl(data) self.http_radiobutton.set_active(True) self.httpserver_entry.set_text(host) self.httpdir_entry.set_text(dir) 5种安装方式也不过如此而已,具体处理string也是很简单的操作,此程序功能的缺失不够意思,竟然不去检查硬盘安装时的输入。 输入越多,需要检查输入的地方就越多。比如网络安装不是主机名的话,IP地址是否合法?这是功能性需要改进的地方。 然而从程序本身我能说些什么了呢?我仅仅感慨GTK notebook widget的好玩?类、方法、参数、调用均是我现在看不到的,基本也没有算法,仅是一个结构上的问题,几乎都是放在UI方面。对于我来说,越是简单的越便于我为更深入的奠定基础,为anaconda,heartbeat3之pacermaker的前端开发打基础。路还很长! |