PERFORCE change 125761 for review

Ivan Voras ivoras at FreeBSD.org
Mon Aug 27 16:47:29 PDT 2007


http://perforce.freebsd.org/chv.cgi?CH=125761

Change 125761 by ivoras at ivoras_finstall on 2007/08/27 23:47:26

	Getting ready for the first alpha / technology preview release.
	- implemented network configuration
	- started working on x11 configuration
	- implemented many configuration settings

Affected files ...

.. //depot/projects/soc2007/ivoras_finstall/installer/basewin.py#6 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/finstall.py#15 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/commonservices.glade#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/netconf.glade#2 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/nfinish.glade#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/x11conf.glade#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/text/netconf.txt#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/text/nfinish.txt#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/text/x11conf.txt#1 add
.. //depot/projects/soc2007/ivoras_finstall/makeimage/bundles/bundle-spec#5 edit
.. //depot/projects/soc2007/ivoras_finstall/makeimage/bundles/gtk.xml#1 add
.. //depot/projects/soc2007/ivoras_finstall/makeimage/bundles/ipfw.rules#1 add
.. //depot/projects/soc2007/ivoras_finstall/makeimage/bundles/prelogin#2 edit
.. //depot/projects/soc2007/ivoras_finstall/makeimage/bundles/prelogin.py#1 add
.. //depot/projects/soc2007/ivoras_finstall/makeimage/bundles/xfce4-tips-autostart.desktop#1 add
.. //depot/projects/soc2007/ivoras_finstall/pybackend/conffile.py#4 edit
.. //depot/projects/soc2007/ivoras_finstall/pybackend/freebsd.py#9 edit
.. //depot/projects/soc2007/ivoras_finstall/pybackend/systoolengine.py#12 edit

Differences ...

==== //depot/projects/soc2007/ivoras_finstall/installer/basewin.py#6 (text+ko) ====

@@ -1,4 +1,4 @@
-import os.path
+import os.path, re
 from types import MethodType
 import gtk, gtk.gdk, gtk.glade
 
@@ -104,3 +104,12 @@
 			col.set_sort_column_id(listid)
 		return col
 
+
+	def _ipv4_valid(self, addr):
+		m = re.match(r"(\d+)\.(\d+)\.(\d+)\.(\d+)", addr)
+		if m == None:
+			return False
+		if 0 <= int(m.group(1)) <= 255 and 0 <= int(m.group(2)) <= 255 and 0 <= int(m.group(3)) <= 255 and 0 <= int(m.group(4)) <= 255:
+			return True
+		return False
+

==== //depot/projects/soc2007/ivoras_finstall/installer/finstall.py#15 (text+ko) ====

@@ -49,8 +49,9 @@
 		{ "tile" : "hostroot" },
 		{ "tile" : "createuser" },
 		{ "tile" : "netconf" },
-		{ "tile" : "x11conf" },
-		{ "tile" : "soundconf" },
+#		{ "tile" : "x11conf" },
+#		{ "tile" : "soundconf" },
+		{ "tile" : "commonservices" },
 		{ "tile" : "nfinish" }
 	]
 
@@ -59,8 +60,9 @@
 		{ "tile" : "hostroot" },
 		{ "tile" : "createuser" },
 		{ "tile" : "netconf" },
-		{ "tile" : "x11conf" },
-		{ "tile" : "soundconf" },
+#		{ "tile" : "x11conf" },
+#		{ "tile" : "soundconf" },
+		{ "tile" : "commonservices" },
 		{ "tile" : "nfinish" }
 	]
 
@@ -247,6 +249,8 @@
 		elif self["radio_expert"].get_active():
 			print "expert"
 		elif self["radio_config"].get_active():
+			self._show_message("This mode is used to configure the *current* system, e.g. if you are using the "
+				"LiveCD, you will configure the LiveCD system, which is not very useful (except for debugging).", "Information")
 			logging.info("track=config")
 			self._load_track(self.Steps_Config)
 			self.server.SetDestRoot("/")
@@ -302,6 +306,10 @@
 		else:
 			# The drive is partitioned, so it's either an upgrade or the user wants
 			# to install it in empty space.
+			# DISABLED FOR ALPHA RELEASE
+			self._show_message("The installer currently doesn't support installing to an already partitioned drive. Please choose an unpartitioned drive.", "Not implemented")
+			return False
+
 			self.trackdata["parts"] = parts
 			logging.info("Drive %s is partitioned" % drive)
 			self._set_next_tile("nparts")
@@ -694,6 +702,9 @@
 		if username.find(" ") != -1:
 			self._show_message("Invalid username. No whitespace, please.", "Error")
 			return False
+		if username == "":
+			self._show_message("Username is empty - the user will not be created.", "Skipping user creation")
+			return True
 		if self["cb_wheel"].get_active():
 			groups = ["wheel"]
 		else:
