PERFORCE change 125281 for review

Ivan Voras ivoras at FreeBSD.org
Fri Aug 17 16:52:37 PDT 2007


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

Change 125281 by ivoras at ivoras_finstall on 2007/08/17 23:51:52

	- Polished the UI a little
	- Started working on partitioning primitives

Affected files ...

.. //depot/projects/soc2007/ivoras_finstall/installer/basewin.py#4 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/finstall.py#10 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/helpdialog.glade#2 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/installprogress.glade#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/intro.glade#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/mainwin.glade#9 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/ndefaultfs.glade#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/ndisks.glade#4 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/nparts.glade#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/glade/nverify.glade#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/helpdialog.py#3 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/text/intro.txt#4 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/text/ndefaultfs.txt#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/text/ndisks.txt#2 edit
.. //depot/projects/soc2007/ivoras_finstall/installer/text/nverify.txt#1 add
.. //depot/projects/soc2007/ivoras_finstall/installer/text/nverify_template.txt#1 add
.. //depot/projects/soc2007/ivoras_finstall/pybackend/freebsd.py#5 edit
.. //depot/projects/soc2007/ivoras_finstall/pybackend/systoold.py#6 edit
.. //depot/projects/soc2007/ivoras_finstall/pybackend/systoolengine.py#7 edit
.. //depot/projects/soc2007/ivoras_finstall/pybackend/xmldict.py#5 edit

Differences ...

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

@@ -40,12 +40,43 @@
 
 
 	def _load_label(self, label, file_name, dir="text"):
-		"""Returns the content of a text/* file with formatting replacements
-		so it looks decent when Pango renders it"""
-		label.set_text(file("%s/%s" % (dir, file_name)).read().replace("\n", " ").replace("<br>", "\n").replace("\n ", "\n"))
+		"""Retrieves the content of a text/* file with formatting replacements
+		so it looks decent when Pango renders it and sets the result to the
+		given label control"""
+		label.set_text(self._get_text(file_name, dir))
+		label.set_use_markup(True)
+
+
+	def _set_label(self, label, txt):
+		"""Sets the content of the given label-ish control to a text with
+		markup tags"""
+		label.set_text(txt)
 		label.set_use_markup(True)
 
 
+	def _get_text(self, file_name, dir="text"):
+		return self._process_markup(file("%s/%s" % (dir, file_name)).read())
+
+
+	def _process_markup(self, txt):
+		"""Processes the text from a non-standard combination of wiki markup
+		and HTML (similar to that of WordPress) into HTML that can be rendered
+		by Gnome's Pango in label controls."""
+		txt = txt.strip(" ")
+		buf = "" # This is not optimal performance-wise, but it's convenient
+		for para in txt.split("\n\n"):
+			if buf != "":
+				buf += "\n\n"
+			para = para.replace("\n", " ")
+			buf += self._process_markup_para(para).replace("<br>", "\n")
+		return buf
+
+
+	def _process_markup_para(self, txt):
+		"""Processes a single paragraph for _process_markup()"""
+		return txt # TODO
+
+
 	def _clear_container(self, cont):
 		for child in cont.get_children():
 			cont.remove(child)
@@ -55,8 +86,9 @@
 		"""Displays a message box"""
 		dlg = gtk.MessageDialog(self.window, flags=gtk.DIALOG_MODAL, type=p_type, buttons=p_buttons, message_format=text)
 		dlg.set_title(title)
-		dlg.run()
+		result = dlg.run()
 		dlg.destroy()
+		return result
 
 
 	def _make_column(self, name, listid, sort=False):

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

@@ -31,6 +31,11 @@
 from basewin import BaseWin
 from helpdialog import HelpDialog
 
+
+class InstallerException(Exception):
+	pass
+
+
 class MainWin(BaseWin):
 
 	# Configured tracks
@@ -38,7 +43,9 @@
 		{ "tile" : "intro" },
 		{ "tile" : "ndisks" },
 		{ "tile" : "nparts" },
