Browse Source

Add scripts and instructions to upgrade from the PHP version of celutz

Baptiste Jonglez 9 years ago
parent
commit
b515b56011

+ 6 - 0
INSTALL.md

@@ -59,3 +59,9 @@ The default parameters use the Django database as a message queue, to ask
 a celery woker to generate tiles for a panorama.  This is far from efficient,
 but since there are very few messages, it is not worth the trouble to configure
 a real message queue such as RabbitMQ.
+
+Upgrading from the PHP version of celutz
+----------------------------------------
+
+Where you previously using the PHP version of celutz?  You can import all your
+old data!  See `UPGRADE.md`.

+ 86 - 0
UPGRADE.md

@@ -0,0 +1,86 @@
+Upgrading from celutz 1.0
+=========================
+
+Here are some instructions to migrate from celutz 1.0 (PHP version)
+to the new Django version.  All data will be migrated: panorama images,
+panorama meta-data, reference points, and "references" (calibration of a
+panorama using several reference points).  Tiles will not be migrated,
+since they can easily be regenerated.
+
+Pre-requisite
+-------------
+
+These instructions assume that the old PHP version and the new Django version
+are installed on distinct machines ("old server" and "new server" respectively).
+Of course, they can actually be the same machine.
+
+You need:
+
+- access to the files of the old celutz instance (no need to be able to run
+  the code itself);
+
+- ability to run simple command-line PHP5 scripts (no dependencies) on the old
+  server;
+
+- the Django version of celutz is installed and configured on the new server;
+
+- the Django database is up-to-date with respect to migrations, but empty
+  (no panorama or reference point);
+
+- enough disk space to store panorama and tiles on the new server.
+
+
+Export data from the old server
+-------------------------------
+
+There are three PHP scripts that export the relevant data to JSON: information
+about panoramas, reference points, and references.
+
+    # Export panoramas
+    php upgrade/export_panorama.php /path/to/old/celutz | tee panoramas.json
+    # Export one or more set of reference points
+    php upgrade/export_refpoints.php /path/to/old/celutz/ref_points/my_ref_points.php | tee refpoints.json
+    # Export references
+    php upgrade/export_references.php /path/to/old/celutz | tee references.json
+
+Besides these three JSON files, you also need to copy panorama images
+(everything in `upload/`).
+You don't need to copy the tiles.
+
+Import data on the new server
+-----------------------------
+
+First copy all panorama images to `media/pano/` (create it if necessary).
+
+**Warning**: for the next step, make sure the Django database is empty!
+That is, if you already have panorama or reference points, they will likely
+be overriden by the import (and the database might end up in an inconsistent 
+state).
+
+    # Enter virtualenv if necessary
+    # Import panoramas
+    python manage.py loaddata panoramas.json
+    # Then import reference points
+    python manage.py loaddata refpoints.json
+    # For importing references, a more complex conversion is needed
+    python manage.py import_references references.json
+
+If all commands run without error, you're probably all good.  If the first
+import command complains about missing images, make sure they are available
+in the `media/pano/` directory, under the expected file name.
+
+The final step is to fix the name of reference points, because characters
+such as "'" are known to cause issue in the frontend code:
+
+    # Remove special characters from reference point names
+    python manage.py fix_refpoints_name
+
+Regenerate all tiles
+--------------------
+
+Simply connect to the Django admin at <http://www.example.com/admin/panorama/panorama/>,
+tick all panorama, and choose "Regenerate tiles for the selected panoramas"
+in the dropdown list of actions.
+
+This will take a few minutes to complete, you can follow the progress by
+reloading the admin page (look at the "Has tiles" column).

+ 0 - 0
panorama/management/__init__.py


+ 0 - 0
panorama/management/commands/__init__.py


+ 21 - 0
panorama/management/commands/fix_refpoints_name.py

@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import unicode_literals, division, print_function
+
+from django.core.management.base import BaseCommand
+
+from panorama.models import ReferencePoint
+
+
+class Command(BaseCommand):
+    help = 'Fix name of reference points, to avoid special characters'
+    
+    def handle(self, *args, **options):
+        nb_fixed = 0
+        for refpoint in ReferencePoint.objects.all():
+            if "'" in refpoint.name:
+                self.stdout.write("Fixing refpoint name: {}".format(refpoint.name))
+                refpoint.name = refpoint.name.replace("'", " ")
+                refpoint.save()
+                nb_fixed += 1
+        self.stdout.write("Fixed {} reference point names".format(nb_fixed))

+ 26 - 0
panorama/management/commands/import_references.py

@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import unicode_literals, division, print_function
+
+import json
+
+from django.core.management.base import BaseCommand, CommandError
+
+from panorama.models import Panorama, ReferencePoint, Reference
+
+
+class Command(BaseCommand):
+    args = '<references.json>'
+    help = 'Convert and import references exported from the old PHP-based celutz'
+    
+    def handle(self, *args, **options):
+        if len(args) < 1:
+            raise CommandError('Usage: import_references <references.json>')
+        with open(args[0]) as f:
+            for ref in json.load(f):
+                pano = Panorama.objects.get(name=ref["pano"])
+                refpoint = ReferencePoint.objects.get(name=ref["refpoint"])
+                x = int(ref["x"] * pano.image_width)
+                y = int((ref["y"] + 0.5) * pano.image_height)
+                r = Reference(reference_point=refpoint, panorama=pano, x=x, y=y)
+                r.save()

