July 13, 2010

Restoring an older state of arbitrary Zope objects

Deleted some Plone folder lately? Undo not working? Continue with reading...

It is well-known that the Undo functionality of Zope (as as wrapped through Plone UI) usually does not work when other transactions happened in-between. Common use-case: you deleted some content (e.g. a Plone folder or a Plone document) some days ago and you need it back (it's usually the boss messing up company contents and then yelling days later at you to get the content back).

You friendly helper is dm.historical (one of the few Dieter tools I really appreciate).

Here is the blueprint how to recover removed content from a ZODB storage. We assume that we are running some Plone site and want to recover a folder originally located under /plone/myfolder and now it is gone and you want it back.

  • Add dm.historical to your buildout (eggs section and re-run buildout)
  • Start your instance in debug mode (bin/instance debug) and after loading type the following on the console:
from DateTime import DateTime
from dm.historical import getObjectAt
site = getObjectAt(app.plone, DateTime('2010-08-05 14:00:00')) 
folder = site['myfolder']
  • The code above will retrieve the state of the Plone portal object to the given timestamp and perform a ZEXP export of the 'myfolder' folder.
  • You will find the myfolder.zexp file usually under var/instance (depending on your instance configuration. Search for *zexp files using the 'find' command otherwise)
  • Now you copy over the myfolder.zexp back to the import folder of your Zope instance, start your Zope/Plone instance again and re-import the ZEXP file through the ZMI
  • It might be necessary to reindex the portal_catalog after import
    That's it.

Keep in mind that you can not restore object versions older than the timestamp of your last ZODB pack operation. So when you packed one week ago (with the option keeping the revisions of the last seven days) you will not be able to restore revisions older than two weeks.