-		{ "tile" : "nfilesys" }
+		{ "tile" : "ndefaultfs" },
+		{ "tile" : "nverify" },
+		{ "tile" : "ninstall" }
 	]
 
 
@@ -49,9 +56,10 @@
 		self["img_logo"].set_from_file("img/logo.jpg")
 		# img_logo stretches the window vertically, so calling window.set_position() has no affect
 		self._center_window(self.window)
-		self.step_current = 0
+		self.step_current = -1
+		self.step_next = 0
 		self.step_track = MainWin.Steps_Novice
-		self._load_tile_nr(self.step_current)
+		self._load_tile_nr(self.step_next)
 		self.backtrack = []
 
 
@@ -89,14 +97,17 @@
 	def _load_tile_nr(self, tile_nr):
 		"""Loads a (numerated) tile from the current step_track"""
 		self._load_tile(self.step_track[tile_nr]["tile"])
+		self.step_current = tile_nr
+		self.step_next = tile_nr + 1
 
 
 	def _set_next_tile(self, tile):
 		found = False
 		for i, t in enumerate(self.step_track):
 			if t["tile"] == tile:
-				self.step_current = i-1		# Actually this is not a clean hack, but it'll do for now
+				self.step_next = i	# Actually this is not a clean hack, but it'll do for now
 				found = True
+				break
 		if not found:
 			logging.error("_set_next_tile cannot set tile to %s. Bogosity ahead." % tile)
 
@@ -122,7 +133,7 @@
 	def initial_tasks(self):
 		"""Perform initial tasks after the GUI is running. For now,
 		set up connection to the SysToolD server"""
-		self.server = ServerProxy("http://localhost:1025")
+		self.server = ServerProxy("http://localhost:1025", allow_none=True)
 		try:
 			caps = self.server.GetCaps()
 		except:
@@ -150,10 +161,7 @@
 				logging.exception("Error executing on_next handler in %s" % self.step_track[self.step_current]["tile"])
 				return
 		self.backtrack.append(self.step_track[self.step_current]["tile"])
-		self.step_current += 1
-		if self.step_current >= len(self.step_track):
-			self.step_current = 0	# XXX: Fix by disabling next/previous
-		self._load_tile_nr(self.step_current)
+		self._load_tile_nr(self.step_next)
 
 
 	def on_button_previous_clicked(self, obj):
@@ -172,6 +180,7 @@
 			return
 		if len(self.backtrack) == 0:
 			self.step_current = 0
+			self.step_next = 1
 		else:
 			tile = self.backtrack.pop()
 			self.step_current = -1
@@ -180,12 +189,20 @@
 					self.step_current = i
 			if self.step_current < 0:
 				self._show_message("Cannot find tile %s" % tile, "Error", p_type.gtk.MESSAGE_ERROR)
+			else:
+				self.step_next = self.step_current + 1
 		self._load_tile_nr(self.step_current)
 
 
 	def on_button_help_clicked(self, obj):
 		help = HelpDialog(self.step_track[self.step_current]["tile"])
 		help.window.show()
+
+
+	def on_button_cancel_clicked(self, obj):
+		res = self._show_message("Do you really want to cancel?", "Cancel?", gtk.BUTTONS_YES_NO, gtk.MESSAGE_QUESTION)
+		if res == gtk.RESPONSE_YES:
+			sys.exit(0)
 	
 
 	# Handlers for "intro" tile
@@ -230,19 +247,30 @@
 	def ndisks_on_next(self):
 		row, col = self["disktree"].get_cursor()
 		if row == None or type(row) != type((1,)):
-			self._show_message("You need to pick a drive onto which FreeBSD will be installed.", "User intervention required")
+			self._show_message("You need to pick a drive onto which FreeBSD will be installed.", 
+					"User intervention required")
 			return False
 		model = self["disktree"].get_model()
 		drive = model.get_value(model.get_iter(row), 0)
-		logging.info("ndisks.drive=%s" % drive)
+		size = model.get_value(model.get_iter(row), 2).split(" ")[0]
+		logging.info("ndisks.drive=%s, ndisks.size=%s" % (drive, size))
 		self.trackdata["drive"] = drive
