Files
entropy/client/text_rescue.py
(no author) ca55d97378 - added more info to equo reports
- misc bug fixes

git-svn-id: http://svn.sabayonlinux.org/projects/entropy/trunk@1117 cd1c1023-2f26-0410-ae45-c471fc1f0318
2008-02-02 15:39:36 +00:00

582 lines
24 KiB
Python

#!/usr/bin/python
'''
# DESCRIPTION:
# Equo integrity handling library
Copyright (C) 2007-2008 Fabio Erculiani
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
'''
########################################################
####
## Repositories Tools
#
from entropyConstants import *
from outputTools import *
from entropy import EquoInterface
Equo = EquoInterface(noclientdb = True)
def database(options):
if len(options) < 1:
return -10
# check if I am root
if (not Equo.entropyTools.isRoot()):
print_error(red("You are not ")+bold("root")+red("."))
return 1
if (options[0] == "generate"):
# test if portage is available
try:
import portageTools
except:
print_error(darkred(" * ")+bold("Portage")+red(" is not available."))
return 1
print_warning(bold("ATTENTION: ")+red("The installed package database will be generated again using Gentoo one."))
print_warning(red("If you dont know what you're doing just, don't do this. Really. I'm not joking."))
rc = Equo.askQuestion(" Understood?")
if rc == "No":
return 0
rc = Equo.askQuestion(" Really?")
if rc == "No":
return 0
rc = Equo.askQuestion(" This is your last chance. Ok?")
if rc == "No":
return 0
# clean caches
Equo.purge_cache()
import shutil
# try to collect current installed revisions if possible
revisionsMatch = {}
try:
myids = Equo.clientDbconn.listAllIdpackages()
for myid in myids:
myatom = Equo.clientDbconn.retrieveAtom(myid)
myrevision = Equo.clientDbconn.retrieveRevision(myid)
revisionsMatch[myatom] = myrevision
except:
pass
# ok, he/she knows it... hopefully
# if exist, copy old database
print_info(red(" @@ ")+blue("Creating backup of the previous database, if exists.")+red(" @@"))
newfile = Equo.databaseTools.backupClientDatabase()
if (newfile):
print_info(red(" @@ ")+blue("Previous database copied to file ")+newfile+red(" @@"))
# Now reinitialize it
print_info(darkred(" Initializing the new database at "+bold(etpConst['etpdatabaseclientfilepath'])), back = True)
Equo.reopenClientDbconn()
Equo.clientDbconn.initializeDatabase()
print_info(darkgreen(" Database reinitialized correctly at "+bold(etpConst['etpdatabaseclientfilepath'])))
# now collect packages in the system
print_info(red(" Transductingactioningintactering databases..."))
portagePackages = portageTools.getInstalledPackages()
portagePackages = portagePackages[0]
# do for each database
maxcount = str(len(portagePackages))
count = 0
for portagePackage in portagePackages:
count += 1
print_info(blue("(")+darkgreen(str(count))+"/"+darkred(maxcount)+blue(")")+red(" atom: ")+brown(portagePackage), back = True)
temptbz2 = etpConst['entropyunpackdir']+"/"+portagePackage.split("/")[1]+".tbz2"
if not os.path.isdir(etpConst['entropyunpackdir']):
os.makedirs(etpConst['entropyunpackdir'])
if os.path.isfile(temptbz2):
os.remove(temptbz2)
elif os.path.isdir(temptbz2):
shutil.rmtree(temptbz2)
f = open(temptbz2,"wb")
f.flush()
f.close()
Equo.entropyTools.appendXpak(temptbz2,portagePackage)
# now extract info
try:
mydata = Equo.entropyTools.extractPkgData(temptbz2, silent = True)
except Exception, e:
Equo.equoLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"Database generation: Exception caught: %s: %s" % (str(Exception),str(e),))
print_warning(red("!!! An error occured while analyzing: ")+blue(portagePackage))
print_warning("Exception: %s: %s" % (str(Exception),str(e),))
continue
# Try to see if it's possible to use the revision of a possible old db
mydata['revision'] = 9999
# create atom string
myatom = mydata['category']+"/"+mydata['name']+"-"+mydata['version']
if mydata['versiontag']:
myatom += "#"+mydata['versiontag']
# now see if a revision is available
savedRevision = revisionsMatch.get(myatom)
if savedRevision != None:
try:
savedRevision = int(savedRevision) # cast to int for security
mydata['revision'] = savedRevision
except:
pass
idpk, rev, xx, status = Equo.clientDbconn.addPackage(etpData = mydata, revision = mydata['revision'])
Equo.clientDbconn.addPackageToInstalledTable(idpk,"gentoo-db")
os.remove(temptbz2)
print_info(red(" All the Gentoo packages have been injected into Entropy database."))
print_info(red(" Now generating depends caching table..."))
Equo.clientDbconn.regenerateDependsTable()
print_info(red(" Database reinitialized successfully."))
return 0
elif (options[0] == "check"):
if Equo.clientDbconn.doesTableExist("baseinfo"):
Equo.clientDatabaseSanityCheck()
else:
print_warning(bold("# ATTENTION: ")+red("database does not exist or is badly broken"))
return 1
return 0
elif (options[0] == "resurrect"):
print_warning(bold("####### ATTENTION -> ")+red("The installed package database will be resurrected, this will take a LOT of time."))
print_warning(bold("####### ATTENTION -> ")+red("Please use this function ONLY if you are using an Entropy-enabled Sabayon distribution."))
rc = Equo.askQuestion(" Can I continue ?")
if rc == "No":
return 0
rc = Equo.askQuestion(" Are you REALLY sure ?")
if rc == "No":
return 0
rc = Equo.askQuestion(" Do you even know what you're doing ?")
if rc == "No":
return 0
# clean caches
Equo.purge_cache()
# ok, he/she knows it... hopefully
# if exist, copy old database
print_info(red(" @@ ")+blue("Creating backup of the previous database, if exists.")+red(" @@"))
newfile = Equo.databaseTools.backupClientDatabase()
if (newfile):
print_info(red(" @@ ")+blue("Previous database copied to file ")+newfile+red(" @@"))
# Now reinitialize it
print_info(darkred(" Initializing the new database at "+bold(etpConst['etpdatabaseclientfilepath'])), back = True)
Equo.clientDbconn.initializeDatabase()
print_info(darkgreen(" Database reinitialized correctly at "+bold(etpConst['etpdatabaseclientfilepath'])))
print_info(red(" Collecting installed files. Writing: "+etpConst['packagestmpfile']+" Please wait..."), back = True)
# since we use find, see if it's installed
find = os.system("which find &> /dev/null")
if find != 0:
print_error(darkred("Attention: ")+red("You must have 'find' installed!"))
return
# spawn process
if os.path.isfile(etpConst['packagestmpfile']):
os.remove(etpConst['packagestmpfile'])
os.system("find "+etpConst['systemroot']+"/ -mount 1> "+etpConst['packagestmpfile'])
if not os.path.isfile(etpConst['packagestmpfile']):
print_error(darkred("Attention: ")+red("find couldn't generate an output file."))
return
f = open(etpConst['packagestmpfile'],"r")
# creating list of files
filelist = set()
item = f.readline().strip()
while item:
filelist.add(item)
item = f.readline().strip()
f.close()
entries = len(filelist)
print_info(red(" Found "+str(entries)+" files on the system. Assigning packages..."))
atoms = {}
pkgsfound = set()
for repo in etpRepositories:
print_info(red(" Matching in repository: ")+etpRepositories[repo]['description'])
# get all idpackages
dbconn = Equo.openRepositoryDatabase(repo)
idpackages = dbconn.listAllIdpackages(branch = etpConst['branch'])
count = str(len(idpackages))
cnt = 0
for idpackage in idpackages:
cnt += 1
idpackageatom = dbconn.retrieveAtom(idpackage)
print_info(" ("+str(cnt)+"/"+count+")"+red(" Matching files from packages..."), back = True)
# content
content = dbconn.retrieveContent(idpackage)
for item in content:
if etpConst['systemroot']+item in filelist:
pkgsfound.add((idpackage,repo))
atoms[(idpackage,repo)] = idpackageatom
filelist.difference_update(set([etpConst['systemroot']+x for x in content]))
break
print_info(red(" Found "+str(len(pkgsfound))+" packages. Filling database..."))
count = str(len(pkgsfound))
cnt = 0
os.remove(etpConst['packagestmpfile'])
for pkgfound in pkgsfound:
cnt += 1
print_info(" ("+str(cnt)+"/"+count+") "+red("Adding: ")+atoms[pkgfound], back = True)
Package = Equo.Package()
Package.prepare(tuple(pkgfound),"install", {})
Package.__install_package_into_database()
Package.kill()
del Package
print_info(red(" Database resurrected successfully."))
print_warning(red(" Keep in mind that virtual/meta packages couldn't be matched. They don't own any files."))
return 0
elif (options[0] == "depends"):
print_info(red(" Regenerating depends caching table..."))
Equo.clientDbconn.regenerateDependsTable()
print_info(red(" Depends caching table regenerated successfully."))
return 0
elif (options[0] == "counters"):
try:
import portageTools
except:
print_error(darkred(" * ")+bold("Portage")+red(" is not available."))
return 1
print_info(red(" Regenerating counters table. Please wait..."))
Equo.clientDbconn.regenerateCountersTable(output = True)
print_info(red(" Counters table regenerated. Check above for errors."))
return 0
elif (options[0] == "gentoosync"):
try:
import portageTools
except:
print_error(darkred(" * ")+bold("Portage")+red(" is not available."))
return 1
print_info(red(" Scanning Portage and Entropy databases for differences..."))
# make it crash
Equo.noclientdb = False
Equo.reopenClientDbconn()
# test if counters table exists, because if not, it's useless to run the diff scan
try:
Equo.clientDbconn.isCounterAvailable(1)
except:
print_error(darkred(" * ")+bold("Entropy database")+red(" has never been in sync with Portage one. So, you can't run this unless you run '")+bold("equo database generate")+red("' first. Sorry."))
return 1
import shutil
from portageTools import getInstalledPackagesCounters, getPackageSlot
print_info(red(" Collecting Portage counters..."), back = True)
installedPackages = getInstalledPackagesCounters()
print_info(red(" Collecting Entropy packages..."), back = True)
installedCounters = set()
toBeAdded = set()
toBeRemoved = set()
print_info(red(" Differential Scan..."), back = True)
# packages to be added/updated (handle add/update later)
for x in installedPackages[0]:
installedCounters.add(x[1])
counter = Equo.clientDbconn.isCounterAvailable(x[1])
if (not counter):
toBeAdded.add(tuple(x))
# packages to be removed from the database
databaseCounters = Equo.clientDbconn.listAllCounters()
for x in databaseCounters:
if x[0] < 0: # skip packages without valid counter
continue
if x[0] not in installedCounters:
# check if the package is in toBeAdded
if (toBeAdded):
atomkey = Equo.entropyTools.dep_getkey(Equo.clientDbconn.retrieveAtom(x[1]))
atomslot = Equo.clientDbconn.retrieveSlot(x[1])
add = True
for pkgdata in toBeAdded:
addslot = getPackageSlot(pkgdata[0])
addkey = Equo.entropyTools.dep_getkey(pkgdata[0])
# workaround for ebuilds not having slot
if addslot == None:
addslot = '0'
if (atomkey == addkey) and (str(atomslot) == str(addslot)):
# do not add to toBeRemoved
add = False
break
if add:
toBeRemoved.add(x[1])
else:
toBeRemoved.add(x[1])
if (not toBeRemoved) and (not toBeAdded):
print_info(red(" Databases already synced."))
# then exit gracefully
return 0
if (toBeRemoved):
print_info(brown(" @@ ")+blue("Someone removed these packages. Would be removed from the Entropy database:"))
for x in toBeRemoved:
atom = Equo.clientDbconn.retrieveAtom(x)
print_info(brown(" # ")+red(atom))
rc = "Yes"
if etpUi['ask']: rc = Equo.askQuestion(">> Continue with removal?")
if rc == "Yes":
queue = 0
totalqueue = str(len(toBeRemoved))
for x in toBeRemoved:
queue += 1
atom = Equo.clientDbconn.retrieveAtom(x)
print_info(red(" ++ ")+bold("(")+blue(str(queue))+"/"+red(totalqueue)+bold(") ")+">>> Removing "+darkgreen(atom))
Equo.clientDbconn.removePackage(x)
print_info(brown(" @@ ")+blue("Database removal complete."))
if (toBeAdded):
print_info(brown(" @@ ")+blue("Someone added these packages. Would be added/updated into the Entropy database:"))
for x in toBeAdded:
print_info(darkgreen(" # ")+red(x[0]))
rc = "Yes"
if etpUi['ask']: rc = Equo.askQuestion(">> Continue with adding?")
if rc == "No":
return 0
# now analyze
totalqueue = str(len(toBeAdded))
queue = 0
for item in toBeAdded:
queue += 1
counter = item[1]
atom = item[0]
print_info(red(" ++ ")+bold("(")+blue(str(queue))+"/"+red(totalqueue)+bold(") ")+">>> Adding "+darkgreen(atom))
if not os.path.isdir(etpConst['entropyunpackdir']):
os.makedirs(etpConst['entropyunpackdir'])
temptbz2 = etpConst['entropyunpackdir']+"/"+atom.split("/")[1]+".tbz2"
if os.path.isfile(temptbz2):
os.remove(temptbz2)
elif os.path.isdir(temptbz2):
shutil.rmtree(temptbz2)
f = open(temptbz2,"wb")
f.flush()
f.close()
Equo.entropyTools.appendXpak(temptbz2,atom)
# now extract info
try:
mydata = Equo.entropyTools.extractPkgData(temptbz2, silent = True)
except Exception, e:
Equo.equoLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"Database gentoosync: Exception caught: %s: %s" % (str(Exception),str(e),))
print_warning(red("!!! An error occured while analyzing: ")+blue(atom))
print_warning("Exception: %s: %s" % (str(Exception),str(e),))
continue
# create atom string
myatom = mydata['category']+"/"+mydata['name']+"-"+mydata['version']
if mydata['versiontag']:
myatom += "#"+mydata['versiontag']
# look for atom in client database
oldidpackage = Equo.clientDbconn.getIDPackage(myatom)
if oldidpackage != -1:
mydata['revision'] = Equo.clientDbconn.retrieveRevision(oldidpackage)
else:
mydata['revision'] = 9999 # can't do much more
idpk, rev, xx, status = Equo.clientDbconn.handlePackage(etpData = mydata, forcedRevision = mydata['revision'])
Equo.clientDbconn.removePackageFromInstalledTable(idpk)
Equo.clientDbconn.addPackageToInstalledTable(idpk,"gentoo-db")
os.remove(temptbz2)
print_info(brown(" @@ ")+blue("Database update completed."))
return 0
else:
return -10
'''
@description: implementation of migration helper tools, like gentoo's python-updater
'''
def updater(options):
if len(options) < 1:
return -10
# check if I am root
if (not Equo.entropyTools.isRoot()):
print_error(red("You are not ")+bold("root")+red("."))
return 1
rc = 0
if options[0] == "python-updater":
rc = pythonUpdater()
return rc
def pythonUpdater():
import re
import text_query
import text_ui
pattern = re.compile(r'^(python)[0-9](.)[0-9]$')
print_info(brown(" @@ ")+blue("Looking for old Python directories..."), back = True)
dirs = [x for x in os.listdir("/usr/lib") if x.startswith("python") and pattern.match(x)]
if len(dirs) <= 1:
print_info(brown(" @@ ")+blue("Your Python installation seems fine."))
return 0
dirs.sort()
print_info(brown(" @@ ")+blue("Multiple Python directories found:"))
for pdir in dirs:
print_info(red(" # ")+blue("/usr/lib/%s" % (pdir,) ))
old_pdir = os.path.join("/usr/lib/",dirs[0])
print_info(brown(" @@ ")+blue("Scanning: %s" % (red(old_pdir),)))
old_pdir = old_pdir.replace("/usr/lib","/usr/lib*")
idpackages = text_query.searchBelongs(files = [old_pdir], idreturn = True, dbconn = Equo.clientDbconn)
if not idpackages:
print_info(brown(" @@ ")+blue("There are no files in %s whose belong to your old Python." % (old_pdir,)))
return 0
print_info(brown(" @@ ")+blue("These are the installed packages whose have files in %s:" % (red(old_pdir),)))
atoms = set()
for idpackage in idpackages:
atom = Equo.clientDbconn.retrieveAtom(idpackage)
atoms.add((atom, idpackage))
print_info(red(" # ")+atom)
print_info(brown(" @@ ")+blue("Searching inside available repositories..."))
atoms = list(atoms)
atoms.sort()
matchedAtoms = set()
for meta in atoms:
atomkey = Equo.entropyTools.dep_getkey(meta[0])
slot = Equo.clientDbconn.retrieveSlot(meta[1])
print_info(brown(" @@ ")+red("Matching ")+bold(atomkey)+red(":")+darkgreen(slot), back = True)
match = Equo.atomMatch(atomkey, matchSlot = slot)
if match[0] != -1:
matchedAtoms.add((atomkey+":"+slot,match))
del atoms
del idpackages
# now show, then ask or exit (if pretend)
if not matchedAtoms:
print_info(brown(" @@ ")+blue("There are no files in %s whose belong to your old Python and are stored in configured repositories." % (old_pdir,)))
return 0
rc = text_ui.installPackages(atomsdata = matchedAtoms)
return rc
'''
@description: prints entropy configuration information
@input: dict (bool) -> if True, returns a dictionary with packed info. if False, just print to STDOUT
@output: dictionary or STDOUT
'''
def getinfo(dict = False):
# sysinfo
info = {}
osinfo = os.uname()
info['OS'] = osinfo[0]
info['Kernel'] = osinfo[2]
info['Architecture'] = osinfo[4]
info['Entropy version'] = etpConst['entropyversion']
# variables
info['User protected directories'] = etpConst['configprotect']
info['Collision Protection'] = etpConst['collisionprotect']
info['Gentoo Compatibility'] = etpConst['gentoo-compat']
info['Equo Log Level'] = etpConst['equologlevel']
info['Current branch'] = etpConst['branch']
info['Entropy configuration directory'] = etpConst['confdir']
info['Entropy work directory'] = etpConst['entropyworkdir']
info['Entropy unpack directory'] = etpConst['entropyunpackdir']
info['Entropy packages directory'] = etpConst['packagesbindir']
info['Entropy logging directory'] = etpConst['logdir']
info['Entropy Official Repository identifier'] = etpConst['officialrepositoryid']
info['Entropy API'] = etpConst['etpapi']
info['Equo pidfile'] = etpConst['pidfile']
info['Entropy database tag'] = etpConst['databasestarttag']
info['Repositories'] = etpRepositories
info['System Config'] = etpSys
info['UI Config'] = etpUi
# client database info
conn = False
try:
Equo.clientDbconn.listAllIdPackages()
conn = True
except:
pass
info['Installed database'] = conn
if (conn):
# print db info
info['Removal internal protected directories'] = Equo.clientDbconn.listConfigProtectDirectories()
info['Removal internal protected directory masks'] = Equo.clientDbconn.listConfigProtectDirectories(mask = True)
info['Total installed packages'] = len(Equo.clientDbconn.listAllIdpackages())
# repository databases info (if found on the system)
info['Repository databases'] = {}
for x in etpRepositories:
dbfile = etpRepositories[x]['dbpath']+"/"+etpConst['etpdatabasefile']
if os.path.isfile(dbfile):
# print info about this database
dbconn = Equo.openRepositoryDatabase(x)
info['Repository databases'][x] = {}
info['Repository databases'][x]['Installation internal protected directories'] = dbconn.listConfigProtectDirectories()
info['Repository databases'][x]['Installation internal protected directory masks'] = dbconn.listConfigProtectDirectories(mask = True)
info['Repository databases'][x]['Total available packages'] = len(dbconn.listAllIdpackages())
info['Repository databases'][x]['Database revision'] = Equo.get_repository_revision(x)
info['Repository databases'][x]['Database hash'] = Equo.get_repository_db_file_checksum(x)
if (dict):
return info
import types
keys = info.keys()
keys.sort()
for x in keys:
#print type(info[x])
if type(info[x]) is types.DictType:
toptext = x
ykeys = info[x].keys()
ykeys.sort()
for y in ykeys:
if type(info[x][y]) is types.DictType:
topsubtext = y
zkeys = info[x][y].keys()
zkeys.sort()
for z in zkeys:
print red(toptext)+": "+blue(topsubtext)+" => "+darkgreen(z)+" => "+str(info[x][y][z])
else:
print red(toptext)+": "+blue(y)+" => "+str(info[x][y])
#print info[x]
else:
print red(x)+": "+str(info[x])