Homepage > FAQ Programmazione , Sviluppo Software > Migrazione Blobstore GAE a un'applicazione HRD

Migrazione Blobstore GAE a un'applicazione HRD

Google App Engine Se avete intenzione di migrare l'applicazione Google App Engine allo schema "nuovo" High database di replica, allora probabilmente sapete che il processo di migrazione Google non sarà di gestire i file Blobstore.

Qui troverete alcuni script python che vi aiuteranno a spostare i file Blobstore dall'applicazione vecchio a quello nuovo, e correggere tutti i riferimenti nel nuovo database. Come sempre, usatela a vostro rischio e pericolo, non provare a fare qualcosa senza leggere e comprendere gli script, altrimenti si rischia di perdere i vostri dati in modo permanente.

Alcune considerazioni:

  • Abbiamo fatto questi script utilizzato nella nostra applicazione molto personale, quindi posso dire che funziona. Tuttavia, ho dovuto modificare gli script originali per renderli più "generico", rimuovere i miei riferimenti e nomi di database, ecc
  • Cercherò di descrivere le fasi della migrazione, ma per favore non cercare di fare nulla prima di leggere l'intero articolo prima.
  • Ciò non è in alcun modo destinati ad essere una migrazione completamente automatico, infatti, i passaggi deve essere eseguita manualmente uno per uno.
  • Gli script non migra file di grandi dimensioni. Abbiamo migrato i file fino a 40MB senza problemi, ma se hai file più grandi di questo, probabilmente fallirà. Per esempio abbiamo provato un file di 300Mb senza successo, il motivo è che il file deve essere scaricato dal app vecchio al nuovo, e c'è un timeout di 1 minuto per le richieste di app, quindi se il download richiede più che fallirà .
Come funziona lo script funziona

Avrete bisogno di mettere lo script nelle applicazioni, sia il nuovo (HRD) e quello vecchio. Espone sostanzialmente quattro gli URL e sarà necessario accedere a due di loro dall'applicazione HRD.
In questo modo potrete scaricare tutti i file blob dall'applicazione vecchio al nuovo, lo script creerà un modello che mantiene una mappa tra i riferimenti vecchi e nuovi.
Il passo finale è quello di migrare i vecchi riferimenti al nuovo sviluppo delle risorse umane nelle banche dati.

Prerequisiti
  • Tutti i riferimenti ai file blob nei tuoi modelli devono essere di tipo blobstore.BlobReferenceProperty , se non sarà necessario modificare in primo luogo.
  • Migrare i database dal vecchio al app app nuovo sviluppo delle risorse umane utilizzando il metodo standard di migrazione Google .
Passi
  • Aggiungere l'URL alla vostra applicazione
def main():
    application = webapp.WSGIApplication(
          [
           # ... Your app URLs here ...
           # TODO - REMOVE THIS AFTER MIGRATION
           ('/mig/__getblob/(.+)', GetBlob),
           ('/mig/__getblobkeys/?', GetBlobKeys),
           ('/mig/__migrateblobs/?', MigrateBlobs),
           ('/mig/__migratereferences/?', MigrateBlobReferences),
          ], debug=True)
    run_wsgi_app(application)

if __name__ == '__main__':
  main()
  • Quindi aggiungere il codice di migrazione
####
# TEMPORARY BLOBSTORE MIGRATION CODE
####

MODELS = (
    # add your (model, blobinfo_field_name) tuples here
    ("myModel1", "blobinfofield"),
    ("myModel2", "BlobInfo"),
)

class mig_BlobMig(db.Model):
    fname = db.StringProperty()
    blobinfo = blobstore.BlobReferenceProperty()
    origkey = db.StringProperty()

class MigrateBlobReferences(blobstore_handlers.BlobstoreDownloadHandler):
    '''Migrate blob info references'''
    def get(self):
        import models
        tb = dict([(str(blob.origkey), blob.blobinfo) for blob in mig_BlobMig.all()])
        for modelname, field in MODELS:
            to_put = []
            skipped = 0
            for obj in db.GqlQuery('SELECT * FROM %s'%modelname):
                oldkey = getattr(obj, field)
                if oldkey:
                    oldkey = str(oldkey.key())
                if oldkey in tb:
                    setattr(obj, field, tb[oldkey])
                    to_put.append(obj)
                else:
                    skipped += 1
            db.put(to_put)
            self.response.out.write("[%s] - Migrated %d references!<br/>Skipped: %d<br/>\n"%(modelname, len(to_put), skipped))