+		self.trackdata["drive_size"] = int(size)
+		physmem = self.server.GetPhysMem()
+		if self.trackdata["drive_size"] < 2048+physmem:
+			self._show_message("The drive you want to install FreeBSD on (%s) is too small.\n"
+					"You will need at least %d MB of disk space to install FreeBSD and a selection of packages." % (self.trackdata["drive"], 2048+physmem),
+					"Drive too small")
+			return False
 		parts = self.server.GetDrivePartitions(drive)
 		if len(parts) == 0:
 			# The drive is not partitioned, so mark it for default configuration
 			self.trackdata["parts"] = None
 			logging.info("Drive %s is not partitioned" % drive)
-			self._set_next_tile("nfilesys")
+			self._set_next_tile("ndefaultfs")
 		else:
+			# The drive is partitioned, so it's either an upgrade or the user wants
+			# to install it in empty space.
 			self.trackdata["parts"] = parts
 			logging.info("Drive %s is partitioned" % drive)
 			self._set_next_tile("nparts")
@@ -266,7 +294,213 @@
 		return True
 
 
-os.chdir(os.path.split(sys.argv[0])[0]) # attempt to chdir into the directory where the script is located
+	def ndefaultfs_on_load(self):
+		self._load_label(self["label2"], "ndefaultfs.txt")
+		return True
+
+
+	def ndefaultfs_on_next(self):
+		"""
+		We'll calculate the default partition scheme here. The overall goal is to make
+		the following separate file systems:
+			/
+			swap
+			/usr/local
+			/var
+			/home
+		and a symlink from /usr/ports to /usr/local/ports.
+		This is a slight deviation from the way FreeBSD is usually partitioned, but I feel
+		that having the whole base system on the root partition is a good thing for a novice
+		user. The only thing not belonging here is the ports tree, which can get huge, so
+		we'll move it to /usr/local.
+		We'll also not use the traditional BSD layout of bsdlabels (a=root, b=swap), except
+		for the unfortunately special "c" label.
+		"""
+
+		if self["radio_ufs"].get_active():
+			self.trackdata["default_fs"] = "UFS+SU"
+		elif self["radio_ufsgj"].get_active():
+			self.trackdata["default_fs"] = "UFS+GJ"
+		elif self["radio_zfs"].get_active():
+			self.trackdata["default_fs"] = "ZFS"
+		elif self["radio_ext2"].get_active():
+			self.trackdata["default_fs"] = "Ext2"
+		else:
+			raise InstallerException, "Cannot determine what default fs the user wants"
+		fs = self.trackdata["default_fs"]
+		physmem = self.server.GetPhysMem()
+		# Do some sanity checking
+		if fs == "ZFS":
+			# Check for memory
+			if physmem < 1024:
+				self._show_message("The system on which you are installing FreeBSD has less than 1 GB of memory.\n"
+						"It's not recomended to use ZFS on systems with less then 1 GB of memory\n"
+						"because it can provoke a system crash in low memory situations."
+						"Proceed at your own risk.", "Not enough memory")
+		if fs == "UFS+GJ":
+			# gjournal is a specific beast because it needs 1 GB of additional space per file system.
+			# To avoid popular outrage, we'll use it only for /usr/local and /home, and
+			# silently fallback to UFS+SU for the rest. For the first approximation, assume we'll need
+			# around 2 GB for the FreeBSD base system + etcetera, two 1 GB gjournals, and a physmem-sized
+			# swap.
+			if self.trackdata["drive_size"] < 1024*4+physmem:
+				self._show_message("The drive you want to install FreeBSD on (%s) is too small to use with gjournal.\n"
+						"You will need at least 4 GB of disk space to use gjournal.", "Drive too small", p_type=gtk.MESSAGE_ERROR)
+				return False
+		if fs == "Ext2":
+			# Just warn the user
+			self._show_message("You have selected the Ext2 file system. This file system has NO DATA RELIABILITY FEATURES.\n"
+					"In case of unexpected system shutdown (e.g. a power outage, a system crash), you might not\n"
+					"find your data where you left it.", "Ext2 doesn't have data reliability features")
+
+		# Calculate the partitioning scheme
+		var_size = min(2048, int(self.trackdata["drive_size"] * 0.1))
+		usrlocal_size = min(10240, int(self.trackdata["drive_size"] * 0.3))
+
+		if fs in ("UFS+SU", "UFS+GJ", "Ext2"):
+			# "Normal" file systems, unix-like
+			if fs == "UFS+GJ" : # Don't use gjournal for all file systems
+				var_fs = "UFS+SU"
+			else:
+				var_fs = fs
+			parts = []
+			self.trackdata["new_parts"] = parts # a reference
+			parts.append({
+				"base" : self.trackdata["drive"],
+				"type" : "fdisk",
+				"size" : 512,
+				"name" : "%ss1" % self.trackdata["drive"],
+				"mount" : "/",
+				"fs"   : "UFS+SU"
+				})
+			parts.append({
+				"base" : self.trackdata["drive"],
+				"type" : "fdisk",
+				"size" : physmem,
+				"name" : "%ss2" % self.trackdata["drive"],
+				"mount" : "swap",
+				"fs"   : "swap"
+				})
+			parts.append({
+				"base" : self.trackdata["drive"],
+				"type" : "fdisk",
+				"size" : self.trackdata["drive_size"] - parts[0]["size"] - parts[1]["size"], # i.e. all the rest
+				"name" : "%ss3" % self.trackdata["drive"],
+				"mount" : None,
+				"fs"   : None
+				})
+			parts.append({
+				"base" : parts[2]["name"],
+				"type" : "bsdlabel",
+				"size" : var_size,
+				"name" : "%sa" % parts[2]["name"],
+				"mount" : "/var",
+				"fs"   : var_fs
+				})
+			parts.append({
+				"base" : parts[2]["name"],
+				"type" : "bsdlabel",
+				"size" : usrlocal_size,
+				"name" : "%sb" % parts[2]["name"],
+				"mount" : "/usr/local",
+				"fs"   : fs
+				})
+			parts.append({
+				"base" : parts[2]["name"],
+				"type" : "bsdlabel",
+				"size" : parts[2]["size"] - parts[3]["size"] - parts[4]["size"],
+				"name" : "%sd" % parts[2]["name"],
+				"mount" : "/home",
+				"fs"   : fs
+				})
+		elif fs == "ZFS":
+			parts = []
+			self.trackdata["new_parts"] = parts
+			# The root file system will be UFS, but all the rest we'll set to ZFS,
+			# including the swap. Since we'll boot from the root file system,
+			# we need to encapsulate ZFS in fdisk partition
+			parts.append({
+				"base" : self.trackdata["drive"],
+				"type" : "fdisk",
+				"size" : 512,
+				"name" : "%ss1" % self.trackdata["drive"],
+				"mount" : "/",
+				"fs"   : "UFS+SU"
+				})
+			parts.append({
+				"base" : self.trackdata["drive"],
+				"type" : "fdisk",
+				"size" : self.trackdata["drive_size"] - parts[0]["size"],
+				"name" : "%ss2" % self.trackdata["drive"],
+				"mount" : None,
+				"fs"   : None
+				})
+			parts.append({
+				"base" : parts[1]["name"],
+				"type" : "zpool",
+				"size" : parts[1]["size"],
+				"name" : "FreeBSD",
+				"mount" : None,
+				"fs"   : None
+				})
+			parts.append({
+				"base" : parts[2]["name"],
+				"type" : "zvol",
+				"size" : physmem,
+				"name" : "swap",
+				"mount" : "swap",
+				"fs"   : "swap"
+				})
+			parts.append({
+				"base" : parts[2]["name"],
+				"type" : "zfs",
+				"size" : var_size,
+				"name" : "%s/var" % parts[2]["name"],
+				"mount" : "/var",
+				"fs"   : "ZFS"
+				})
+			parts.append({
+				"base" : parts[2]["name"],
+				"type" : "zfs",
+				"size" : usrlocal_size,
+				"name" : "%s/usrlocal" % parts[2]["name"],
+				"mount" : "/usr/local",
+				"fs"   : "ZFS"
+				})
+			parts.append({
+				"base" : parts[2]["name"],
+				"type" : "zfs",
+				"size" : None,
+				"name" : "%s/home" % parts[2]["name"],
+				"mount" : "/home",
+				"fs"   : "ZFS"
+				})
+
+		return True
+
+
+	def nverify_on_load(self):
+		self._load_label(self["label2"], "nverify.txt")
+		txt = self._get_text("nverify_template.txt")
+		txt = txt.replace("{$drive}", self.trackdata["drive"])
+		txt = txt.replace("{$drive_size}", str(self.trackdata["drive_size"]))
+		txt = txt.replace("{$default_fs}", self.trackdata["default_fs"])
+
+		parts_txt = ""
+		for part in self.trackdata["new_parts"]:
+			parts_txt += "\tName: <b>%s</b>\n\tSize: %d MB\n\tMount point: <b>%s</b>\n\tFile system: %s\n\n" % (part["name"], part["size"], part["mount"], part["fs"])
+		txt = txt.replace("{$new_parts}", parts_txt)
+
+		self._set_label(self["verifytext"], txt)
+		return True
+
+
+
+
+my_dir = os.path.split(sys.argv[0])[0]
+if my_dir != "":
+	# attempt to chdir into the directory where the script is located
+	os.chdir(my_dir) 
 
 logging.basicConfig(level=logging.DEBUG)
 w = MainWin()

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


