Migration profiles for add-on products?
Martin Aspeli
optilude at gmx.net
Fri May 11 23:17:00 UTC 2007
Maurits van Rees wrote:
>> class Migration(object):
>> implements(IMigration)
>> def __init__(self, id, to_version, profile):
>> self.id = self
>> self.to_version = version
>> self.profile = profile
>>
>
> Let's compare this to my untested code in
> https://svn.plone.org/svn/collective/collective.generations/trunk
>
> from Products.collective.generations import SchemaManager
>
> sm = SchemaManager(
> minimum_generation = 0,
> generation = 5,
> package_name = 'Products.eXtremeManagement'
> )
Good. :)
I think the name SchemaManager is a bit misleading, though. Is it
managing an Archetypes schema? :)
>> then, you register a profile, like Products.Poi:migrate-1.0-2.0 and
>> Products.Poi:migration-2.0-2.1
>
> That would be something like this:
>
> <genericsetup:registerProfile
> name="3"
> title="Migration profile for eXtremeManagement generation 2 to 3."
> description="This profile contains configuration changes that
> are applied during the migration from
> eXtremeManagement generation 2 to 3, which is part
> of the change from 1.1 to 1.5."
> directory="migrations/v1.5"
> provides="Products.GenericSetup.interfaces.MIGRATION"
> />
>
> Note that Products.GenericSetup.interfaces.MIGRATION does not
> currently exist. It is just an idea. But that is not really an issue
> here.
>
>> and a few utilities:
>>
>> v1_0_to_v_2_0 = Migration(1, "2.0", "Products.Poi:migration-1.0-2.0")
>> v2_0_to_v_2_1 = Migration(2, "2.1", "Products.Poi:migration-2.0-2.1")
>>
>> <utility component=".migrations.v1_0_to_v_2_0"
>> name="Products.Poi.v1_0_to_v_2_0" />
>> <utility component=".migrations.v2_0_to_v_2_1"
>> name="Products.Poi.v2_0_to_v_2_1" />
>>
>> (we need some thinking about how to separate different products here, maybe
>> a property in the utility? can't remember what zope.generation does).
>
> No utilities need to be registered with the collective.generations
> approach. That one SchemaManager should be enough. Maybe that can be
> done in zcml though if wanted.
>
>> Then, all you have to do is to work out the current version, find and order
>> the migration utilities for a given product, and execute those profiles
>> one-by-one.
>
> In collective.generations I define an UpgradeManager that has this
> method which takes a SchemaManager as input and does one step:
>
> def evolve(manager):
> """Do one evolution step for this manager.
> """
> generation = get_current_generation(manager) + 1
> manager.evolve(self.site, generation)
> set_current_generation(manager, generation)
> transaction.commit()
>
> Also there are methods evolve_minimum and evolve_maximum that evolve
> the database to the minimum or the maximum generation as defined by
> the SchemaManager.
>
> (I repeat: totally untested.)
>
>> Also, a propertysheet feels quite volatile. It may be nicer to have a local
>> utility which keeps track of the current installed version of each
>> migration-capable product.
>
> Agreed. A property sheet feels rather easy for initial testing though.
>
>>> A first install of eXtremeManagement would probably just need to apply
>>> the main GS extension profile and set
>>> portal_properties.generations.eXtremeManagement to the latest
>>> generation number.
>>>
>>> I would actually want to shield the user from this migration by simply
>>> integrating this in the installer so that it automatically gets called
>>> on a reinstall of eXtremeManagement. I would say for add-on products
>>> this makes sense.
>>>
>> It ought to be an explicit action in Install.py when reinstall=True, but
>> that sounds sensible, yes.
>
> Extensions/install.py could have something like this:
>
> from Products.collective.generations import UpgradeManager
> from Products.collective.generations import SchemaManager
>
> sm = SchemaManager(
> minimum_generation = 0,
> generation = 5,
> package_name = 'Products.eXtremeManagement'
> )
>
>
> def install(context):
> um = UpgradeManager(context) # or getUtility/getToolByName
> um.install(sm)
>
> And during a reinstall it is probably enough to evolve from the
> current iteration to the maximum defined generation, using this
> method:
>
> um.evolve_maximum(sm)
>
> I do not know if this works, but I *am* beginning to like the
> approach. :-)
>
More information about the Product-Developers
mailing list