[server/migractions] simplify the Migration Handler entry point

There is no need to entertain numerous ways to create a migration handler. We move .set_cnx to cwctl.admincnx, which given a repository, will return an admin cnx.

Moreover, we use the repoapi.get_repository to get repositories.

Related to #3933480.

authorAurelien Campeas <aurelien.campeas@logilab.fr>
changeset760efef45de6
branchdefault
phasedraft
hiddenno
parent revision#a4d465a3e77d fix(ci): manually remove the .tox/doc directory
child revision<not specified>
files modified by this revision
cubicweb/cwctl.py
cubicweb/devtools/testlib.py
cubicweb/server/__init__.py
cubicweb/server/migractions.py
cubicweb/server/serverconfig.py
cubicweb/server/serverctl.py
cubicweb/server/test/unittest_migractions.py
cubicweb/test/unittest_cwctl.py
# HG changeset patch
# User Aurelien Campeas <aurelien.campeas@logilab.fr>
# Date 1404908797 -7200
# Wed Jul 09 14:26:37 2014 +0200
# Node ID 760efef45de659de598b6083c5790f827419921a
# Parent a4d465a3e77d07cf6a79c121c10b2d6484cd7468
[server/migractions] simplify the Migration Handler entry point

There is no need to entertain numerous ways to create a migration
handler. We move .set_cnx to cwctl.admincnx, which given a repository,
will return an admin cnx.

Moreover, we use the repoapi.get_repository to get repositories.

Related to #3933480.