==== //depot/projects/soc2007/ivoras_finstall/installer/glade/mainwin.glade#9 (text+ko) ====

@@ -65,7 +65,7 @@
                         <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                         <property name="xalign">0</property>
                         <property name="yalign">0</property>
-                        <property name="label" translatable="yes">This installer application will guide you through FreeBSD's install  and setup process. FreeBSD is a popular open source operating system, the result of volundeer work of hundreds of individuals...
+                        <property name="label" translatable="yes">This installer application will guide you through FreeBSD's install  and setup process. FreeBSD is a popular open source operating system, the result of volunteer work of hundreds of individuals...
 </property>
                         <property name="use_markup">True</property>
                         <property name="wrap">True</property>
@@ -99,6 +99,7 @@
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                             <property name="border_width">6</property>
                             <property name="label" translatable="yes">Novice</property>
+                            <property name="response_id">0</property>
                             <property name="active">True</property>
                             <property name="draw_indicator">True</property>
                           </widget>
@@ -113,6 +114,7 @@
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                             <property name="border_width">6</property>
                             <property name="label" translatable="yes">Standard</property>
+                            <property name="response_id">0</property>
                             <property name="active">True</property>
                             <property name="draw_indicator">True</property>
                             <property name="group">radiobutton1</property>
@@ -129,6 +131,7 @@
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                             <property name="border_width">6</property>
                             <property name="label" translatable="yes">Expert</property>