@@ -707,15 +718,120 @@
 
 
 	def netconf_on_load(self):
-		pass
+		self._load_label(self["label2"], "netconf.txt")
+		nics = self.server.GetNetworkInterfaces()
+		if nics == None:
+			return True
+		ls = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+		self.trackdata["nics"] = []
+		for nic in nics:
+			if nics[nic]["type"] == "manual":
+				row = [nic, nics[nic]["inet"], nics[nic]["netmask"]]
+				ls.append(row)
+				self.trackdata["nics"].append(row)
+			elif nics[nic]["type"] == "DHCP":
+				row = [nic, "DHCP", ""]
+				ls.append(row)
+				self.trackdata["nics"].append(row)
+			else:
+				logging.error("Unknown NIC config type: %s" % nic[nic]["type"])
+		self["treeview_netif"].set_model(ls)
+		self["treeview_netif"].append_column(self._make_column("Device", 0, True))
+		self["treeview_netif"].append_column(self._make_column("Address", 1, False))
+		self["treeview_netif"].append_column(self._make_column("Netmask", 2, False))
+		self["treeview_netif"].set_cursor(0, None, True)
+		self["cb_ipv6"].set_active(self.server.GetIPv6Enabled())
+		self["cb_ipfw"].set_active(self.server.GetIPfwEnabled())
+		default_router = self.server.GetDefaultRouter()
+		if default_router:
+			self["entry_defaultrouter"].set_text(default_router)
+		dns_servers = self.server.GetDNSServers()
+		if dns_servers:
+			self["entry_dns"].set_text(dns_servers[0])
+		self.netconf_on_treeview_netif_row_activated(self["treeview_netif"], [0], None) # simulate a click in the grid
+		return True
+
+
+	def netconf_on_treeview_netif_row_activated(self, treeview, path, view_column):
+		nic_id = path[0]
+		self.trackdata["nic_selected"] = nic_id
+		nic = self.trackdata["nics"][nic_id]
+		if nic[1] == "DHCP":
+			self["cb_dhcp"].set_active(True)
+			self["entry_inet"].set_sensitive(False)
+			self["entry_netmask"].set_sensitive(False)
+		else:
+			self["cb_dhcp"].set_active(False)
+			self["entry_inet"].set_text(nic[1])
+			self["entry_inet"].set_sensitive(True)
+			self["entry_netmask"].set_text(nic[2])
+			self["entry_netmask"].set_sensitive(True)
+
+
+	def netconf_on_cb_dhcp_toggled(self, evt):
+		if self["cb_dhcp"].get_active():
+			self["entry_inet"].set_text("")
+			self["entry_inet"].set_sensitive(False)
+			self["entry_netmask"].set_text("")
+			self["entry_netmask"].set_sensitive(False)
+			self.trackdata["nics"][self.trackdata["nic_selected"]][1] = "DHCP"
+			self.trackdata["nics"][self.trackdata["nic_selected"]][2] = ""
+		else:
+			self.trackdata["nics"][self.trackdata["nic_selected"]][1] = "10.0.0.2"
+			self.trackdata["nics"][self.trackdata["nic_selected"]][2] = "255.255.255.0"
+			self["entry_inet"].set_text(self.trackdata["nics"][self.trackdata["nic_selected"]][1])
+			self["entry_inet"].set_sensitive(True)
+			self["entry_netmask"].set_text(self.trackdata["nics"][self.trackdata["nic_selected"]][2])
+			self["entry_netmask"].set_sensitive(True)
+		self.netconf_recalc_model()
+
+
+	def netconf_on_entry_inet_focus_out_event(self, w, evt):
+		self.netconf_validate_set_nics()
+
+	
+	def netconf_on_entry_netmask_focus_out_event(self, w, evt):
+		self.netconf_validate_set_nics()
+
+
+	def netconf_validate_set_nics(self):
+		if not self._ipv4_valid(self["entry_inet"].get_text()):
+			self._show_message("%s is not a valid IPv4 address" % self["entry_inet"].get_text())
+			return
+		if not self._ipv4_valid(self["entry_netmask"].get_text()):
+			self._show_message("%s is not a valid IPv4 netmask" % self["entry_inet"].get_text())
+			return
+		self.trackdata["nics"][self.trackdata["nic_selected"]][1] = self["entry_inet"].get_text()
+		self.trackdata["nics"][self.trackdata["nic_selected"]][2] = self["entry_netmask"].get_text()
+		self.netconf_recalc_model()
+
+
+	def netconf_recalc_model(self):
+		"""Recreates the TreeView model based on the configured values of the NICs"""
+		ls = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
+		for row in self.trackdata["nics"]:
+			ls.append(row)
+		self["treeview_netif"].set_model(ls)
+		self["treeview_netif"].set_cursor(self.trackdata["nic_selected"], None)
 
 
 	def netconf_on_next(self):