diff --git a/cubicweb/cwctl.py b/cubicweb/cwctl.py
@@ -567,12 +567,12 @@
1          config.verbosity = self.config.verbosity
2          set_sources_mode = getattr(config, 'set_sources_mode', None)
3          if set_sources_mode is not None:
4              set_sources_mode(self.config.ext_sources or ('migration',))
5          # get instance and installed versions for the server and the componants
6 -        mih = config.migration_handler()
7 -        repo = mih.repo
8 +        repo = config.repository()
9 +        mih = config.migration_handler(admincnx(appid))
10          vcconf = repo.get_versions()
11          helper = self.config_helper(config, required=False)
12          if self.config.force_cube_version:
13              for cube, version in self.config.force_cube_version.items():
14                  vcconf[cube] = Version(version)
@@ -712,11 +712,11 @@
15              sources = ('system',)
16          else:
17              sources = ('all',)
18          config.set_sources_mode(sources)
19          config.repairing = self.config.force
20 -        mih = config.migration_handler()
21 +        mih = config.migration_handler(cnx)
22          return mih, lambda: mih.shutdown()
23 
24      def run(self, args):
25          appuri = args.pop(0)
26          mih, shutdown_callback = self._get_mih(appuri)
diff --git a/cubicweb/devtools/testlib.py b/cubicweb/devtools/testlib.py
@@ -239,12 +239,11 @@
27 
28      @contextmanager
29      def shell(self):
30          from cubicweb.server.migractions import ServerMigrationHelper
31          with self.cnx() as cnx:
32 -            mih = ServerMigrationHelper(None, repo=self._repo, cnx=cnx,
33 -                                        interactive=False,
34 +            mih = ServerMigrationHelper(None, cnx=cnx, interactive=False,
35                                          # hack so it don't try to load fs schema
36                                          schema=1)
37              yield mih
38              cnx.commit()
39 
diff --git a/cubicweb/server/__init__.py b/cubicweb/server/__init__.py
@@ -286,11 +286,11 @@
40      schema = repo.schema
41      with connect(repo, login, password=pwd) as cnx:
42          with cnx.security_enabled(False, False):
43              repo.system_source.eid = ssource.eid  # redo this manually
44              handler = config.migration_handler(schema, interactive=False,
45 -                                               cnx=cnx, repo=repo)
46 +                                               cnx=cnx)
47              # serialize the schema
48              initialize_schema(config, schema, handler)
49              # yoo !
50              cnx.commit()
51              repo.system_source.init_creating()
diff --git a/cubicweb/server/migractions.py b/cubicweb/server/migractions.py
@@ -83,37 +83,26 @@
52  class ServerMigrationHelper(MigrationHelper):
53      """specific migration helper for server side migration scripts,
54      providing actions related to schema/data migration
55      """
56 
57 -    def __init__(self, config, schema, interactive=True,
58 -                 repo=None, cnx=None, verbosity=1, connect=True):
59 -        MigrationHelper.__init__(self, config, interactive, verbosity)
60 -        if not interactive:
61 -            assert cnx
62 -            assert repo
63 -        if cnx is not None:
64 -            assert repo
65 -            self.cnx = cnx
66 -            self.repo = repo
67 -        elif connect:
68 -            self.repo = config.repository()
69 -            self.set_cnx()
70 -        # no config on shell to a remote instance
71 -        if config is not None and (cnx or connect):
72 -            repo = self.repo
73 -            # register a hook to clear our group_mapping cache and the
74 -            # self._synchronized set when some group is added or updated
75 -            ClearGroupMap.mih = self
76 -            ClearGroupMap.mih_register(repo)
77 -            CW_EVENT_MANAGER.bind('after-registry-reload',
78 -                                  ClearGroupMap.mih_register, repo)
79 -            # notify we're starting maintenance (called instead of server_start
80 -            # which is called on regular start
81 -            repo.hm.call_hooks('server_maintenance', repo=repo)
82 +    def __init__(self, config, cnx, schema=None, interactive=True, verbosity=1):
83 +        super(ServerMigrationHelper, self).__init__(config, interactive, verbosity)
84 +        self.cnx = cnx
85 +        self.repo = cnx.session.repo
86 +        # register a hook to clear our group_mapping cache and the
87 +        # self._synchronized set when some group is added or updated
88 +        ClearGroupMap.mih = self
89 +        ClearGroupMap.mih_register(self.repo)
90 +        CW_EVENT_MANAGER.bind('after-registry-reload',
91 +                              ClearGroupMap.mih_register, self.repo)
92 +        # notify we're starting maintenance (called instead of server_start
93 +        # which is called on regular start)
94 +        self.repo.hm.call_hooks('server_maintenance', repo=self.repo)
95          if not schema and not config.quick_start:
96 -            insert_lperms = self.repo.get_versions()['cubicweb'] < (3, 14, 0) and 'localperms' in config.available_cubes()
97 +            insert_lperms = (self.repo.get_versions()['cubicweb'] < (3, 14, 0) and
98 +                             'localperms' in config.available_cubes())
99              if insert_lperms:
100                  cubes = config._cubes
101                  config._cubes += ('localperms',)
102              try:
103                  schema = config.load_schema(expand_cubes=True)
@@ -123,10 +112,11 @@
104          self.fs_schema = schema
105          self._synchronized = set()
106 
107      # overriden from base MigrationHelper ######################################
108 
109 +<<<<<<< dest
110      def set_cnx(self):
111          try:
112              login = self.repo.config.default_admin_config['login']
113              pwd = self.repo.config.default_admin_config['password']
114              logger.info(f"use login/password '{login}/*******' found in repo configuration "
@@ -160,10 +150,12 @@
115                        f'this is executed from a script)\nChange the login/password of admin in the '
116                        f'config file (in {self.repo.config.apphome}) to match that.')
117                  print('aborting...')
118                  sys.exit(0)
119 
120 +=======
121 +>>>>>>> source
122      def cube_upgraded(self, cube, version):
123          self.cmd_set_property('system.version.%s' % cube.lower(),
124                                str(version))
125          self.commit()
126 
@@ -196,11 +188,10 @@
127 
128      # server specific migration methods ########################################
129 
130      def backup_database(self, backupfile=None, askconfirm=True, format='native'):
131          config = self.config
132 -        repo = self.repo
133          # paths
134          timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
135          instbkdir = osp.join(config.appdatahome, 'backup')
136          if not osp.exists(instbkdir):
137              os.makedirs(instbkdir)
@@ -215,11 +206,11 @@
138              print('-> no backup done.')
139              return
140          open(backupfile,'w').close()  # kinda lock
141          os.chmod(backupfile, 0o600)
142          # backup
143 -        source = repo.system_source
144 +        source = self.repo.system_source
145          tmpdir = tempfile.mkdtemp()
146          try:
147              failed = False
148              try:
149                  source.backup(osp.join(tmpdir, source.uri), self.confirm, format=format)
@@ -230,20 +221,20 @@
150                  else:
151                      failed = True
152              with open(osp.join(tmpdir, 'format.txt'), 'w') as format_file:
153                  format_file.write('%s\n' % format)
154              with open(osp.join(tmpdir, 'versions.txt'), 'w') as version_file:
155 -                versions = repo.get_versions()
156 +                versions = self.repo.get_versions()
157                  for cube, version in versions.items():
158                      version_file.write('%s %s\n' % (cube, version))
159              if not failed:
160                  bkup = tarfile.open(backupfile, 'w|gz')
161                  for filename in os.listdir(tmpdir):
162                      bkup.add(osp.join(tmpdir, filename), filename)
163                  bkup.close()
164                  # call hooks
165 -                repo.hm.call_hooks('server_backup', repo=repo, timestamp=timestamp)
166 +                self.repo.hm.call_hooks('server_backup', repo=self.repo, timestamp=timestamp)
167                  # done
168                  print('-> backup file', backupfile)
169          finally:
170              shutil.rmtree(tmpdir)
171 
@@ -272,24 +263,35 @@
172          if osp.isfile(osp.join(tmpdir, 'format.txt')):
173              with open(osp.join(tmpdir, 'format.txt')) as format_file:
174                  written_format = format_file.readline().strip()
175                  if written_format in ('portable', 'native'):
176                      format = written_format
177 +<<<<<<< dest
178          repo = self.repo = repository.Repository(self.config)
179          source = repo.system_source
180 +=======
181 +        self.config.init_cnxset_pool = False
182 +        repo = self.repo = self.config.repository()
183 +        source = self.repo.system_source
184 +>>>>>>> source
185          try:
186              source.restore(osp.join(tmpdir, source.uri), self.confirm, drop, format)
187          except Exception:
188              _, exc, traceback_ = sys.exc_info()
189              print('-> error trying to restore %s [%s]' % (source.uri, exc))
190              if not self.confirm('Continue anyway?', default='n', pdb=True, traceback=traceback_):
191                  raise SystemExit(1)
192          finally:
193              shutil.rmtree(tmpdir)
194          # call hooks
195 +<<<<<<< dest
196          repo.bootstrap()
197          repo.hm.call_hooks('server_restore', repo=repo, timestamp=backupfile)
198 +=======
199 +        self.repo.init_cnxset_pool()
200 +        self.repo.hm.call_hooks('server_restore', repo=self.repo, timestamp=backupfile)
201 +>>>>>>> source
202          print('-> database restored.')
203 
204      def commit(self):
205          self.cnx.commit()
206 
diff --git a/cubicweb/server/serverconfig.py b/cubicweb/server/serverconfig.py
@@ -345,14 +345,12 @@
207 
208      sources_mode = None
209      def set_sources_mode(self, sources):
210          self.sources_mode = sources
211 
212 -    def migration_handler(self, schema=None, interactive=True,
213 -                          cnx=None, repo=None, connect=True, verbosity=None):
214 +    def migration_handler(self, cnx, schema=None, interactive=True, verbosity=None):
215          """return a migration handler instance"""
216          from cubicweb.server.migractions import ServerMigrationHelper
217          if verbosity is None:
218              verbosity = getattr(self, 'verbosity', 0)
219 -        return ServerMigrationHelper(self, schema, interactive=interactive,
220 -                                     cnx=cnx, repo=repo, connect=connect,
221 -                                     verbosity=verbosity)
222 +        return ServerMigrationHelper(self, cnx, schema=schema,
223 +                                     interactive=interactive, verbosity=verbosity)
diff --git a/cubicweb/server/serverctl.py b/cubicweb/server/serverctl.py
@@ -30,10 +30,11 @@
224 
225  from logilab.database import get_db_helper, get_connection
226 
227  from cubicweb import AuthenticationError, ExecutionError, ConfigurationError, SourceException
228  from cubicweb.toolsutils import Command, CommandHandler, underline_title
229 +from cubicweb.utils import admincnx
230  from cubicweb.cwctl import CWCTL, check_options_consistency, ConfigureInstanceCommand
231  from cubicweb.server import SOURCE_TYPES
232  from cubicweb.server import checkintegrity
233  from cubicweb.server.serverconfig import (
234      USER_OPTIONS, ServerConfiguration, SourceConfiguration,
@@ -687,20 +688,22 @@
235 
236 
237  def _local_dump(appid, output, format='native'):
238      config = ServerConfiguration.config_for(appid)
239      config.quick_start = True
240 -    mih = config.migration_handler(verbosity=1)
241 +    cnx = admincnx(appid)
242 +    mih = config.migration_handler(cnx, connect=False, verbosity=1)
243      mih.backup_database(output, askconfirm=False, format=format)
244      mih.shutdown()
245 
246 
247  def _local_restore(appid, backupfile, drop, format='native'):
248      config = ServerConfiguration.config_for(appid)
249      config.verbosity = 1  # else we won't be asked for confirmation on problems
250      config.quick_start = True
251 -    mih = config.migration_handler(connect=False, verbosity=1)
252 +    cnx = admincnx(appid)
253 +    mih = config.migration_handler(cnx, connect=False, verbosity=1)
254      mih.restore_database(backupfile, drop, askconfirm=False, format=format)
255      repo = mih.repo
256      # version of the database
257      dbversions = repo.get_versions()
258      mih.shutdown()
diff --git a/cubicweb/server/test/unittest_migractions.py b/cubicweb/server/test/unittest_migractions.py
@@ -100,13 +100,11 @@
259          self.repo.vreg['etypes'].clear_caches()
260 
261      @contextmanager
262      def mh(self):
263          with self.admin_access.repo_cnx() as cnx:
264 -            yield cnx, ServerMigrationHelper(self.repo.config, migrschema,
265 -                                             repo=self.repo, cnx=cnx,
266 -                                             interactive=False)
267 +            yield cnx, ServerMigrationHelper(self.repo.config, cnx, migrschema, interactive=False)
268 
269      def table_sql(self, mh, tablename):
270          result = mh.sqlexec(
271              "SELECT table_name FROM information_schema.tables WHERE LOWER(table_name)=%(table)s",
272              {'table': tablename.lower()})
diff --git a/cubicweb/test/unittest_cwctl.py b/cubicweb/test/unittest_cwctl.py
@@ -63,11 +63,11 @@
273  class CubicWebShellTC(CubicWebTC):
274 
275      def test_process_script_args_context(self):
276          repo = self.repo
277          with self.admin_access.repo_cnx() as cnx:
278 -            mih = ServerMigrationHelper(None, repo=repo, cnx=cnx,
279 +            mih = ServerMigrationHelper(None, cnx=cnx,
280                                          interactive=False,
281                                          # hack so it don't try to load fs schema
282                                          schema=1)
283              scripts = {
284                  'script1.py': list(),