author | Sylvain Thénault <sylvain.thenault@logilab.fr> |
Wed, 23 Sep 2009 11:22:19 +0200 | |
changeset 3412 | 368c68ffb99e |
parent 2312 | af4d8f75c5db |
child 3689 | deb13e88e037 |
permissions | -rw-r--r-- |
0 | 1 |
"""special management views to manage repository content (initialization and |
2 |
restoration). |
|
3 |
||
4 |
:organization: Logilab |
|
1977
606923dff11b
big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1802
diff
changeset
|
5 |
:copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
0 | 6 |
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
1977
606923dff11b
big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1802
diff
changeset
|
7 |
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
0 | 8 |
""" |
9 |
__docformat__ = "restructuredtext en" |
|
10 |
||
11 |
from os.path import exists, join, abspath |
|
12 |
from pickle import loads, dumps |
|
13 |
||
14 |
from logilab.common.decorators import cached |
|
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
15 |
from logilab.mtconverter import xml_escape |
0 | 16 |
|
692
800592b8d39b
replace deprecated cubicweb.common.selectors by its new module path (cubicweb.selectors)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
635
diff
changeset
|
17 |
from cubicweb.selectors import none_rset, match_user_groups |
0 | 18 |
from cubicweb.common.view import StartupView |
19 |
from cubicweb.web import Redirect |
|
20 |
from cubicweb.goa.dbinit import fix_entities, init_persistent_schema, insert_versions |
|
21 |
||
22 |
from google.appengine.api.datastore import Entity, Key, Get, Put, Delete |
|
23 |
from google.appengine.api.datastore_types import Blob |
|
24 |
from google.appengine.api.datastore_errors import EntityNotFoundError |
|
25 |
||
26 |
||
27 |
def _get_status(name, create=True): |
|
28 |
key = Key.from_path('EApplicationStatus', name) |
|
29 |
try: |
|
30 |
status = Get(key) |
|
31 |
except EntityNotFoundError: |
|
32 |
if create: |
|
33 |
status = Entity('EApplicationStatus', name=name) |
|
34 |
else: |
|
35 |
status = None |
|
36 |
return status |
|
37 |
||
38 |
||
39 |
class AuthInfo(StartupView): |
|
40 |
"""special management view to get cookie values to give to laxctl commands |
|
41 |
which are doing datastore administration requests |
|
42 |
""" |
|
43 |
id = 'authinfo' |
|
742
99115e029dca
replaced most of __selectors__ assignments with __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
692
diff
changeset
|
44 |
__select__ = none_rset() & match_user_groups('managers') |
0 | 45 |
|
46 |
def call(self): |
|
47 |
cookie = self.req.get_cookie() |
|
48 |
values = [] |
|
49 |
if self.config['use-google-auth']: |
|
50 |
for param in ('ACSID', 'dev_appserver_login'): |
|
51 |
morsel = cookie.get(param) |
|
52 |
if morsel: |
|
53 |
values.append('%s=%s' % (param, morsel.value)) |
|
54 |
break |
|
55 |
values.append('__session=%s' % cookie['__session'].value) |
|
56 |
self.w(u"<p>pass this flag to the client: --cookie='%s'</p>" |
|
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
57 |
% xml_escape('; '.join(values))) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
58 |
|
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
59 |
|
0 | 60 |
|
61 |
class ContentInit(StartupView): |
|
62 |
"""special management view to initialize content of a repository, |
|
63 |
step by step to avoid depassing quotas |
|
64 |
""" |
|
65 |
id = 'contentinit' |
|
742
99115e029dca
replaced most of __selectors__ assignments with __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
692
diff
changeset
|
66 |
__select__ = none_rset() & match_user_groups('managers') |
0 | 67 |
|
68 |
def server_session(self): |
|
69 |
ssession = self.config.repo_session(self.req.cnx.sessionid) |
|
70 |
ssession.set_pool() |
|
71 |
return ssession |
|
72 |
||
73 |
def end_core_step(self, msg, status, stepid): |
|
74 |
status['cpath'] = '' |
|
75 |
status['stepid'] = stepid |
|
76 |
Put(status) |
|
77 |
self.msg(msg) |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
78 |
|
0 | 79 |
def call(self): |
80 |
status = _get_status('creation') |
|
81 |
if status.get('finished'): |
|
82 |
self.redirect('process already completed') |
|
83 |
config = self.config |
|
84 |
# execute cubicweb's post<event> script |
|
85 |
#mhandler.exec_event_script('post%s' % event) |
|
86 |
# execute cubes'post<event> script if any |
|
87 |
paths = [p for p in config.cubes_path() + [config.apphome] |
|
88 |
if exists(join(p, 'migration'))] |
|
89 |
paths = [abspath(p) for p in (reversed(paths))] |
|
90 |
cpath = status.get('cpath') |
|
91 |
if cpath is None and status.get('stepid') is None: |
|
92 |
init_persistent_schema(self.server_session(), self.schema) |
|
93 |
self.end_core_step(u'inserted schema entities', status, 0) |
|
94 |
return |
|
95 |
if cpath == '' and status.get('stepid') == 0: |
|
96 |
fix_entities(self.schema) |
|
97 |
self.end_core_step(u'fixed bootstrap groups and users', status, 1) |
|
98 |
return |
|
99 |
if cpath == '' and status.get('stepid') == 1: |
|
100 |
insert_versions(self.server_session(), self.config) |
|
101 |
self.end_core_step(u'inserted software versions', status, None) |
|
102 |
return |
|
103 |
for i, path in enumerate(paths): |
|
104 |
if not cpath or cpath == path: |
|
105 |
self.info('running %s', path) |
|
106 |
stepid = status.get('stepid') |
|
107 |
context = status.get('context') |
|
108 |
if context is not None: |
|
109 |
context = loads(context) |
|
110 |
else: |
|
111 |
context = {} |
|
112 |
stepid = self._migrhandler.exec_event_script( |
|
113 |
'postcreate', path, 'stepable_postcreate', stepid, context) |
|
114 |
if stepid is None: # finished for this script |
|
115 |
# reset script state |
|
116 |
context = stepid = None |
|
117 |
# next time, go to the next script |
|
118 |
self.msg(u'finished postcreate for %s' % path) |
|
119 |
try: |
|
120 |
path = paths[i+1] |
|
121 |
self.continue_link() |
|
122 |
except IndexError: |
|
123 |
status['finished'] = True |
|
124 |
path = None |
|
125 |
self.redirect('process completed') |
|
126 |
else: |
|
127 |
if context.get('stepidx'): |
|
128 |
self.msg(u'created %s entities for step %s of %s' % ( |
|
129 |
context['stepidx'], stepid, path)) |
|
130 |
else: |
|
131 |
self.msg(u'finished postcreate step %s for %s' % ( |
|
132 |
stepid, path)) |
|
133 |
context = Blob(dumps(context)) |
|
134 |
self.continue_link() |
|
135 |
status['context'] = context |
|
136 |
status['stepid'] = stepid |
|
137 |
status['cpath'] = path |
|
138 |
break |
|
139 |
else: |
|
140 |
if not cpath: |
|
141 |
# nothing to be done |
|
142 |
status['finished'] = True |
|
143 |
self.redirect('process completed') |
|
144 |
else: |
|
145 |
# Note the error: is expected by the laxctl command line tool, |
|
146 |
# deal with this if internationalization is introduced |
|
147 |
self.msg(u'error: strange creation state, can\'t find %s' |
|
148 |
% cpath) |
|
149 |
self.w(u'<div>click <a href="%s?vid=contentclear">here</a> to ' |
|
150 |
'<b>delete all datastore content</b> so process can be ' |
|
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
151 |
'reinitialized</div>' % xml_escape(self.req.base_url())) |
0 | 152 |
Put(status) |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
153 |
|
0 | 154 |
@property |
155 |
@cached |
|
156 |
def _migrhandler(self): |
|
157 |
return self.config.migration_handler(self.schema, interactive=False, |
|
158 |
cnx=self.req.cnx, |
|
159 |
repo=self.config.repository()) |
|
160 |
||
161 |
def msg(self, msg): |
|
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
162 |
self.w(u'<div class="message">%s</div>' % xml_escape(msg)) |
0 | 163 |
def redirect(self, msg): |
164 |
raise Redirect(self.req.build_url('', msg)) |
|
165 |
def continue_link(self): |
|
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
166 |
self.w(u'<a href="%s">continue</a><br/>' % xml_escape(self.req.url())) |
0 | 167 |
|
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
168 |
|
0 | 169 |
class ContentClear(StartupView): |
170 |
id = 'contentclear' |
|
742
99115e029dca
replaced most of __selectors__ assignments with __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
692
diff
changeset
|
171 |
__select__ = none_rset() & match_user_groups('managers') |
1398
5fe84a5f7035
rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents:
742
diff
changeset
|
172 |
skip_etypes = ('CWGroup', 'CWUser') |
1802
d628defebc17
delete-trailing-whitespace + some copyright update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1398
diff
changeset
|
173 |
|
0 | 174 |
def call(self): |
175 |
# XXX should use unsafe_execute with all hooks deactivated |
|
176 |
# XXX step by catching datastore errors? |
|
177 |
for eschema in self.schema.entities(): |
|
178 |
if eschema.is_final() or eschema in self.skip_etypes: |
|
179 |
continue |
|
180 |
self.req.execute('DELETE %s X' % eschema) |
|
181 |
self.w(u'deleted all %s entities<br/>' % eschema) |
|
182 |
status = _get_status('creation', create=False) |
|
183 |
if status: |
|
184 |
Delete(status) |
|
185 |
self.w(u'done<br/>') |
|
186 |
self.w(u'click <a href="%s?vid=contentinit">here</a> to start the data ' |
|
187 |
'initialization process<br/>' % self.req.base_url()) |