+                            <property name="response_id">0</property>
                             <property name="active">True</property>
                             <property name="draw_indicator">True</property>
                             <property name="group">radiobutton1</property>
@@ -171,6 +174,7 @@
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <property name="label" translatable="yes">gtk-help</property>
                     <property name="use_stock">True</property>
+                    <property name="response_id">0</property>
                     <signal name="clicked" handler="on_button_help_clicked"/>
                   </widget>
                 </child>
@@ -181,6 +185,8 @@
                     <property name="can_default">True</property>
                     <property name="label">gtk-cancel</property>
                     <property name="use_stock">True</property>
+                    <property name="response_id">0</property>
+                    <signal name="clicked" handler="on_button_cancel_clicked"/>
                   </widget>
                   <packing>
                     <property name="position">1</property>
@@ -193,6 +199,7 @@
                     <property name="can_default">True</property>
                     <property name="label">gtk-media-previous</property>
                     <property name="use_stock">True</property>
+                    <property name="response_id">0</property>
                     <signal name="clicked" handler="on_button_previous_clicked"/>
                   </widget>
                   <packing>
@@ -206,6 +213,7 @@
                     <property name="can_default">True</property>
                     <property name="label">gtk-media-next</property>
                     <property name="use_stock">True</property>
+                    <property name="response_id">0</property>
                     <signal name="clicked" handler="on_button_next_clicked"/>
                   </widget>
                   <packing>