class MigrateBlobs(blobstore_handlers.BlobstoreDownloadHandler):
    '''Migrate blobs from myoldapp to mynewapp'''
    def get(self):
        import time
        from google.appengine.api import files, urlfetch
        start_time = time.time()
        timed_out = False
        migrated_keys = set([str(blob.origkey) for blob in mig_BlobMig.all()])
        all_blobs = eval(urlfetch.fetch("https://myoldapp.appspot.com/mig/__getblobkeys", deadline=15.0).content)
        all_keys = set(all_blobs.keys())
        missing_keys = list(all_keys-migrated_keys)
        if not missing_keys:
            self.response.out.write("Nothing to migrate!")
            return
        # Download 20 blobs per round
        download_keys = missing_keys[:20]
        MAXSIZE = (10*1024*1024) # 10MB
        for origkey in download_keys:
            blob = all_blobs[origkey]
            url = "https://myoldapp.appspot.com/mig/__getblob/%s"%urllib.quote_plus(origkey)
            blob_path = files.blobstore.create(mime_type=blob["content_type"], _blobinfo_uploaded_filename=blob["filename"])
            fsize = int(blob["size"])
            with files.open(blob_path, 'a') as f:
                for first_byte in range(0, fsize, MAXSIZE):
                    last_byte = (first_byte+MAXSIZE-1)
                    if last_byte>=fsize: last_byte=(fsize-1)
                    bytes_range = "bytes=%d-%d"%(first_byte,last_byte)
                    logging.info("Downloading [%s] range [%s] key=[%s]"%(blob["filename"], bytes_range, origkey))
                    res = urlfetch.fetch(url, deadline=35.0, headers={"Range": bytes_range})
                    f.write(res.content)
                    del res.content
                    del res
                    if (time.time()-start_time > 40.0):
                        timed_out = True
                        break
            if timed_out:
                self.response.out.write("Stopped due to time limit!<br/>")
                break
            files.finalize(blob_path)
            blob_key = files.blobstore.get_blob_key(blob_path)
            blob_info = blobstore.BlobInfo.get(blob_key)
            mig_BlobMig(fname=blob["filename"], blobinfo=blob_info, origkey=origkey).put()
            logging.info("Successfully downloaded [%s]!!!"%(blob["filename"]))
            self.response.out.write("Migrated %s<br/>"%blob["filename"])
        self.response.out.write("<br/>SUCCESS!")

class GetBlobKeys(blobstore_handlers.BlobstoreDownloadHandler):
    '''Retrieve all Blob Keys, as a JSON string'''
    def get(self):
        from simplejson.encoder import JSONEncoder
        blobs = {}
        for blob_info in blobstore.BlobInfo.all():
            blobs[str(blob_info.key())] = {
             "filename":str(blob_info.filename),
             "content_type":str(blob_info.content_type),
             "size":int(blob_info.size),
             "key":str(blob_info.key()),
            }
        self.response.headers["Content-type"] = "application/json"
        self.response.out.write(JSONEncoder().encode(blobs))

class GetBlob(blobstore_handlers.BlobstoreDownloadHandler):
    '''Download a blob given its key'''
    def get(self, blobkey):
        blobkey = str(urllib.unquote(blobkey))
        blob_info = blobstore.BlobInfo.get(blobkey)
        if not blob_info:
            self.error(404)
            return
        self.response.headers["Content-type"] = str(blob_info.content_type)
        self.send_blob(blob_info, save_as=True)

####
# END OF TEMPORARY BLOBSTORE MIGRATION CODE
####
  • Modificare la MODELS variabile aggiunta dei modelli e dei campi blob informazioni che è necessario aggiornare
  • Sostituire myoldapp URL con l'URL effettivo della vostra vecchia applicazione
  • Sincronizzare il codice su entrambi i apps
  • Aprire un browser e puntare a http://mynewapp.appspot.com/mig/__migrateblobs . Naturalmente, mynewapp deve essere sostituito con il nome della relativa applicazione HRD. Questo scaricherà le macchie dal app vecchio a quello nuovo. Perché c'è un limite di timeout sarà bisogno di chiamare molte volte. ATTENZIONE: è necessario presentare una sola richiesta alla volta, mai chiamare da due browser / schede allo stesso tempo, altrimenti si scherza il database di migrazione!. Quindi, questo passaggio deve essere ben eseguita, una richiesta al momento e attendere che finisca prima di chiamare il prossimo. Ripetere questa operazione fino a visualizzare il messaggio Nothing to migrate! . Questo passo può essere molto lento a seconda di quanti file avete nel blobstore e la loro dimensione, potrebbe richiedere molto tempo per ottenere tutti i file scaricati. Sii paziente!
  • Una volta che tutti i file vengono copiati nella nuova applicazione, puntare il browser a http://mynewapp.appspot.com/mig/__migratereferences . Deve essere veloce, e deve essere eseguito una sola volta. Tuttavia, non fa male a chiamare più di una volta.
  • L'ultimo passo, rimuovere il codice di migrazione e gli URL e sincronizzare nuovamente il codice. È inoltre possibile rimuovere il mig_BlobMig database.

Buona la migrazione.

  1. Nessun commento ancora.

Spam protezione da WP Captcha-Free