31 from logilab.common.shellutils import ProgressBar |
31 from logilab.common.shellutils import ProgressBar |
32 |
32 |
33 from cubicweb.schema import PURE_VIRTUAL_RTYPES |
33 from cubicweb.schema import PURE_VIRTUAL_RTYPES |
34 from cubicweb.server.sqlutils import SQL_PREFIX |
34 from cubicweb.server.sqlutils import SQL_PREFIX |
35 from cubicweb.server.session import security_enabled |
35 from cubicweb.server.session import security_enabled |
|
36 |
|
37 def notify_fixed(fix): |
|
38 if fix: |
|
39 print >> sys.stderr, ' [FIXED]' |
|
40 else: |
|
41 print >> sys.stderr |
36 |
42 |
37 def has_eid(session, sqlcursor, eid, eids): |
43 def has_eid(session, sqlcursor, eid, eids): |
38 """return true if the eid is a valid eid""" |
44 """return true if the eid is a valid eid""" |
39 if eid in eids: |
45 if eid in eids: |
40 return eids[eid] |
46 return eids[eid] |
165 if not has_eid(session, cursor, eid, eids): |
171 if not has_eid(session, cursor, eid, eids): |
166 msg = ' Entity with eid %s exists in the text index but in no source' |
172 msg = ' Entity with eid %s exists in the text index but in no source' |
167 print >> sys.stderr, msg % eid, |
173 print >> sys.stderr, msg % eid, |
168 if fix: |
174 if fix: |
169 session.system_sql('DELETE FROM appears WHERE uid=%s;' % eid) |
175 session.system_sql('DELETE FROM appears WHERE uid=%s;' % eid) |
170 print >> sys.stderr, ' [FIXED]' |
176 notify_fixed(fix) |
171 else: |
|
172 print >> sys.stderr |
|
173 |
177 |
174 |
178 |
175 def check_entities(schema, session, eids, fix=1): |
179 def check_entities(schema, session, eids, fix=1): |
176 """check all entities registered in the repo system table""" |
180 """check all entities registered in the repo system table""" |
177 print 'Checking entities system table' |
181 print 'Checking entities system table' |
181 if not has_eid(session, cursor, eid, eids): |
185 if not has_eid(session, cursor, eid, eids): |
182 msg = ' Entity with eid %s exists in the system table but in no source' |
186 msg = ' Entity with eid %s exists in the system table but in no source' |
183 print >> sys.stderr, msg % eid, |
187 print >> sys.stderr, msg % eid, |
184 if fix: |
188 if fix: |
185 session.system_sql('DELETE FROM entities WHERE eid=%s;' % eid) |
189 session.system_sql('DELETE FROM entities WHERE eid=%s;' % eid) |
186 print >> sys.stderr, ' [FIXED]' |
190 notify_fixed(fix) |
187 else: |
|
188 print >> sys.stderr |
|
189 print 'Checking entities tables' |
191 print 'Checking entities tables' |
190 for eschema in schema.entities(): |
192 for eschema in schema.entities(): |
191 if eschema.final: |
193 if eschema.final: |
192 continue |
194 continue |
193 table = SQL_PREFIX + eschema.type |
195 table = SQL_PREFIX + eschema.type |
200 if not eid in eids or not eids[eid]: |
202 if not eid in eids or not eids[eid]: |
201 msg = ' Entity with eid %s exists in the %s table but not in the system table' |
203 msg = ' Entity with eid %s exists in the %s table but not in the system table' |
202 print >> sys.stderr, msg % (eid, eschema.type), |
204 print >> sys.stderr, msg % (eid, eschema.type), |
203 if fix: |
205 if fix: |
204 session.system_sql('DELETE FROM %s WHERE %s=%s;' % (table, column, eid)) |
206 session.system_sql('DELETE FROM %s WHERE %s=%s;' % (table, column, eid)) |
205 print >> sys.stderr, ' [FIXED]' |
207 notify_fixed(fix) |
206 else: |
|
207 print >> sys.stderr |
|
208 |
208 |
209 |
209 |
210 def bad_related_msg(rtype, target, eid, fix): |
210 def bad_related_msg(rtype, target, eid, fix): |
211 msg = ' A relation %s with %s eid %s exists but no such entity in sources' |
211 msg = ' A relation %s with %s eid %s exists but no such entity in sources' |
212 print >> sys.stderr, msg % (rtype, target, eid), |
212 print >> sys.stderr, msg % (rtype, target, eid), |
213 if fix: |
213 notify_fixed(fix) |
214 print >> sys.stderr, ' [FIXED]' |
|
215 else: |
|
216 print >> sys.stderr |
|
217 |
214 |
218 |
215 |
219 def check_relations(schema, session, eids, fix=1): |
216 def check_relations(schema, session, eids, fix=1): |
220 """check all relations registered in the repo system table""" |
217 """check that eids referenced by relations are registered in the repo system |
|
218 table |
|
219 """ |
221 print 'Checking relations' |
220 print 'Checking relations' |
222 for rschema in schema.relations(): |
221 for rschema in schema.relations(): |
223 if rschema.final or rschema in PURE_VIRTUAL_RTYPES: |
222 if rschema.final or rschema in PURE_VIRTUAL_RTYPES: |
224 continue |
223 continue |
225 if rschema.inlined: |
224 if rschema.inlined: |
259 bad_related_msg(rschema, 'object', eid, fix) |
258 bad_related_msg(rschema, 'object', eid, fix) |
260 if fix: |
259 if fix: |
261 sql = 'DELETE FROM %s_relation WHERE eid_to=%s;' % ( |
260 sql = 'DELETE FROM %s_relation WHERE eid_to=%s;' % ( |
262 rschema, eid) |
261 rschema, eid) |
263 session.system_sql(sql) |
262 session.system_sql(sql) |
|
263 |
|
264 |
|
265 def check_mandatory_relations(schema, session, eids, fix=1): |
|
266 """check entities missing some mandatory relation""" |
|
267 print 'Checking mandatory relations' |
|
268 for rschema in schema.relations(): |
|
269 if rschema.final or rschema in PURE_VIRTUAL_RTYPES: |
|
270 continue |
|
271 smandatory = set() |
|
272 omandatory = set() |
|
273 for rdef in rschema.rdefs.values(): |
|
274 if rdef.cardinality[0] in '1+': |
|
275 smandatory.add(rdef.subject) |
|
276 if rdef.cardinality[1] in '1+': |
|
277 omandatory.add(rdef.object) |
|
278 for role, etypes in (('subject', smandatory), ('object', omandatory)): |
|
279 for etype in etypes: |
|
280 if role == 'subject': |
|
281 rql = 'Any X WHERE NOT X %s Y, X is %s' % (rschema, etype) |
|
282 else: |
|
283 rql = 'Any X WHERE NOT Y %s X, X is %s' % (rschema, etype) |
|
284 for entity in session.execute(rql).entities(): |
|
285 print >> sys.stderr, '%s #%s is missing mandatory %s relation %s' % ( |
|
286 entity.__regid__, entity.eid, role, rschema) |
|
287 if fix: |
|
288 #if entity.cw_describe()['source']['uri'] == 'system': XXX |
|
289 entity.delete() |
|
290 notify_fixed(fix) |
|
291 |
|
292 |
|
293 def check_mandatory_attributes(schema, session, eids, fix=1): |
|
294 """check for entities stored in the system source missing some mandatory |
|
295 attribute |
|
296 """ |
|
297 print 'Checking mandatory attributes' |
|
298 for rschema in schema.relations(): |
|
299 if not rschema.final or rschema in VIRTUAL_RTYPES: |
|
300 continue |
|
301 for rdef in rschema.rdefs.values(): |
|
302 if rdef.cardinality[0] in '1+': |
|
303 rql = 'Any X WHERE X %s NULL, X is %s, X cw_source S, S name "system"' % ( |
|
304 rschema, rdef.subject) |
|
305 for entity in session.execute(rql).entities(): |
|
306 print >> sys.stderr, '%s #%s is missing mandatory attribute %s' % ( |
|
307 entity.__regid__, entity.eid, rschema) |
|
308 if fix: |
|
309 entity.delete() |
|
310 notify_fixed(fix) |
264 |
311 |
265 |
312 |
266 def check_metadata(schema, session, eids, fix=1): |
313 def check_metadata(schema, session, eids, fix=1): |
267 """check entities has required metadata |
314 """check entities has required metadata |
268 |
315 |
283 print >> sys.stderr, msg % (etype, eid, rel), |
330 print >> sys.stderr, msg % (etype, eid, rel), |
284 if fix: |
331 if fix: |
285 session.system_sql("UPDATE %s SET %s=%%(v)s WHERE %s=%s ;" |
332 session.system_sql("UPDATE %s SET %s=%%(v)s WHERE %s=%s ;" |
286 % (table, column, eidcolumn, eid), |
333 % (table, column, eidcolumn, eid), |
287 {'v': default}) |
334 {'v': default}) |
288 print >> sys.stderr, ' [FIXED]' |
335 notify_fixed(fix) |
289 else: |
|
290 print >> sys.stderr |
|
291 cursor = session.system_sql('SELECT MIN(%s) FROM %sCWUser;' % (eidcolumn, |
336 cursor = session.system_sql('SELECT MIN(%s) FROM %sCWUser;' % (eidcolumn, |
292 SQL_PREFIX)) |
337 SQL_PREFIX)) |
293 default_user_eid = cursor.fetchone()[0] |
338 default_user_eid = cursor.fetchone()[0] |
294 assert default_user_eid is not None, 'no user defined !' |
339 assert default_user_eid is not None, 'no user defined !' |
295 for rel, default in ( ('owned_by', default_user_eid), ): |
340 for rel, default in ( ('owned_by', default_user_eid), ): |
301 msg = ' %s with eid %s has no %s relation' |
346 msg = ' %s with eid %s has no %s relation' |
302 print >> sys.stderr, msg % (etype, eid, rel), |
347 print >> sys.stderr, msg % (etype, eid, rel), |
303 if fix: |
348 if fix: |
304 session.system_sql('INSERT INTO %s_relation VALUES (%s, %s) ;' |
349 session.system_sql('INSERT INTO %s_relation VALUES (%s, %s) ;' |
305 % (rel, eid, default)) |
350 % (rel, eid, default)) |
306 print >> sys.stderr, ' [FIXED]' |
351 notify_fixed(fix) |
307 else: |
|
308 print >> sys.stderr |
|
309 |
352 |
310 |
353 |
311 def check(repo, cnx, checks, reindex, fix, withpb=True): |
354 def check(repo, cnx, checks, reindex, fix, withpb=True): |
312 """check integrity of instance's repository, |
355 """check integrity of instance's repository, |
313 using given user and password to locally connect to the repository |
356 using given user and password to locally connect to the repository |