common/migration.py
branchstable
changeset 2275 bc0bed0616a3
parent 2124 5a0b02f37b23
child 2446 440cb4ea7e5c
equal deleted inserted replaced
2274:885873dc4361 2275:bc0bed0616a3
    16 
    16 
    17 from logilab.common.decorators import cached
    17 from logilab.common.decorators import cached
    18 from logilab.common.configuration import REQUIRED, read_old_config
    18 from logilab.common.configuration import REQUIRED, read_old_config
    19 
    19 
    20 from cubicweb import ConfigurationError
    20 from cubicweb import ConfigurationError
    21 
       
    22 
       
    23 def migration_files(config, toupgrade):
       
    24     """return an orderer list of path of scripts to execute to upgrade
       
    25     an installed application according to installed cube and cubicweb versions
       
    26     """
       
    27     merged = []
       
    28     for cube, fromversion, toversion in toupgrade:
       
    29         if cube == 'cubicweb':
       
    30             migrdir = config.migration_scripts_dir()
       
    31         else:
       
    32             migrdir = config.cube_migration_scripts_dir(cube)
       
    33         scripts = filter_scripts(config, migrdir, fromversion, toversion)
       
    34         merged += [s[1] for s in scripts]
       
    35     if config.accept_mode('Any'):
       
    36         migrdir = config.migration_scripts_dir()
       
    37         merged.insert(0, join(migrdir, 'bootstrapmigration_repository.py'))
       
    38     return merged
       
    39 
    21 
    40 
    22 
    41 def filter_scripts(config, directory, fromversion, toversion, quiet=True):
    23 def filter_scripts(config, directory, fromversion, toversion, quiet=True):
    42     """return a list of paths of migration files to consider to upgrade
    24     """return a list of paths of migration files to consider to upgrade
    43     from a version to a greater one
    25     from a version to a greater one
   124         self.__context = {'confirm': self.confirm,
   106         self.__context = {'confirm': self.confirm,
   125                           'config': self.config,
   107                           'config': self.config,
   126                           'interactive_mode': interactive,
   108                           'interactive_mode': interactive,
   127                           }
   109                           }
   128 
   110 
       
   111     def __getattribute__(self, name):
       
   112         try:
       
   113             return object.__getattribute__(self, name)
       
   114         except AttributeError:
       
   115             cmd = 'cmd_%s' % name
       
   116             if hasattr(self, cmd):
       
   117                 meth = getattr(self, cmd)
       
   118                 return lambda *args, **kwargs: self.interact(args, kwargs,
       
   119                                                              meth=meth)
       
   120             raise
       
   121         raise AttributeError(name)
       
   122 
   129     def repo_connect(self):
   123     def repo_connect(self):
   130         return self.config.repository()
   124         return self.config.repository()
   131 
   125 
   132     def migrate(self, vcconf, toupgrade, options):
   126     def migrate(self, vcconf, toupgrade, options):
   133         """upgrade the given set of cubes
   127         """upgrade the given set of cubes
   142             def accept_mode(mode):
   136             def accept_mode(mode):
   143                 if mode == 'Any':
   137                 if mode == 'Any':
   144                     return False
   138                     return False
   145                 return orig_accept_mode(mode)
   139                 return orig_accept_mode(mode)
   146             self.config.accept_mode = accept_mode
   140             self.config.accept_mode = accept_mode
   147         scripts = migration_files(self.config, toupgrade)
   141         # may be an iterator
   148         if scripts:
   142         toupgrade = tuple(toupgrade)
   149             vmap = dict( (pname, (fromver, tover)) for pname, fromver, tover in toupgrade)
   143         vmap = dict( (cube, (fromver, tover)) for cube, fromver, tover in toupgrade)
   150             self.__context.update({'applcubicwebversion': vcconf['cubicweb'],
   144         ctx = self.__context
   151                                    'cubicwebversion': self.config.cubicweb_version(),
   145         ctx['versions_map'] = vmap
   152                                    'versions_map': vmap})
   146         if self.config.accept_mode('Any') and 'cubicweb' in vmap:
   153             self.scripts_session(scripts)
   147             migrdir = self.config.migration_scripts_dir()
   154         else:
   148             self.process_script(join(migrdir, 'bootstrapmigration_repository.py'))
   155             print 'no migration script to execute'
   149         for cube, fromversion, toversion in toupgrade:
       
   150             if cube == 'cubicweb':
       
   151                 migrdir = self.config.migration_scripts_dir()
       
   152             else:
       
   153                 migrdir = self.config.cube_migration_scripts_dir(cube)
       
   154             scripts = filter_scripts(self.config, migrdir, fromversion, toversion)
       
   155             if scripts:
       
   156                 for version, script in scripts:
       
   157                     self.process_script(script)
       
   158                     self.cube_upgraded(cube, version)
       
   159                 if version != toversion:
       
   160                     self.cube_upgraded(cube, toversion)
       
   161             else:
       
   162                 self.cube_upgraded(cube, toversion)
       
   163 
       
   164     def cube_upgraded(self, cube, version):
       
   165         pass
   156 
   166 
   157     def shutdown(self):
   167     def shutdown(self):
   158         pass
   168         pass
   159 
       
   160     def __getattribute__(self, name):
       
   161         try:
       
   162             return object.__getattribute__(self, name)
       
   163         except AttributeError:
       
   164             cmd = 'cmd_%s' % name
       
   165             if hasattr(self, cmd):
       
   166                 meth = getattr(self, cmd)
       
   167                 return lambda *args, **kwargs: self.interact(args, kwargs,
       
   168                                                              meth=meth)
       
   169             raise
       
   170         raise AttributeError(name)
       
   171 
   169 
   172     def interact(self, args, kwargs, meth):
   170     def interact(self, args, kwargs, meth):
   173         """execute the given method according to user's confirmation"""
   171         """execute the given method according to user's confirmation"""
   174         msg = 'execute command: %s(%s) ?' % (
   172         msg = 'execute command: %s(%s) ?' % (
   175             meth.__name__[4:],
   173             meth.__name__[4:],
   203         if answer in ('n', 'no'):
   201         if answer in ('n', 'no'):
   204             return False
   202             return False
   205         if answer in ('r', 'retry'):
   203         if answer in ('r', 'retry'):
   206             return 2
   204             return 2
   207         if answer in ('a', 'abort'):
   205         if answer in ('a', 'abort'):
   208             self.rollback()
       
   209             raise SystemExit(1)
   206             raise SystemExit(1)
   210         if shell and answer in ('s', 'shell'):
   207         if shell and answer in ('s', 'shell'):
   211             self.interactive_shell()
   208             self.interactive_shell()
   212             return self.confirm(question)
   209             return self.confirm(question)
   213         return True
   210         return True
   282                 except KeyError:
   279                 except KeyError:
   283                     self.critical('no %s in script %s', funcname, migrscript)
   280                     self.critical('no %s in script %s', funcname, migrscript)
   284                     return None
   281                     return None
   285                 return func(*args, **kwargs)
   282                 return func(*args, **kwargs)
   286 
   283 
   287     def scripts_session(self, migrscripts):
       
   288         """execute some scripts in a transaction"""
       
   289         try:
       
   290             for migrscript in migrscripts:
       
   291                 self.process_script(migrscript)
       
   292             self.commit()
       
   293         except:
       
   294             self.rollback()
       
   295             raise
       
   296 
       
   297     def cmd_option_renamed(self, oldname, newname):
   284     def cmd_option_renamed(self, oldname, newname):
   298         """a configuration option has been renamed"""
   285         """a configuration option has been renamed"""
   299         self._option_changes.append(('renamed', oldname, newname))
   286         self._option_changes.append(('renamed', oldname, newname))
   300 
   287 
   301     def cmd_option_group_change(self, option, oldgroup, newgroup):
   288     def cmd_option_group_change(self, option, oldgroup, newgroup):