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,
 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
 but since there are very few messages, it is not worth the trouble to configure
 a real message queue such as RabbitMQ.
 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]);
+}
+
+?>