-		pass
+		self.server.SetIPv6Enabled(self["cb_ipv6"].get_active())
+		self.server.SetIPfwEnabled(self["cb_ipfw"].get_active())
+		if self["entry_defaultrouter"].get_text() != "":
+			self.server.SetDefaultRouter(self["entry_defaultrouter"].get_text())
+		if self["entry_dns"].get_text() != "":
+			self.server.SetDNSServers([self["entry_dns"].get_text()])
+		for row in self.trackdata["nics"]:
+			self.server.ConfigureNetworkInterface(row[0], row[1], row[2])
+		return True
 
 
 	def x11conf_on_load(self):
-		pass
+		self._load_label(self["label2"], "x11conf.txt")
+		cfg = self.server.GetX11Configuration()
+		print cfg
+		return True
 
 
 	def x11conf_on_next(self):
@@ -730,12 +846,61 @@
 		pass
 
 
+	def commonservices_on_load(self):
+		self._load_label(self["label2"], "commonservices.txt")
+		self["cb_powerd"].set_active(self.server.GetConf("powerd_enable", "NO") == "YES")
+		self["cb_nfsserver"].set_active(self.server.GetConf("nfs_server_enable", "NO") == "YES")
+		self["cb_ssh"].set_active(self.server.GetConf("sshd_enable", "NO") == "YES")
+		self["cb_ntpdate"].set_active(self.server.GetConf("ntpdate_enable", "NO") == "YES")
+		self["cb_linux"].set_active(self.server.GetConf("linux_enable", "NO") == "YES")
+		return True
+
+
+	def commonservices_on_next(self):
+		if self["cb_powerd"].get_active():
+			self.server.SetConf("powerd_enable", "YES", "Power saving daemon")
+		else:
+			self.server.SetConf("powerd_enable", "NO", "Power saving daemon")
+
+		if self["cb_nfsserver"].get_active():
+			self.server.SetConf("nfs_server_enable", "YES", "NFS server")
+			self.server.SetConf("rpc_lockd_enable", "YES", "NFS lockd")
+			self.server.SetConf("rpc_statd_enable", "YES", "NFS statd")
+		else:
+			self.server.SetConf("nfs_server_enable", "NO", "NFS server")
+
+		if self["cb_ssh"].get_active():
+			self.server.SetConf("sshd_enable", "YES", "SSH server")
+		else:
+			self.server.SetConf("sshd_enable", "NO", "SSH server")
+				
+		if self["cb_ntpdate"].get_active():
+			self.server.SetConf("ntpdate_enable", "YES", "Sync NTP on boot")
+			self.server.SetConf("ntpdate_hosts", "pool.ntp.org", "NTP default pool")
+		else:
+			self.server.SetConf("ntpdate_enable", "NO", "Sync NTP on boot")
+
+		if self["cb_ntpd"].get_active():
+			self.server.SetConf("ntpd_enable", "YES", "Network time sync")
+		else:
+			self.server.SetConf("ntpd_enable", "NO", "Network time sync")
+
+		if self["cb_linux"].get_active():
+			self.server.SetConf("linux_enable", "YES", "Linux ABI support")
+		else:
+			self.server.SetConf("linux_enable", "NO", "Linux ABI support")
+		return True
+
+
 	def nfinish_on_load(self):
-		pass
+		self._load_label(self["label2"], "nfinish.txt")
+		return True
 
 
 	def nfinish_on_next(self):
-		pass
+		self._show_message("Have a nice day!", "Install finished")
+		gtk.main_quit()
+		return False
 
 
 my_dir = os.path.split(sys.argv[0])[0]

==== //depot/projects/soc2007/ivoras_finstall/installer/glade/netconf.glade#2 (text+ko) ====

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.2.2 on Wed Aug 22 00:09:02 2007 by ivoras at finstall.cosmos-->
+<!--Generated with glade3 3.2.2 on Mon Aug 27 23:49:37 2007 by ivoras at finstall.cosmos-->
 <glade-interface>
   <widget class="GtkWindow" id="window1">
     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
@@ -49,7 +49,7 @@
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <child>
-                      <widget class="GtkCheckButton" id="checkbutton1">
+                      <widget class="GtkCheckButton" id="cb_ipv6">
                         <property name="width_request">220</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
@@ -81,7 +81,7 @@
                           </packing>
                         </child>
                         <child>
-                          <widget class="GtkEntry" id="entry3">
+                          <widget class="GtkEntry" id="entry_defaultrouter">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
@@ -107,7 +107,7 @@
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <child>
-                      <widget class="GtkCheckButton" id="checkbutton2">
+                      <widget class="GtkCheckButton" id="cb_ipfw">
                         <property name="width_request">220</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
@@ -139,7 +139,7 @@
                           </packing>
                         </child>
                         <child>
