weidner/archives/2012/01/

Read-Write/Read-Only mit LuCI

OpenWrt ist als Linux-Distribution nicht nur für Router, sondern auch für ALIX-Rechner sehr gut geeignet. Insbesondere das Webinterface macht die Bedienung für denjenigen, der die Kommandozeile eher scheut, akzeptabel. Im Gegensatz zu einigen Routern, die mit OpenWrt betrieben werden können und spezielle Dateisysteme benötigen, die direkt mit den verbauten Flash-Speichern umgehen können, kann ich bei den ALIX-Rechnern das ext2 Dateisystem einsetzen, da die verwendeten CompactFlash-Karten einen eigenen Controller mitbringen. Diese haben gegenüber der Kombination SquashFS und JFFS2 sogar den Vorteil, dass der Paketmanager opkg weiss, wieviel Platz noch verfügbar ist.

Einen kleinen Haken hat die Angelegenheit aber doch: Per Default wird in OpenWrt das ext2 Dateisystem nicht read-only eingebunden und dementsprechend kann ich den Rechner nicht einfach ausschalten, ohne zu riskieren, dass er beim nächsten Start auf einen Dateisystem-Check wartet.

Dem kann ich glücklicherweise mit der folgenden Zeile in der Datei /etc/rc.local abhelfen:

mount -o remount,ro /

Damit hängt er die Root-Partition nach dem Neustart read-only ein. Um die Konfiguration zu ändern, Software zu aktualisieren oder zu installieren, lege ich zwei Scripts namens remountro und remountrw im Verzeichnis /sbin/ an, die obigen Text enthalten beziehungsweise diesen:

mount -o remount,rw,noatime /

Damit kann ich das System nun wie folgt auf der Kommandozeile administrieren:

# remountrw
# opkg update
# opkg list-upgradable
...
# remountro

Natürlich darf ich nicht vergessen, nach einer Administrationssitzung das Dateisystem wieder read-only einzuhängen.

Damit habe ich eine Lösung für die Kommandozeile. So etwas ähnliches möchte ich nun auch im Webinterface LuCI haben. Hier half mir ein Artikel in der Computerzeitschrift c't [1], in dem beschrieben wird, wie man das Webinterface LuCI erweitern kann. Mit Hilfe dieses Artikels habe ich eine Steuerdatei und ein Template für die Ausgabe geschrieben, mit denen ich aus dem Webinterface heraus, das Root-Dateisystem read-only oder read-write einhängen kann.

Die Steuerdatei /usr/lib/lua/luci/controller/remount.lua:

module("luci.controller.remount", package.seeall)
function index()
  local page = node("remount")
  page.sysauth = "root"
  page.sysauth_authenticator = "htmlauth"
  entry({"remount"}, template("remount"), "Remount")
  entry({"remount", "readonly"}, call("readonly"))
  entry({"remount", "readwrite"}, call("readwrite"))
end
function readwrite()
  luci.sys.exec("mount -o remount,rw,noatime /")
  luci.http.redirect(luci.dispatcher.build_url("remount"))
end
function readonly()
  luci.sys.exec("mount -o remount,ro /")
  luci.http.redirect(luci.dispatcher.build_url("remount"))
end
function mounted()
  local data = ""
  local partitions = luci.util.execi("mount")

  if not partitions then
      return "failure with mount command"
  end
  for line in partitions do
    if string.match(line,"^/.+%s/%s.+") then
       data = data .. line .. "\n"
    end
  end
  return data
end

Diese Datei registriert in der Funktion index() eine URL beim Dispatcher. Ausserdem stellt sie die Funktionen readonly(), readwrite() und mounted() bereit. Die ersten beiden hängen das Dateisystem um, die dritte fischt aus der Ausgabe von mount die Zeile mit dem Root-Dateisystem, um den momentanen Zustand anzuzeigen.

Ansicht mit read-only Dateisystem

Das Template /usr/lib/lua/luci/view/remount.htm:

<%+header%>
<h1><%:Remount%></h1>
<p>&nbsp;</p><br />
<% mounted = luci.controller.remount.mounted() %>
<pre>
<%=mounted%>
</pre>
<form name="readwrite" id="readwrite" action="<%=controller%>/remount/readwrite" target ="_self" style="display:inline">
<input type="submit" value="read-write" />
</form>
<form name="readonly" id="readonly" action="<%=controller%>/remount/readonly" target ="_self" style="display:inline">
<input type="submit" value="read-only" />
</form>
<%+footer%>

Dieses gibt den Rückgabewert der Funktion mounted() aus und bietet zwei Formularknöpfe, über die man die Funktionen readonly() beziehungsweise readwrite() aufrufen kann.

Ansicht mit read-write Dateisystem

Natürlich darf ich auch hier nicht vergessen, nach einer Administrationssitzung das Dateisystem wieder read-only einzuhängen.

[1] Mikolas Bingemer, Ab geht die LuCI, Das Webfrontend der Router-Firmware OpenWrt erweitern, c't 24/08 S. 268ff (Softlink mit Programmbeispielen: http://www.ct.de/0824268)

Posted 2012-01-13
Tags: