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