-                          <widget class="GtkEntry" id="entry4">
+                          <widget class="GtkEntry" id="entry_dns">
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
@@ -177,12 +177,13 @@
                     <property name="visible">True</property>
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <child>
-                      <widget class="GtkTreeView" id="treeview1">
+                      <widget class="GtkTreeView" id="treeview_netif">
                         <property name="height_request">300</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="headers_clickable">True</property>
+                        <signal name="row_activated" handler="on_treeview_netif_row_activated"/>
                       </widget>
                       <packing>
                         <property name="padding">15</property>
@@ -200,6 +201,7 @@
                             <property name="label" translatable="yes">Use DHCP?</property>
                             <property name="response_id">0</property>
                             <property name="draw_indicator">True</property>
+                            <signal name="toggled" handler="on_cb_dhcp_toggled"/>
                           </widget>
                           <packing>
                             <property name="expand">False</property>
@@ -218,61 +220,63 @@
                               <placeholder/>
                             </child>
                             <child>
-                              <widget class="GtkEntry" id="entry2">
-                                <property name="width_request">70</property>
+                              <widget class="GtkLabel" id="label3">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="xalign">1</property>
+                                <property name="label" translatable="yes">IPv4 address:</property>
                               </widget>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
                                 <property name="y_options"></property>
+                                <property name="x_padding">2</property>
                               </packing>
                             </child>
                             <child>
-                              <widget class="GtkEntry" id="entry1">
-                                <property name="width_request">70</property>
+                              <widget class="GtkLabel" id="label4">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+                                <property name="xalign">1</property>
+                                <property name="label" translatable="yes">IPv4 network mask:</property>
                               </widget>
                               <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
                                 <property name="y_options"></property>
+                                <property name="x_padding">2</property>
                               </packing>
                             </child>
                             <child>
-                              <widget class="GtkLabel" id="label4">
+                              <widget class="GtkEntry" id="entry_inet">
+                                <property name="width_request">120</property>
                                 <property name="visible">True</property>
+                                <property name="can_focus">True</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="xalign">1</property>
-                                <property name="label" translatable="yes">IPv4 network mask:</property>
+                                <signal name="focus_out_event" handler="on_entry_inet_focus_out_event"/>
                               </widget>
                               <packing>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
                                 <property name="y_options"></property>
-                                <property name="x_padding">2</property>
                               </packing>
                             </child>
                             <child>
-                              <widget class="GtkLabel" id="label3">
+                              <widget class="GtkEntry" id="entry_netmask">
+                                <property name="width_request">120</property>
                                 <property name="visible">True</property>
+                                <property name="can_focus">True</property>
                                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                                <property name="xalign">1</property>
-                                <property name="label" translatable="yes">IP address:</property>
+                                <signal name="focus_out_event" handler="on_entry_netmask_focus_out_event"/>
                               </widget>
                               <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="top_attach">1</property>
+                                <property name="bottom_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
                                 <property name="y_options"></property>
-                                <property name="x_padding">2</property>
                               </packing>
                             </child>
                           </widget>
@@ -282,6 +286,7 @@
                         </child>
                       </widget>
                       <packing>
+                        <property name="expand">False</property>
                         <property name="padding">15</property>
                         <property name="position">1</property>
                       </packing>

==== //depot/projects/soc2007/ivoras_finstall/makeimage/bundles/bundle-spec#5 (text+ko) ====

@@ -12,7 +12,6 @@
 /etc/hosts=hosts;kw;a
 /etc/fstab=fstab;kw
 /etc/rc.d/prelogin=prelogin;kw;x
-/etc/prelogin.txt=prelogin.txt
 /etc/ipfw.rules=ipfw.rules
 /root/.xinitrc=dot.xinitrc;kw
 /root/.config/xfce4/mcs_settings/gtk.xml=gtk.xml
@@ -21,6 +20,8 @@
 /install/.xinitrc=dot.xinitrc;kw
 /install/.config/xfce4/mcs_settings/gtk.xml=gtk.xml
 /install/installer=../../installer;d
+/install/prelogin.txt=prelogin.txt
+/install/prelogin.py=prelogin.py;kw;x
 /install/pybackend=../../pybackend;d
 /install/Desktop/installer.desktop=installer.desktop
 /usr/local/etc/fonts/local.conf=font.local.conf;kw

==== //depot/projects/soc2007/ivoras_finstall/makeimage/bundles/prelogin#2 (text+ko) ====

@@ -1,7 +1,7 @@
 #!/bin/sh
 # BEFORE: login
 
-cat /etc/prelogin.txt
+# Simply pass execution to prelogin.py
 
-rm /install/Desktop/TRANS.TBL
+/usr/local/bin/python /install/prelogin.py
 

==== //depot/projects/soc2007/ivoras_finstall/pybackend/conffile.py#4 (text+ko) ====

@@ -22,6 +22,7 @@
 # Class encapsulating a configuration file such as /etc/rc.conf
 
 import os,os.path
+import re
 
 class ConfFile:
 
@@ -60,24 +61,26 @@
 					if val[-1] == '"':
 						val = val[0:-1]
 				return (i, line, val.strip())
-		raise LookupError("Cannot find %s" % search_name)
+		raise LookupError("Cannot find '%s'" % search_name)
 
 
 	def _saveFile(self):
 		"""Saves the config file data"""
 		f = file(self.filename, "w")
 		for line in self.lines:
-			f.write("%s\n", line.strip())
+			f.write("%s\n" % line.strip())
 		f.close()
 
 
 	def GetConf(self, search_name, default=None):
-		"""Returns the requested configuration variable, or the
+		"""
+		Returns the requested configuration variable, or the
 		default value if it's not found. We don't do any kind of
 		caching here (e.g. the smart thing would be to do the
 		parsing once and store it all in a dictionary) because we
 		want to preserve the structure of the config file as much
-		as possible, including user additions and comments."""
+		as possible, including user additions and comments.
+		"""
 		try:
 			n, line, val = self._findLine(search_name)
 			return val
@@ -85,24 +88,43 @@
 			return default
 
 
-	def SetConf(self, name, val, description=None):
-		"""Sets the specified name-value pair in the configuration
-		file. Optionally, also sets the description as comment."""
+	def SetConf(self, name, new_val, description=None):
+		"""
+		Sets the specified name-value pair in the configuration
+		file. Optionally, also sets the description as comment.
+		"""
 		try:
-			n, line, val = self._findLine(search_name)
+			n, line, val = self._findLine(name)
 			set_description = True
 			if n > 0:
 				line_before = self.lines[n-1]
 				if len(line_before) >= 2 and line_before[0:2] == "##":
 					set_description = False
+			self.lines[n] = '%s="%s"' % (name, new_val)
 			if set_description and description:
 				self.lines.insert(n-1, "## %s" % description)
-			self.lines[n] = '%s="%s"' % (name, val)
 		except LookupError:
 			self.lines.append("")
 			if description:
 				self.lines.append("## %s" % description)
-			self.lines.append('%s="%s"' % (name, val))
+			self.lines.append('%s="%s"' % (name, new_val))
 		self._saveFile()
+		return True
+
+
+	def GetConfKeys(self):
+		"""Returns a list of names of config variables / keys"""
+		keys = {}
+		for line in self.lines:
+			m = re.match(r"^([a-zA-Z0-9_]+)\s*=\s*([^#]+)", line)
+			if m != None:
+				value = m.group(2).strip()
+				if value.startswith('"'):
+					value = value[1:]
+				if value.endswith('"'):
+					value = value[:-1]
+				keys[m.group(1)] = value
+		return keys
+
 
 

==== //depot/projects/soc2007/ivoras_finstall/pybackend/freebsd.py#9 (text+ko) ====

@@ -39,8 +39,10 @@
 cmd_gjournal = "/sbin/gjournal"
 cmd_kldstat = "/sbin/kldstat"
 cmd_kldload = "/sbin/kldload"
+cmd_ifconfig = "/sbin/ifconfig"
 cmd_mke2fs = "/usr/local/sbin/mke2fs"
 cmd_boot0cfg = "/usr/sbin/boot0cfg"
+cmd_vidcontrol = "/usr/sbin/vidcontrol"
 cmd_pw = "/usr/sbin/pw"
 
 file_dmesg = "/var/run/dmesg.boot"
@@ -357,7 +359,10 @@
 def chpasswd(user_name, password, etc_dir="/etc"):
 	"""Changes the user's password. The user must exist."""
 	global cmd_pw
-	return exec_cmd("%s -V %s usermod %s -h 0" % (cmd_pw, etc_dir, user_name), password)
+	if password != "":
+		return exec_cmd("%s -V %s usermod %s -h 0" % (cmd_pw, etc_dir, user_name), password)
+	else:
+		return exec_cmd("%s -V %s usermod %s -w none" % (cmd_pw, etc_dir, user_name))
 
 
 def useradd(user_name, user, password, shell, groups=[], etc_dir="/etc"):
@@ -373,6 +378,78 @@
 		return exec_cmd("%s -V %s useradd %s -m -s %s -c \"%s\" -b %s" % (cmd_pw, etc_dir, user_name, shell, user, guess_home))
 
 