+ 56 - 0
upgrade/export_panoramas.php

@@ -0,0 +1,56 @@
+<?php
+
+/* Converts a panorama to a dictionary with all parameters. */
+/* Given "foo.tif", fetch parameters from "tiles/foo/site.params" */
+function load_panorama($image_name) {
+    $components = pathinfo($image_name);
+    $celutz_dir = pathinfo($components["dirname"])["dirname"];
+    $params_file = join("/", array($celutz_dir, "tiles", $components["filename"], "site.params"));
+    $params = parse_ini_file($params_file);
+    if (! $params)
+        return false;
+    $result = array();
+    $result["loop"] = (boolean) $params["image_loop"];
+    $result["name"] = $params["titre"];
+    // Relative to Django's MEDIAROOT
+    $result["image"] = "pano/" . $components["basename"];
+    $result["latitude"] = (float) $params["latitude"];
+    $result["longitude"] = (float) $params["longitude"];
+    $result["altitude"] = (float) $params["altitude"];
+    return $result;
+}
+
+/* Convert all panoramas images found in the given directory to JSON */
+function convert_panoramas($upload_dir) {
+    /* The Django model uses inheritance, so we need to create both the
+     * panorama and the associated reference point, with the same ID. */
+    $panoramas = array();
+    $refpoints = array();
+    $id = 1;
+    foreach (scandir($upload_dir) as $pano) {
+        if ($pano == "." || $pano == "..")
+            continue;
+        $params = load_panorama($upload_dir . "/" . $pano);
+        if (! $params)
+            continue;
+        $p = array("pk" => $id, "model" => "panorama.panorama");
+        $r = array("pk" => $id, "model" => "panorama.referencepoint");
+        $p["fields"] = array("loop" => $params["loop"], "image" => $params["image"]);
+        $r["fields"] = array("name" => $params["name"],
+                             "latitude" => $params["latitude"],
+                             "longitude" => $params["longitude"],
+                             "altitude" => $params["altitude"]);
+        $panoramas[] = $p;
+        $refpoints[] = $r;
+        $id++;
+    }
+    return json_encode(array_merge($panoramas, $refpoints), JSON_PRETTY_PRINT);
+}
+
+if (isset($argv[1])) {
+    print(convert_panoramas($argv[1] . "/upload"));
+} else {
+    printf("Usage: %s /path/to/celutz\n", $argv[0]);
+}
+
+?>

+ 43 - 0
upgrade/export_references.php

@@ -0,0 +1,43 @@
+<?php
+
+/* Loads all references for the given panorama into a dictionary */
+function load_references($image_name) {
+    $components = pathinfo($image_name);
+    $celutz_dir = pathinfo($components["dirname"])["dirname"];
+    $params_file = join("/", array($celutz_dir, "tiles", $components["filename"], "site.params"));
+    $params = parse_ini_file($params_file);
+    if (! $params)
+        return false;
+    $res = array();
+    if (! isset($params["reference"]))
+        return $res;
+    foreach ($params["reference"] as $name => $position) {
+        $pos = explode(",", $position);
+        $res[] = array("pano" => $params["titre"],
+                       "refpoint" => $name,
+                       "x" => (float) $pos[0],
+                       "y" => (float) $pos[1]);
+    }
+    return $res;
+}
+
+function convert_references($upload_dir) {
+    $result = array();
+    foreach (scandir($upload_dir) as $pano) {
+        if ($pano == "." || $pano == "..")
+            continue;
+        $references = load_references($upload_dir . "/" . $pano);
+        if (! $references)
+            continue;
+        $result = array_merge($result, $references);
+    }
+    return json_encode($result, JSON_PRETTY_PRINT);
+}
+
+if (isset($argv[1])) {
+    print(convert_references($argv[1] . "/upload"));
+} else {
+    printf("Usage: %s /path/to/celutz\n", $argv[0]);
+}
+
+?>

+ 36 - 0
upgrade/export_refpoints.php

@@ -0,0 +1,36 @@
+<?php
+
+/* Converts a set of refpoints to a JSON file suitable for Django import. */
+
+/* Pass one or several refpoint PHP files as arguments. */
+
+function convert_refpoints($refpoint_file) {
+    $ref_points = array();
+    include($refpoint_file);
+    $result = array();
+    foreach ($ref_points as $name => $attributes) {
+        $item = array("model" => "panorama.referencepoint");
+        $item["fields"] = array("name" => $name,
+                                "latitude" => $attributes[0],
+                                "longitude" => $attributes[1],
+                                "altitude" => $attributes[2]);
+        $result[] = $item;
+    }
+    return $result;
+}
+
+function convert_all_refpoints($argv) {
+    $all_refpoints = array();
+    foreach (array_slice($argv, 1) as $refpoint_file) {
+        $all_refpoints = array_merge($all_refpoints, convert_refpoints($refpoint_file));
+    }
+    print(json_encode($all_refpoints, JSON_PRETTY_PRINT));
+}
+
+if (isset($argv[1])) {
+    convert_all_refpoints($argv);
+} else {
+    printf("Usage: %s <ref_points_1.php> [ref_points_2.php [...]]\n", $argv[0]);
+}
+
+?>