Snapshot Backups der virtuellen Maschinen

Nach dem letzten Crash bin ich dazu übergegangen die virtuellen Maschinen jede Nacht per lvm-snapshot mit lzop komprimiert zu sichern. Eine separat eingebaute Festplatte (/mnt/backup) hält diese backups. Das ultra-kurze Skript dazu sieht so aus:

#!/bin/bash
LVMS="snowhow komplett root"
VG=vg0
BUP_DST=/mnt/backup/snapshot_vms
NICE=15
VERBOSE=0
## cron needs full path to commands
LVCR=/sbin/lvcreate
LVRM=/sbin/lvremove
LVS=/sbin/lvs
VIRSH=/usr/bin/virsh
while getopts ":vl:" opt; do
  case $opt in
    v)
      VERBOSE=1
      ;;
    l)
      LVMS=$OPTARG
      ;;
  esac
done
function doBackup {
  logger -t SNAPSHOT_BACKUP "starting backup for $LV"
  if [ -f $BUP_DST/$LV-snap.lzo ]
  then
    mv $BUP_DST/$LV-snap.lzo $BUP_DST/$LV-snap.lzo.old
  fi
  $VIRSH suspend $LV
  $LVCR -L1G -s -n $LV-snap /dev/$VG/$LV
  $VIRSH resume $LV
  if [ $VERBOSE -eq 1 ]
  then
    $LVS
    SIZE=$($LVS --nosuffix --units b -o lv_size --rows --separator ':' /dev/$VG/$LV | cut -d':' -f2)
    echo $SIZE
    nice -n $NICE bash -c "dd if=/dev/$VG/$LV-snap bs=4M | pv -s $SIZE | lzop -c | dd of=$BUP_DST/$LV-snap.lzo bs=4M"
    $LVS
  else
    nice -n 15 bash -c "dd if=/dev/$VG/$LV-snap bs=4M | lzop -c | dd of=$BUP_DST/$LV-snap.lzo bs=4M"
  fi
  $LVRM -f /dev/$VG/$LV-snap
  logger -t SNAPSHOT_BACKUP "done backup for $LV"
}
for i in $LVMS
do
  LV=$i
  doBackup
done

Die Parameter funktionieren folgendermaßen: Wird der -l switch angegeben, so werden die default Logical Volumes snowhow komplett root überschrieben. Mit -v gibt es eine graphische Ausgabe des Fortschritts. Damit die VM im suspend Modus gesichert werden kann, muss die KVM Instanz den gleichen Namen haben wie das LV auf dem sie liegt.

Natürlich läuft auch ein konventionelles backup um einzelne Files wiederherzustellen, aber sicher ist sicher.

Mapnik tiles für einen Ausschnitt neu erzeugen

Unsere Basiskarte wird laufend um Informationen ergänzt (zum Beispiel ein Shapefile mit Skipisten). Nach einer solchen Ergänzung soll nicht der gesamte Karten-Cache (mod_tile/renderd) neu gerechnet werden, sondern nur der Ausschnitt in dem Veränderungen stattgefunden haben.

Lösung

Drei Schritte um die Kartenkacheln neu zu erzeugen:

Extent des Shapefiles ermitteln

ogrinfo -geom=SUMMARY pp.shp pp
...
Extent: (11.015149, 46.848712) - (11.085476, 46.911385)
...

Liste der Tiles für diesen Ausschnitt erzeugen

Die maximale Zoomstufe meiner Karte ist 17. Jetzt nur noch die Bounding Box des Shapefiles angeben und die gewünschte Ausgabe (nach grep und awk) in eine Datei umleiten.

./globalmaptiles.py 17 46.848712 11.015149 46.911385 11.085476 | grep __Goo | awk '{print $1}' > /tmp/expired.lst

Das globalmaptiles.py Script wurde ge-patched um die gewünschten „Google“-Coordinaten einfach auszulesen

--- globalmaptiles.py.orig	2014-02-06 00:36:01.021060820 +0100
+++ globalmaptiles.py	2014-02-06 00:15:42.459082600 +0100
@@ -427,7 +427,7 @@
 			print tilefilename, "( TileMapService: z / x / y )"
 		
 			gx, gy = mercator.GoogleTile(tx, ty, tz)
-			print "tGoogle:", gx, gy
+			print "%s/%s/%s __Google__" % (tz, gx, gy)
 			quadkey = mercator.QuadTree(tx, ty, tz)
 			print "tQuadkey:", quadkey, '(',int(quadkey, 4),')'
 			bounds = mercator.TileBounds( tx, ty, tz)

render_expired mit der Liste der Tiles aufrufen

Abschließend wird das Programm render_expired mit der generierten Liste der Tiles aufgerufen. Um die unteren Zoomstufen kümmert sich das Script selbst.

render_expired -m snowhow -s /var/run/renderd/renderd.sock < /tmp/expired.lst

obergurgl_blog_rerender

HTTP requests aus Javascript auf der Entwicklermaschine

Ein Problem, das vermutlich mehrere Entwickler haben, die in einer Web-Applikation mit Javascript auf ein backend zugreifen: Entwicklet wird auf der lokalen Maschine, das backend liegt (zum Entwickeln) auf einem anderen Server.

Browser lassen HTTP-Requests in Javascript von http://localhost/ auf eine andere Domain nicht zu (hier gilt die same origin policy). Auf den Seiten des Mozilla Developer Network wird sehr übersichtlich erklärt, wie man diese Einschränkung sicher umgehen kann. Da wir im content der requests json verschicken müssten unsere Zugriffe recht aufwändig als preflighted requests behandelt werden.

Bisher verwendeten wir zur Umgehung dieses Problems google-chrome mit dem Command-line switch --disable-web-security. Etwas unschön und vor allem konnten wir mit Firefox erst testen, nachdem der Code am Entwicklungsserver deployed war.

Mit wenigen Zeilen in der lokalen apache Konfiguration ist das Problem auch vom Tisch: Man richtet einen lokalen Proxy ein, der die ajax-requests an den Server weitergibt:

  <IfModule mod_proxy.c>
    ## mod_proxy for ajax CORS troubles
    ProxyPassMatch ^/(.*/specimen/.*)$ http://server.tld/$1
    ProxyPassMatch ^/(.*/j_spring_security_logout)$ http://server.tld/$1
    ProxyPassMatch ^/(.*/j_spring_security_check)$ http://server.tld/$1
  </IfModule>

Ist das apache-Modul mod_proxy aktiviert (a2enmod mod_proxy), werden alle requests die in der Adresse den Pfad /specimen/ enthalten zu server.tld umgeleitet. Gleiches gilt für die security-checks.