+def getnicsinfo():
+	"""Returnes NIC information from ifconfig"""
+	global cmd_ifconfig
+	code, result = exec_cmd("%s -l" % cmd_ifconfig)
+	if code != 0:
+		return None
+	nics = {}
+	for nic in [x for x in result.split(" ") if not (x.startswith("lo") or x.startswith("plip"))]:
+		code, result = exec_cmd("%s %s" % (cmd_ifconfig, nic))
+		if code != 0:
+			return None
+		ni = {}
+		m = re.match(r"flags=(\d+)<(.+)>.+ mtu (\d+)", result)
+		if m != None:
+			ni["flags"] = int(m.group(1))
+			ni["flags_str"] = m.group(2).split(",")
+			ni["mtu"] = int(m.group(2))
+		m = re.match(r"ether (..:..:..:..:..:..)", result)
+		if m != None:
+			ni["ether"] = m.group(1)
+		m = re.match(r"inet (\d+\.\d+\.\d+\.\d+) netmask 0x(.+) broadcast (\d+\.\d+\.\d+\.\d+)", result)
+		if m != None:
+			ni["inet"] = m.group(1)
+			ni["netmask"] = m.group(2)
+			ni["broadcast"] = m.group(3)
+		m = re.match(r"media: (.+)")
+		if m != None:
+			ni["media"] = m.group(1)
+		nics[nic] = ni
+	return nics
+
+
+def get_dns_servers(etc_dir="/etc"):
+	"""Returns DNS server information from resolv.conf"""
+	servers = []
+	for line in file("%s/resolv.conf" % etc_dir, "r"):
+		line = line.strip()
+		m = re.match(r"nameserver\s+(\d+\.\d+\.\d+\.\d+)", line)
+		if m != None:
+			servers.append(m.group(1))
+	return servers
+
+
+def set_dns_servers(dnss, domain, etc_dir="/etc"):
+	"""Writes a new resolv.conf from given arguments"""
+	f = file("%s/resolv.conf" % etc_dir, "w")
+	if domain:
+		f.write("domain %s\n" % domain)
+	for d in dnss:
+		f.write("nameserver %s\n" % d)
+	f.close()
+
+
+def vesa_detect_modes():
+	"""Returnes a list of lists describing detected VESA video modes"""
+	global cmd_vidcontrol, cmd_kldload, cmd_kldstat
+	code, result = exec_cmd(cmd_kldstat)
+	if result.find("vesa.ko"):
+		code, result = exec_cmd("%s vesa.ko" % cmd_kldload)
+	code, result = exec_cmd("%s -i modes < /dev/ttyv0" % cmd_vidcontrol)
+	mall = re.findall(r"^\s*\d+\s+\(.+\)\s+0x.+?\s+G\s+(\d+)x(\d+)x(\d+)\s+\d", re.M)
+	modes = []
+	for m in mall:
+		x = int(m.group(1))
+		y = int(m.group(2))
+		c = int(m.group(3))
+		if x >= 800:
+			modes.append((x,y,c))
+	return modes
+
+
+
 if __name__ == "__main__":
 	xml = get_geom_xml()
 	for cls in xml["mesh"]["class"]:

==== //depot/projects/soc2007/ivoras_finstall/pybackend/systoolengine.py#12 (text+ko) ====

@@ -359,12 +359,14 @@
 	"""
 	This job finishes the installation - unmounts the temporary tree, etc.
 	"""
-	def __init__(self, part_spec, force):
+	def __init__(self, systool, part_spec, force):
 		SysToolJob.__init__(self)
 		self.part_spec = part_spec
 		self.force = force
+		self.systool = systool
 
 	def run(self):
+		self.systool.SetConf("moused_enable", "YES", "Enable system mouse") # by default
 		code, result = self.UmountPartitions(self.part_spec, self.INSTALL_ROOT, force)
 		if code != 0:
 			self.error = code
@@ -417,12 +419,33 @@
 		return cf.GetConf(name, default)
 
 
-	def SetConf(self, name, value, description):
+	def SetConf(self, name, value, description=""):
 		"""Sets configuration variable to /etc/rc.conf"""
 		cf = ConfFile("%s/etc/rc.conf" % self.root_dest)
 		return cf.SetConf(name, value, description)
 
 
+	def GetConfBoolean(self, name):
+		val = self.GetConf(name, None)
+		if val != None and val.upper() == "YES":
+			return True
+		else:
+			return False
+
+
+	def SetConfBoolean(self, name, val, description=""):
+		if val:
+			self.SetConf(name, "YES", description)
+		else:
+			self.SetConf(name, "NO", description)
+
+
+	def GetConfKeys(self):
+		"""Returns rc.conf keys (variables)"""
+		cf = ConfFile("%s/etc/rc.conf" % self.root_dest)
+		return cf.GetConfKeys()
+
+
 	@logexception
 	def GetShells(self):
 		"""Returns a list of acceptable shells"""
@@ -635,6 +658,20 @@
 
 
 	@logexception
