# HG changeset patch # User Sylvain Thénault # Date 1255696631 -7200 # Node ID fd550e4dc51531dbbaa0f085eaee14c07eec9f89 # Parent 20ba545e00e1074d9aa0777f81b1b8d4e9be8fc2 #481017: cubicweb-ctl shell on remote instance diff -r 20ba545e00e1 -r fd550e4dc515 common/migration.py --- a/common/migration.py Fri Oct 16 14:15:44 2009 +0200 +++ b/common/migration.py Fri Oct 16 14:37:11 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 diff -r 20ba545e00e1 -r fd550e4dc515 cwctl.py --- a/cwctl.py Fri Oct 16 14:15:44 2009 +0200 +++ b/cwctl.py Fri Oct 16 14:37:11 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. 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': '', - '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': '', + '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): diff -r 20ba545e00e1 -r fd550e4dc515 server/migractions.py --- a/server/migractions.py Fri Oct 16 14:15:44 2009 +0200 +++ b/server/migractions.py Fri Oct 16 14:37:11 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