fix workflow graph views and tabs for the new wf system, remove useless view and action (actually useless since introduction of tabbed entity type view
"""special management views to manage repository content (initialization and
restoration).
:organization: Logilab
:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
__docformat__ = "restructuredtext en"
from os.path import exists, join, abspath
from pickle import loads, dumps
from logilab.common.decorators import cached
from logilab.mtconverter import xml_escape
from cubicweb.selectors import none_rset, match_user_groups
from cubicweb.common.view import StartupView
from cubicweb.web import Redirect
from cubicweb.goa.dbinit import fix_entities, init_persistent_schema, insert_versions
from google.appengine.api.datastore import Entity, Key, Get, Put, Delete
from google.appengine.api.datastore_types import Blob
from google.appengine.api.datastore_errors import EntityNotFoundError
def _get_status(name, create=True):
key = Key.from_path('EApplicationStatus', name)
try:
status = Get(key)
except EntityNotFoundError:
if create:
status = Entity('EApplicationStatus', name=name)
else:
status = None
return status
class AuthInfo(StartupView):
"""special management view to get cookie values to give to laxctl commands
which are doing datastore administration requests
"""
id = 'authinfo'
__select__ = none_rset() & match_user_groups('managers')
def call(self):
cookie = self.req.get_cookie()
values = []
if self.config['use-google-auth']:
for param in ('ACSID', 'dev_appserver_login'):
morsel = cookie.get(param)
if morsel:
values.append('%s=%s' % (param, morsel.value))
break
values.append('__session=%s' % cookie['__session'].value)
self.w(u"<p>pass this flag to the client: --cookie='%s'</p>"
% xml_escape('; '.join(values)))
class ContentInit(StartupView):
"""special management view to initialize content of a repository,
step by step to avoid depassing quotas
"""
id = 'contentinit'
__select__ = none_rset() & match_user_groups('managers')
def server_session(self):
ssession = self.config.repo_session(self.req.cnx.sessionid)
ssession.set_pool()
return ssession
def end_core_step(self, msg, status, stepid):
status['cpath'] = ''
status['stepid'] = stepid
Put(status)
self.msg(msg)
def call(self):
status = _get_status('creation')
if status.get('finished'):
self.redirect('process already completed')
config = self.config
# execute cubicweb's post<event> script
#mhandler.exec_event_script('post%s' % event)
# execute cubes'post<event> script if any
paths = [p for p in config.cubes_path() + [config.apphome]
if exists(join(p, 'migration'))]
paths = [abspath(p) for p in (reversed(paths))]
cpath = status.get('cpath')
if cpath is None and status.get('stepid') is None:
init_persistent_schema(self.server_session(), self.schema)
self.end_core_step(u'inserted schema entities', status, 0)
return
if cpath == '' and status.get('stepid') == 0:
fix_entities(self.schema)
self.end_core_step(u'fixed bootstrap groups and users', status, 1)
return
if cpath == '' and status.get('stepid') == 1:
insert_versions(self.server_session(), self.config)
self.end_core_step(u'inserted software versions', status, None)
return
for i, path in enumerate(paths):
if not cpath or cpath == path:
self.info('running %s', path)
stepid = status.get('stepid')
context = status.get('context')
if context is not None:
context = loads(context)
else:
context = {}
stepid = self._migrhandler.exec_event_script(
'postcreate', path, 'stepable_postcreate', stepid, context)
if stepid is None: # finished for this script
# reset script state
context = stepid = None
# next time, go to the next script
self.msg(u'finished postcreate for %s' % path)
try:
path = paths[i+1]
self.continue_link()
except IndexError:
status['finished'] = True
path = None
self.redirect('process completed')
else:
if context.get('stepidx'):
self.msg(u'created %s entities for step %s of %s' % (
context['stepidx'], stepid, path))
else:
self.msg(u'finished postcreate step %s for %s' % (
stepid, path))
context = Blob(dumps(context))
self.continue_link()
status['context'] = context
status['stepid'] = stepid
status['cpath'] = path
break
else:
if not cpath:
# nothing to be done
status['finished'] = True
self.redirect('process completed')
else:
# Note the error: is expected by the laxctl command line tool,
# deal with this if internationalization is introduced
self.msg(u'error: strange creation state, can\'t find %s'
% cpath)
self.w(u'<div>click <a href="%s?vid=contentclear">here</a> to '
'<b>delete all datastore content</b> so process can be '
'reinitialized</div>' % xml_escape(self.req.base_url()))
Put(status)
@property
@cached
def _migrhandler(self):
return self.config.migration_handler(self.schema, interactive=False,
cnx=self.req.cnx,
repo=self.config.repository())
def msg(self, msg):
self.w(u'<div class="message">%s</div>' % xml_escape(msg))
def redirect(self, msg):
raise Redirect(self.req.build_url('', msg))
def continue_link(self):
self.w(u'<a href="%s">continue</a><br/>' % xml_escape(self.req.url()))
class ContentClear(StartupView):
id = 'contentclear'
__select__ = none_rset() & match_user_groups('managers')
skip_etypes = ('CWGroup', 'CWUser')
def call(self):
# XXX should use unsafe_execute with all hooks deactivated
# XXX step by catching datastore errors?
for eschema in self.schema.entities():
if eschema.is_final() or eschema in self.skip_etypes:
continue
self.req.execute('DELETE %s X' % eschema)
self.w(u'deleted all %s entities<br/>' % eschema)
status = _get_status('creation', create=False)
if status:
Delete(status)
self.w(u'done<br/>')
self.w(u'click <a href="%s?vid=contentinit">here</a> to start the data '
'initialization process<br/>' % self.req.base_url())