+	def StartPostInstallJob(self, part_spec, force):
+		"""
+		Starts the post-install job. Returns an integer job_id.
+		"""
+		self.job_list_lock.acquire()
+		job = PostInstallJob(self, part_spec, force)
+		self.job_list.append(job)
+		job_id = len(self.job_list)
+		job.start()
+		self.job_list_lock.release()
+		return job_id
+
+
+	@logexception
 	def QueryJobProgress(self, job_id):
 		"""
 		Queries the progress of a job, returns percent complete or None
@@ -704,6 +741,7 @@
 
 	@logexception
 	def SetHostName(self, host_name):
+		"""Sets the host name in rc.conf"""
 		if self.SetConf("hostname", host_name, "Host name"):
 			return (0, None)
 		else:
@@ -712,6 +750,7 @@
 
 	@logexception
 	def GetHostName(self):
+		"""Returns host name from rc.conf"""
 		host_name = self.GetConf("hostname")
 		if host_name == None:
 			return "amnesiac"
@@ -721,11 +760,218 @@
 
 	@logexception
 	def SetUserPassword(self, user_name, password):
+		"""Mofifies user's password"""
 		return freebsd.chpasswd(user_name, password, "%s/etc" % self.root_dest)
 
 	
 	@logexception
 	def AddUser(self, user_name, user, password, shell, groups):
+		"""Creates a user"""
 		return freebsd.useradd(user_name, user, password, shell, groups, "%s/etc" % self.root_dest)
 
 
