merge stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 16 Oct 2009 14:38:01 +0200
branchstable
changeset 3703 f8955575541c
parent 3702 29cce43d6af2 (diff)
parent 3698 9f652194bfb3 (current diff)
child 3704 ddb10568f5f8
merge
--- a/common/migration.py	Fri Oct 16 10:59:11 2009 +0200
+++ b/common/migration.py	Fri Oct 16 14:38:01 2009 +0200
@@ -92,7 +92,9 @@
 
     def __init__(self, config, interactive=True, verbosity=1):
         self.config = config
-        self.config.init_log(logthreshold=logging.ERROR, debug=True)
+        if config:
+            # no config on shell to a remote instance
+            self.config.init_log(logthreshold=logging.ERROR, debug=True)
         # 0: no confirmation, 1: only main commands confirmed, 2 ask for everything
         self.verbosity = verbosity
         self.need_wrap = True
--- a/cwctl.py	Fri Oct 16 10:59:11 2009 +0200
+++ b/cwctl.py	Fri Oct 16 14:38:01 2009 +0200
@@ -685,10 +685,16 @@
 
 
 class ShellCommand(Command):
-    """Run an interactive migration shell. This is a python shell with
-    enhanced migration commands predefined in the namespace. An additional
-    argument may be given corresponding to a file containing commands to
-    execute in batch mode.
+    """Run an interactive migration shell on an instance. This is a python shell
+    with enhanced migration commands predefined in the namespace. An additional
+    argument may be given corresponding to a file containing commands to execute
+    in batch mode.
+
+    By default it will connect to a local instance using an in memory
+    connection, unless -P option is specified, in which case you will be
+    connected through pyro. In the later case, you won't have access to
+    repository internals (session, etc...) so most migration commands won't be
+    available.
 
     <instance>
       the identifier of the instance to connect.
@@ -698,46 +704,72 @@
     options = (
         ('system-only',
          {'short': 'S', 'action' : 'store_true',
-          'default': False,
           'help': 'only connect to the system source when the instance is '
           'using multiple sources. You can\'t use this option and the '
-          '--ext-sources option at the same time.'}),
+          '--ext-sources option at the same time.',
+          'group': 'local'
+         }),
 
         ('ext-sources',
          {'short': 'E', 'type' : 'csv', 'metavar': '<sources>',
-          'default': None,
           'help': "For multisources instances, specify to which sources the \
 repository should connect to for upgrading. When unspecified or 'all' given, \
 will connect to all defined sources. If 'migration' is given, appropriate \
 sources for migration will be automatically selected.",
+          'group': 'local'
           }),
 
         ('force',
          {'short': 'f', 'action' : 'store_true',
-          'default' : False,
-          'help': 'don\'t check instance is up to date.'}
-         ),
+          'help': 'don\'t check instance is up to date.',
+          'group': 'local'
+          }),
+
+        ('pyro',
+         {'short': 'P', 'action' : 'store_true',
+          'help': 'connect to a running instance through Pyro.',
+          'group': 'remote',
+          }),
+        ('pyro-ns-host',
+         {'short': 'H', 'type' : 'string', 'metavar': '<host[:port]>',
+          'help': 'Pyro name server host. If not set, will be detected by '
+          'using a broadcast query.',
+          'group': 'remote'
+          }),
         )
 
     def run(self, args):
         appid = pop_arg(args, 99, msg="No instance specified !")
-        config = cwcfg.config_for(appid)
-        if self.config.ext_sources:
-            assert not self.config.system_only
-            sources = self.config.ext_sources
-        elif self.config.system_only:
-            sources = ('system',)
+        if self.config.pyro:
+            from cubicweb.dbapi import connect
+            from cubicweb.server.utils import manager_userpasswd
+            from cubicweb.server.migractions import ServerMigrationHelper
+            login, pwd = manager_userpasswd(msg=None)
+            cnx = connect(appid, login=login, password=pwd,
+                          host=self.config.pyro_ns_host, mulcnx=False)
+            repo = cnx._repo
+            mih = ServerMigrationHelper(None, repo=repo, cnx=cnx,
+                                         # hack so it don't try to load fs schema
+                                        schema=1)
         else:
-            sources = ('all',)
-        config.set_sources_mode(sources)
-        config.repairing = self.config.force
-        mih = config.migration_handler()
+            config = cwcfg.config_for(appid)
+            if self.config.ext_sources:
+                assert not self.config.system_only
+                sources = self.config.ext_sources
+            elif self.config.system_only:
+                sources = ('system',)
+            else:
+                sources = ('all',)
+            config.set_sources_mode(sources)
+            config.repairing = self.config.force
+            mih = config.migration_handler()
         if args:
             for arg in args:
                 mih.process_script(arg)
         else:
             mih.interactive_shell()
-        mih.shutdown()
+        if not self.config.pyro:
+            mih.shutdown()
 
 
 class RecompileInstanceCatalogsCommand(InstanceCommand):
--- a/cwvreg.py	Fri Oct 16 10:59:11 2009 +0200
+++ b/cwvreg.py	Fri Oct 16 14:38:01 2009 +0200
@@ -374,6 +374,8 @@
             implemented_interfaces = set()
             if 'Any' in self.get('etypes', ()):
                 for etype in self.schema.entities():
+                    if etype.final:
+                        continue
                     cls = self['etypes'].etype_class(etype)
                     for iface in cls.__implements__:
                         implemented_interfaces.update(iface.__mro__)