==== //depot/projects/soc2007/ivoras_finstall/installer/glade/ndisks.glade#4 (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.0 on Thu Jun  7 20:57:58 2007 by ivoras at finstall.cosmos-->
+<!--Generated with glade3 3.2.2 on Sun Aug 12 12:14:18 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>
@@ -47,7 +47,6 @@
                 <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="border_width">2</property>
                 <property name="headers_clickable">True</property>
               </widget>
               <packing>
@@ -55,9 +54,6 @@
                 <property name="position">2</property>
               </packing>
             </child>
-            <child>
-              <placeholder/>
-            </child>
           </widget>
         </child>
       </widget>

==== //depot/projects/soc2007/ivoras_finstall/installer/helpdialog.py#3 (text+ko) ====


==== //depot/projects/soc2007/ivoras_finstall/installer/text/intro.txt#4 (text+ko) ====

@@ -1,6 +1,7 @@
 <b>Welcome to FreeBSD</b>, a free and Open source operating system that is the
 result of hundreds of volunteers worldwide. FreeBSD is modern and high-performance
-operating system that aims to do everything...
-<br><br>
-FreeBSD is licensed under the famous <i>BSD license</i> as presented on TV...
-<br>
+Unix-like operating system that can be used for various tasks, from network servers
+to desktop systems.
+
+FreeBSD is Copyright (c) 2007., The FreeBSD Project, all rights reserved.
+FreeBSD is distributed under the 2-clause BSD license.

==== //depot/projects/soc2007/ivoras_finstall/installer/text/ndisks.txt#2 (text+ko) ====

@@ -1,4 +1,3 @@
 The first step to installing <b>FreeBSD</b> on your computer is choosing
 storage space for it on your hard drive. In the following table
 you'll need to select a hard drive to contain <b>FreeBSD</b>.
-

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

@@ -22,6 +22,7 @@
 # Interface to (most) FreeBSD's low-level utilities
 
 import os, sys
+import re
 import xmldict
 
 cmd_sysctl = "/sbin/sysctl"
@@ -32,10 +33,14 @@
 file_dmesg = "/var/run/dmesg.boot"
 
 
-def get_sysctl(name):
+def get_sysctl(name, b_flag = False):
 	global cmd_sysctl
-	str = os.popen("%s -b %s" % (cmd_sysctl, name)).read().strip()
-	while str[-1] == "\0":
+	if b_flag:
+		str = os.popen("%s -b %s" % (cmd_sysctl, name)).read().strip()
+	else:
+		str = os.popen("%s %s" % (cmd_sysctl, name)).read().strip()
+		str = str.split(": ")[1]
+	while len(str) > 0 and str[-1] == "\0":
 		str = str[:-1]
 	return str
 
@@ -50,7 +55,7 @@
 
 
 def get_geom_xml():
-	return xmldict.buildxmldict(get_sysctl("kern.geom.confxml"))
+	return xmldict.buildxmldict(get_sysctl("kern.geom.confxml", True))
 
 
 def guess_fs_type(dev):
@@ -73,13 +78,26 @@
 		return "XFS"
 	elif guess.find("ReiserFS") != -1:
 		return "ReiserFS"
-	elif guess.find("Unix Fast File system v2") != -1:
+	elif guess.find("Unix Fast File system [v2]") != -1:
 		return "UFS2"
 	elif guess.find("Unix Fast File system") != -1:
 		return "UFS"
 	return "(unknown)"
 
 