+	@logexception
+	def GetPresentNetworkInterfaces(self):
+		"""Returns currently available network interfaces"""
+		return freebsd.getnicsinfo()
+
+
+	@logexception
+	def GetNetworkInterfaces(self):
+		"""Returns configured network interfaces (in rc.conf)"""
+		nics = {}
+		keys = self.GetConfKeys()
+		for key in keys:
+			value = keys[key]
+			if key.find("alias") == -1:
+				m = re.match("ifconfig_(.+)", key)
+				if m != None:
+					nic = m.group(1)
+					nics[nic] = {}
+					m = re.search(r"inet\s+(\d+\.\d+\.\d+\.\d+)", value)
+					if m != None:
+						nics[nic]["type"] = "manual"
+						nics[nic]["inet"] = m.group(1)
+						m = re.search(r"netmask\s+(\d+\.\d+\.\d+\.\d+)", value)
+						if m != None:
+							nics[nic]["netmask"] = m.group(1)
+					elif value.upper() == "DHCP":
+						nics[nic]["type"] = "DHCP"
+					else:
+						nics[nic]["type"] = "unknown"
+		return nics
+
+	
+	@logexception
+	def GetIPv6Enabled(self):
+		"""Returns value of "ipv6_enable" rc.conf variable"""
+		return self.GetConfBoolean("ipv6_enable")
+
+	
+	@logexception
+	def GetIPfwEnabled(self):
+		"""Returns value of "firewall_enable" rc.conf variable"""
+		return self.GetConfBoolean("firewall_enable")
+
+
+	@logexception
+	def GetDefaultRouter(self):
+		"""Returns value of "defaultrouter" rc.conf variable"""
+		return self.GetConf("defaultrouter", None)
+
+
+	@logexception
+	def GetDNSServers(self):
+		"""Returns nameserver contents of /etc/resolv.conf"""
+		return freebsd.get_dns_servers("%s/etc" % self.root_dest)
+
+
+	@logexception
+	def SetIPv6Enabled(self, val):
+		"""Sets the "ipv6_enable" rc.conf variable"""
+		self.SetConfBoolean("ipv6_enable", val, "Enable IPv6 networking")
+
+
+	@logexception
+	def SetIPfwEnabled(self, val):
+		"""Sets the "firewall_enable" rc.conf variable"""
+		self.SetConfBoolean("firewall_enable", val, "Enable ipfw firewall")
+		if val:
+			self.SetConf("firewall_type", "client", "Firewall type (predefined)")
+
+
+	@logexception
+	def SetDefaultRouter(self, val):
+		"""Sets the "defaultrouter" rc.conf variable"""
+		self.SetConf("defaultrouter", val, "The default IPv4 gateway")
+
+
+	@logexception
+	def SetDNSServers(self, dnss):
+		"""Configures /etc/resolv.conf"""
+		hostname = self.GetHostName()
+		if hostname.find(".") != -1:
+			domain = hostname[hostname.find(".")+1:]
+		else:
+			domain = None
+		freebsd.set_dns_servers(dnss, domain, "%s/etc" % self.root_dest)
+
+	
+	@logexception
+	def ConfigureNetworkInterface(self, name, inet, netmask):
+		"""Configure a network interface in rc.conf"""
+		var_name = "ifconfig_%s" % name
+		if inet.upper() == "DHCP":
+			self.SetConf(var_name, "DHCP")
+		else:
+			self.SetConf(var_name, "inet %s netmask %s" % (inet, netmask))
+
+	
+	@logexception
+	def GetX11Configuration(self):
+		"""Returns what it can find about xorg.conf."""
+		result = {}
+		result["detect"] = {}
+		result["detect"]["modes"] = freebsd.vesa_detect_modes()
+		# Parse available keyboard models. This isn't a fully functional
+		# parser, but simmulates a subset only for parsing of the "pc" x.org
+		# definition.
+		result["detect"]["keyboard_models"] = {}
+		f = file("%s/usr/local/share/X11/xkb/geometry/pc" % self.root_dest, "r")
+		line = ""
+		while line != None:
+			line = f.readline().strip()
+			m = re.search(r'.+xkb_geometry\s+"(.+?)"\s*{', line)
+			if m != None:
+				model = m.group(1)
+				while line != None:
+					line = f.readline().strip()
+					if line != None:
+						m = re.search(r'\s*description\s*=\s*".+?";', line)
+						if m != None:
+							result["detect"]["keyboard_models"][model] = {"description":m.group(1)}
+							break
+		f.close()
+		# Parse available kayboard layouts. Not a very robust parser.
+		result["detect"]["keyboard_symbols"] = {}
+		xkb_symbols_dir = "%s/usr/local/share/X11/xkb/symbols" % self.root_dest
+		kblist = os.listdir(xkb_symbols_list)
+		for kbname in kblist:
+			kbfilename = "%s/%s" % (xkb_symbols_dir, kbname)
+			if os.path.isfile(kbfilename):
+				kbdescr = {}
+				result["detect"]["keyboard_symbols"][kbname] = kbdescr
+				kbfile = file(kbfilename, "r").read()
+				name = None
+				m = re.search(r'^\s*name[Group1]\s*=\s*"(.+?)";', kbfile, re.M)
+				if m != None:
+					name = m.group(1)
+				kbdescr["name"] = name
+				kbdescr["subtypes"] = {}
+				subtypes = re.findall(r'kbd_symbols\s+"(.+?)"\s*{.+name[Group1]\s*=\s*"(.+?)"\s*;', kbfile, re.M | re.S)
+				for st in subtypes:
+					kbdescr["subtypes"][m.group(1)] = {"description" : m.group(2)}
+		result["conf"] = {}
+		# Parse xorg.conf (if it exists). Not a robust parser.
+		xorg_conf = "%s/etc/X11/xorg.conf" % self.root_dest
+		if os.path.exists(xorg_conf):
+			conf = file(xorg_conf, "r").read()
+			m = re.search(r'Section\s+"InputDevice"(.+?Driver\s*"kbd".+?)EndSection', conf, re.S)
+			if m != None:
+				kbd_conf = m.group(1)
+				m = re.search(r'Option\s+"XkbModel"\s+"(.+?)"', kbd_conf)
+				if m != None:
+					result["conf"]["XkbModel"] = m.group(1)
+				m = re.search(r'Option\s+"XkbLayout"\s+"(.+?)"', kbd_conf)
+				if m != None:
+					result["conf"]["XkbLayout"] = m.group(1)
+				m = re.search(r'Option\s+"XkbVariant"\s+"(.+?)"', kbd_conf)
+				if m != None:
+					result["conf"]["XkbVariant"] = m.group(1)
+			m = re.search(r'Section\s+"Device"(.+?)EndSection', conf)
+			if m != None:
+				device_conf = m.group(1)
+				m = re.search(r'Driver\s+"(.+?)"')
+				if m != None:
+					result["conf"]["DisplayDriver"] = m.group(1)
+			m = re.search(r'Section\s+"Screen"(.+?)EndSection', conf)
+			if m != None:
+				screen_conf = m.group(1)
+				m = re.search(r'DefaultDepth\s+(\d+)', screen_conf)
+				if m != None:
+					result["conf"]["DisplayDefaultDepth"] = int(m.group(1))
+				m = re.search(r'SubSection\s+"Display"(.+?)EndSubSection', screen_conf)
+				if m != None:
+					display_conf = m.group(1)
+					m = re.search(r'Depth\s+(\d+)', display_conf)
+					if m != None:
+						result["conf"]["DisplayDepth"] = int(m.group(1))
+					m = re.search(r'^\s*Modes\s+(.+?)$', display_conf, re.M)
+					if m != None:
+						mmodes = m.group(1)
+						mmodes = mmodes.replace("\t", " ")
+						while mmodes.find("  ") != -1:
+							mmodes = mmodes.replace("  ", " ")
+						mmodes = mmodes.split(" ")
+						for i,m in enumerate(mmodes):
+							if m.startswith('"'):
+								m = m[1:]
+							if m.endswith('"'):
+								m = m[:-1]
+							mmodes[i] = m
+						result["conf"]["DisplayModes"] = mmodes
+		return result
+
+
+
+
+
+
+
+
+
+
+
+
+		
+

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list