--- a/server/__init__.py	Fri Oct 16 10:59:11 2009 +0200
+++ b/server/__init__.py	Fri Oct 16 14:38:01 2009 +0200
@@ -176,6 +176,10 @@
     # reloging using the admin user
     config._cubes = None # avoid assertion error
     repo, cnx = in_memory_cnx(config, login, pwd)
+    # trigger vreg initialisation of entity classes
+    config.cubicweb_appobject_path = set(('entities',))
+    config.cube_appobject_path = set(('entities',))
+    repo.vreg.set_schema(repo.schema)
     assert len(repo.sources) == 1, repo.sources
     handler = config.migration_handler(schema, interactive=False,
                                        cnx=cnx, repo=repo)
--- a/server/migractions.py	Fri Oct 16 10:59:11 2009 +0200
+++ b/server/migractions.py	Fri Oct 16 14:38:01 2009 +0200
@@ -54,6 +54,7 @@
     def __init__(self, config, schema, interactive=True,
                  repo=None, cnx=None, verbosity=1, connect=True):
         MigrationHelper.__init__(self, config, interactive, verbosity)
+        # no config on shell to a remote instance
         if not interactive:
             assert cnx
             assert repo
@@ -61,7 +62,8 @@
             assert repo
             self._cnx = cnx
             self.repo = repo
-            self.session.data['rebuild-infered'] = False
+            if config is not None:
+                self.session.data['rebuild-infered'] = False
         elif connect:
             self.repo_connect()
         if not schema:
@@ -233,7 +235,10 @@
 
     @property
     def session(self):
-        return self.repo._get_session(self.cnx.sessionid)
+        if self.config is not None:
+            return self.repo._get_session(self.cnx.sessionid)
+        # no access to session on remote instance
+        return None
 
     def commit(self):
         if hasattr(self, '_cnx'):
@@ -268,8 +273,7 @@
     @cached
     def group_mapping(self):
         """cached group mapping"""
-        self.session.set_pool()
-        return ss.group_mapping(self.session)
+        return ss.group_mapping(self._cw)
 
     def exec_event_script(self, event, cubepath=None, funcname=None,
                           *args, **kwargs):
@@ -981,7 +985,6 @@
 
          :rtype: `Workflow`
         """
-        self.session.set_pool() # ensure pool is set
         wf = self.cmd_create_entity('Workflow', name=unicode(name),
                                     **kwargs)
         if not isinstance(wfof, (list, tuple)):
@@ -1001,7 +1004,6 @@
 
     # XXX remove once cmd_add_[state|transition] are removed
     def _get_or_create_wf(self, etypes):
-        self.session.set_pool() # ensure pool is set
         if not isinstance(etypes, (list, tuple)):
             etypes = (etypes,)
         rset = self.rqlexec('Workflow X WHERE X workflow_of ET, ET name %(et)s',
@@ -1041,16 +1043,14 @@
         """set or add (if `reset` is False) groups and conditions for a
         transition
         """
-        self.session.set_pool() # ensure pool is set
-        tr = self.session.entity_from_eid(treid)
+        tr = self._cw.entity_from_eid(treid)
         tr.set_transition_permissions(requiredgroups, conditions, reset)
         if commit:
             self.commit()
 
     @deprecated('[3.5] use entity.fire_transition("transition") or entity.change_state("state")')
     def cmd_set_state(self, eid, statename, commit=False):
-        self.session.set_pool() # ensure pool is set
-        self.session.entity_from_eid(eid).change_state(statename)
+        self._cw.entity_from_eid(eid).change_state(statename)
         if commit:
             self.commit()
 
@@ -1074,11 +1074,18 @@
 
     # other data migration commands ###########################################
 
+    @property
+    def _cw(self):
+        session = self.session
+        if session is not None:
+            session.set_pool()
+            return session
+        return self.cnx.request()
+
     def cmd_create_entity(self, etype, *args, **kwargs):
         """add a new entity of the given type"""
         commit = kwargs.pop('commit', False)
-        self.session.set_pool()
-        entity = self.session.create_entity(etype, *args, **kwargs)
+        entity = self._cw.create_entity(etype, *args, **kwargs)
         if commit:
             self.commit()
         return entity
@@ -1114,7 +1121,6 @@
         if not isinstance(rql, (tuple, list)):
             rql = ( (rql, kwargs), )
         res = None
-        self.session.set_pool()
         for rql, kwargs in rql:
             if kwargs:
                 msg = '%s (%s)' % (rql, kwargs)
@@ -1122,7 +1128,7 @@
                 msg = rql
             if not ask_confirm or self.confirm('execute rql: %s ?' % msg):
                 try:
-                    res = self.session.execute(rql, kwargs, cachekey)
+                    res = self._cw.execute(rql, kwargs, cachekey)
                 except Exception, ex:
                     if self.confirm('error: %s\nabort?' % ex):
                         raise
@@ -1211,9 +1217,8 @@
         if self.ask_confirm:
             if not self._h.confirm('execute rql: %s ?' % msg):
                 raise StopIteration
-        self._h.session.set_pool()
         try:
-            rset = self._h.session.execute(rql, kwargs)
+            rset = self._h._cw.execute(rql, kwargs)
         except Exception, ex:
             if self._h.confirm('error: %s\nabort?' % ex):
                 raise
--- a/server/utils.py	Fri Oct 16 10:59:11 2009 +0200
+++ b/server/utils.py	Fri Oct 16 14:38:01 2009 +0200
@@ -71,7 +71,8 @@
 def manager_userpasswd(user=None, msg=DEFAULT_MSG, confirm=False,
                        passwdmsg='password'):
     if not user:
-        print msg
+        if msg:
+            print msg
         while not user:
             user = raw_input('login: ')
         user = unicode(user, sys.stdin.encoding)