+def guess_fs_last_mount(dev, fs_type="UFS"):
+	global cmd_file
+	if not fs_type in ("UFS2", "UFS"): # For now, we only know how to handle UFS
+		return None
+	if not dev.startswith("/dev/"):
+		dev = "/dev/%s" % dev
+	guess = get_cmd_output("%s %s" % (cmd_file, dev))
+	m = re.search("last mounted on (.+),", guess)
+	if m == None:
+		return None
+	return m.group(1)
+
+
 if __name__ == "__main__":
 	xml = get_geom_xml()
 	for cls in xml["mesh"]["class"]:

==== //depot/projects/soc2007/ivoras_finstall/pybackend/systoold.py#6 (text+ko) ====

@@ -72,7 +72,7 @@
 
 engine = SysToolEngine()
 
-server = SimpleXMLRPCServer((bind_host, bind_port), SimpleXMLRPCRequestHandler, globals.debug_level > 0)
+server = SimpleXMLRPCServer((bind_host, bind_port), SimpleXMLRPCRequestHandler, globals.debug_level > 0, allow_none=True)
 server.register_introspection_functions()
 server.register_function(ToUpper)
 server.register_instance(engine)

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

@@ -113,7 +113,7 @@
 					"mediasize": 300000  # (MB)
 				}
 		}"""
-		drive_list = freebsd.get_sysctl("kern.disks").split(" ")
+		drive_list = freebsd.get_sysctl("kern.disks", True).split(" ")
 		dmesg = freebsd.get_dmesg()
 		drive_dict = {}
 		for drive in drive_list:
@@ -155,14 +155,16 @@
 		RETURN VALUE:
 		The return value is a dictionary whose keys are partition names
 		and values are dictionaries containing keys:
-			name, mediasize, sectorsize, type
+			name, mediasize, sectorsize, type, fs_type, fs_last_mount
 		For example:
 		{
 			"ad0s1a" : {
 				"name" : "ad0s1a",
 				"mediasize" : 100000, # MB
 				"sectorsize" : 512,
-				"type" : "BSD"
+				"type" : "BSD",
+				"fs_type" : "UFS2",
+				"fs_last_mount", "/usr"
 				}
 		}"""
 		parts = {}
@@ -193,7 +195,7 @@
 						if num_msdos_parts != 0:
 							logging.error("The impossible has happened: drive has both MSDOS and BSD partitions directly on it")
 							continue
-						for prov in tolist(gerom["provider"]):
+						for prov in tolist(geom["provider"]):
 							part = {
 								"name" : prov["name"].data,
 								"mediasize" : int(prov["mediasize"].data) / (1024*1024),
@@ -219,12 +221,11 @@
 		# Try to divine file system types for the partitions
 		for part in parts:
 			parts[part]["fs_type"] = freebsd.guess_fs_type(part)
+			parts[part]["fs_last_mount"] = freebsd.guess_fs_last_mount(part, parts[part]["fs_type"])
 
 		return parts
 
 
-
-
 	def GetMountPoints(self):
 		"""Returns a list of dictionaries containing information
 		about currently mounted file systems"""
@@ -243,5 +244,9 @@
 		return False
 
 
-
+	@logexception
+	def GetPhysMem(self):
+		"""Returns the amount of physical memory in the machine, in MB"""
+		physmem = int(freebsd.get_sysctl("hw.realmem"))
+		return int(physmem / (1024*1024))
 

==== //depot/projects/soc2007/ivoras_finstall/pybackend/xmldict.py#5 (text+ko) ====

@@ -317,7 +317,11 @@
     print d['clock']
     for tick in d['clock']['tick']: # d['clock']['tick'] is a list of <tick> tags
         print tick
-
+    if not 'clock' in d:
+        print "** no clock in d"
+    if not 'tick' in d['clock']:
+        print "** no tick in clock"
+ 
     xml = "<abcd><![CDATA[content]]><![CDATA[ more content]]></abcd>"
     d = buildxmldict(xml)
     print d["abcd"]


More information about the p4-projects mailing list