introducing configuration management tools
git-svn-id: http://svn.sabayonlinux.org/projects/entropy/trunk@539 cd1c1023-2f26-0410-ae45-c471fc1f0318
This commit is contained in:
@@ -3,6 +3,8 @@ TODO list:
|
||||
CLIENT:
|
||||
- trap elogs in reagent
|
||||
- add etc-update alike support
|
||||
- rewrite the bash stuff in python
|
||||
- add cached scan stuff
|
||||
- add env-update alike support
|
||||
- add preinst/postinst/prerm/postrm scripts
|
||||
- move branches to version naming (3.5, 3.6, 3.7) instead of using stable, unstable...
|
||||
@@ -24,6 +26,7 @@ TODO list:
|
||||
- world looks inside the latest (if run with "upgrade")
|
||||
- world: add --prune option that removes packages not available anymore
|
||||
- world upgrade should switch python to 2.5
|
||||
- if a mirror fails several times, disable it
|
||||
|
||||
|
||||
Project Status:
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/python
|
||||
'''
|
||||
# DESCRIPTION:
|
||||
# Packages configuration files handling function (etc-update alike)
|
||||
|
||||
Copyright (C) 2007 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
|
||||
'''
|
||||
|
||||
import sys
|
||||
import commands
|
||||
sys.path.append('../libraries')
|
||||
from entropyConstants import *
|
||||
from clientConstants import *
|
||||
from outputTools import *
|
||||
import entropyTools
|
||||
from equoTools import openClientDatabase, closeClientDatabase
|
||||
|
||||
# test if diff is installed
|
||||
difftest = entropyTools.spawnCommand("diff -v", redirect = "&> /dev/null")
|
||||
if (difftest):
|
||||
print "ERROR: diff not found, cannot continue"
|
||||
|
||||
########################################################
|
||||
####
|
||||
## Configuration Tools
|
||||
#
|
||||
|
||||
def configurator(options):
|
||||
|
||||
rc = 0
|
||||
if len(options) < 1:
|
||||
return rc
|
||||
|
||||
equoRequestVerbose = False
|
||||
equoRequestQuiet = False
|
||||
myopts = []
|
||||
for opt in options:
|
||||
if (opt == "--verbose"):
|
||||
equoRequestVerbose = True
|
||||
elif (opt == "--quiet"):
|
||||
equoRequestQuiet = True
|
||||
else:
|
||||
if not opt.startswith("-"):
|
||||
myopts.append(opt)
|
||||
|
||||
if myopts[0] == "info":
|
||||
rc = confinfo()
|
||||
|
||||
#elif options[0] == "belongs":
|
||||
#rc = searchBelongs(myopts[1:], quiet = equoRequestQuiet)
|
||||
|
||||
return rc
|
||||
|
||||
'''
|
||||
@description: scan for files that need to be merged
|
||||
@output: dictionary using filename as key
|
||||
'''
|
||||
def scanfs(quiet = True):
|
||||
# load etpConst['dbconfigprotect']
|
||||
clientDbconn = openClientDatabase()
|
||||
closeClientDatabase(clientDbconn)
|
||||
# etpConst['dbconfigprotect']
|
||||
if (not quiet): print_info(yellow(" @@ ")+darkgreen("Scanning filesystem..."))
|
||||
scandata = {}
|
||||
counter = 0
|
||||
for path in etpConst['dbconfigprotect']:
|
||||
# it's a file?
|
||||
deep = True
|
||||
if os.path.isfile(path):
|
||||
# find inside basename
|
||||
path = os.path.basename(path)
|
||||
deep = False
|
||||
|
||||
for currentdir,subdirs,files in os.walk(path):
|
||||
for file in files:
|
||||
filepath = currentdir+"/"+file
|
||||
if file.startswith("._cfg"):
|
||||
# further check then
|
||||
number = file[5:9]
|
||||
try:
|
||||
int(number)
|
||||
except:
|
||||
continue # not a valid etc-update file
|
||||
if file[9] != "_": # no valid format provided
|
||||
continue
|
||||
# FIXME: add automerging trivial changes
|
||||
tofile = file[10:]
|
||||
tofilepath = currentdir+"/"+tofile
|
||||
scandata[filepath] = {}
|
||||
scandata[filepath]['revision'] = number
|
||||
scandata[filepath]['destination'] = tofilepath
|
||||
if os.path.isfile(tofilepath):
|
||||
scandata[filepath]['automerge'] = False
|
||||
else:
|
||||
scandata[filepath]['automerge'] = True
|
||||
counter += 1
|
||||
try:
|
||||
if (not quiet): print_info("("+blue(str(counter))+") "+red(" Found file: ")+filepath)
|
||||
except:
|
||||
pass # possible encoding issues
|
||||
return scandata
|
||||
|
||||
|
||||
|
||||
'''
|
||||
@description: prints information about config files that should be updated
|
||||
'''
|
||||
def confinfo():
|
||||
|
||||
print_info(yellow(" @@ ")+darkgreen("Loading information..."), back = True)
|
||||
data = scanfs(quiet = False)
|
||||
print len(data)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
+12
-3
@@ -47,7 +47,7 @@ def print_help():
|
||||
print_info(" \t\t"+red("--fetch")+"\t\t\t just download packages without doing the install")
|
||||
print_info(" \t\t"+red("--pretend")+"\t\t just show what would be done")
|
||||
print_info(" \t\t"+red("--verbose")+"\t\t show more details about what's going on")
|
||||
print_info(" \t"+blue("install")+brown("\t\t install a package"))
|
||||
print_info(" \t"+blue("install")+brown("\t\t install one or more packages"))
|
||||
print_info(" \t\t"+red("--ask")+"\t\t\t ask before making any changes")
|
||||
print_info(" \t\t"+red("--pretend")+"\t\t just show what would be done")
|
||||
print_info(" \t\t"+red("--fetch")+"\t\t\t just download packages without doing the install")
|
||||
@@ -56,7 +56,7 @@ def print_help():
|
||||
print_info(" \t\t"+red("--deep")+"\t\t\t analyze dependencies deeply")
|
||||
print_info(" \t\t"+red("--verbose")+"\t\t show more details about what's going on")
|
||||
print_info(" \t\t"+red("--configfiles")+"\t\t also remove old configuration files [use with care]")
|
||||
print_info(" \t"+blue("remove")+brown("\t\t remove a package"))
|
||||
print_info(" \t"+blue("remove")+brown("\t\t remove one or more packages"))
|
||||
print_info(" \t\t"+red("--deep")+"\t\t\t also pull unused dependencies where depends list is empty")
|
||||
print_info(" \t\t"+red("--configfiles")+"\t\t also remove configuration files")
|
||||
print_info(" \t"+blue("deptest")+brown("\t\t look for unsatisfied dependencies"))
|
||||
@@ -64,6 +64,9 @@ def print_help():
|
||||
print_info(" \t\t"+red("--ask")+"\t\t\t ask before making any changes")
|
||||
print_info(" \t\t"+red("--pretend")+"\t\t just show what would be done")
|
||||
|
||||
print_info(" \t"+blue("conf")+brown("\t\t configuration files update tool"))
|
||||
print_info(" \t\t"+darkgreen("info")+red("\t\t\t show info about configuration files that should be updated"))
|
||||
|
||||
print_info(" \t"+blue(bold("query"))+brown("\t\t do misc queries on repository and local databases"))
|
||||
print_info(" \t\t"+darkgreen("installed")+red("\t\t search a package into the local database"))
|
||||
print_info(" \t\t"+darkgreen("belongs")+red("\t\t\t search from what package a file belongs"))
|
||||
@@ -83,6 +86,7 @@ def print_help():
|
||||
print_info(" \t\t"+darkgreen("depends")+red("\t\t\t to regenerate/generate depends caching table"))
|
||||
print_info(" \t"+blue("cleanup")+brown("\t\t remove downloaded packages and clean temporary directories"))
|
||||
print_info(" \t"+blue("--info")+brown("\t\t show Equo System information"))
|
||||
|
||||
|
||||
options = sys.argv[1:]
|
||||
|
||||
@@ -95,7 +99,6 @@ if len(options) < 1 or string.join(options).find("--help") != -1 or string.join(
|
||||
|
||||
|
||||
import equoTools
|
||||
import queryTools
|
||||
import entropyTools
|
||||
from entropyConstants import *
|
||||
from clientConstants import *
|
||||
@@ -153,9 +156,15 @@ try:
|
||||
sys.exit(rc)
|
||||
|
||||
elif (options[0] == "query"):
|
||||
import queryTools
|
||||
rc = queryTools.query(options[1:])
|
||||
sys.exit(rc)
|
||||
|
||||
elif (options[0] == "conf"):
|
||||
import confTools
|
||||
rc = confTools.configurator(options[1:])
|
||||
sys.exit(rc)
|
||||
|
||||
elif (options[0] == "search"):
|
||||
if len(options) > 1:
|
||||
rc = queryTools.searchPackage(options[1:])
|
||||
|
||||
+65
-57
@@ -1089,7 +1089,7 @@ def removePackage(infoDict):
|
||||
# collision check
|
||||
if etpConst['collisionprotect'] > 0:
|
||||
if file in contentCache:
|
||||
print "DEBUG!! [remove]: collision found for "+file.encode(sys.getfilesystemencoding()) #FIXME: beautify
|
||||
print_warning(yellow(" ## ")+red("Collision found during remove for ")+file.encode(sys.getfilesystemencoding())+" - cannot overwrite")
|
||||
continue
|
||||
try:
|
||||
del contentCache[file]
|
||||
@@ -1099,25 +1099,28 @@ def removePackage(infoDict):
|
||||
|
||||
protected = False
|
||||
if (not infoDict['removeconfig']):
|
||||
# -- CONFIGURATION FILE PROTECTION --
|
||||
if os.access(file,os.R_OK):
|
||||
for x in protect:
|
||||
if file.startswith(x):
|
||||
protected = True
|
||||
break
|
||||
if (protected):
|
||||
for x in mask:
|
||||
try:
|
||||
# -- CONFIGURATION FILE PROTECTION --
|
||||
if os.access(file,os.R_OK):
|
||||
for x in protect:
|
||||
if file.startswith(x):
|
||||
protected = False
|
||||
break
|
||||
if (protected) and os.path.isfile(file):
|
||||
protected = istextfile(file)
|
||||
else:
|
||||
protected = False # it's not a file
|
||||
# -- CONFIGURATION FILE PROTECTION --
|
||||
protected = True
|
||||
break
|
||||
if (protected):
|
||||
for x in mask:
|
||||
if file.startswith(x):
|
||||
protected = False
|
||||
break
|
||||
if (protected) and os.path.isfile(file):
|
||||
protected = istextfile(file)
|
||||
else:
|
||||
protected = False # it's not a file
|
||||
# -- CONFIGURATION FILE PROTECTION --
|
||||
except:
|
||||
pass # some filenames are buggy encoded
|
||||
|
||||
if (protected):
|
||||
print "DEBUG: PROTECTED -> "+str(file)
|
||||
print_warning(yellow(" ## ")+red("Protecting config file: ")+str(file))
|
||||
else:
|
||||
try:
|
||||
os.remove(file)
|
||||
@@ -1214,54 +1217,59 @@ def installPackage(infoDict):
|
||||
|
||||
if etpConst['collisionprotect'] > 1:
|
||||
if tofile in contentCache:
|
||||
print "DEBUG!! [install]: collision found for "+file.encode(sys.getfilesystemencoding()) #FIXME: beautify
|
||||
print_warning(yellow(" ## ")+red("Collision found during install for ")+file.encode(sys.getfilesystemencoding())+" - cannot overwrite")
|
||||
print_warning(yellow(" ## ")+red("Protecting config file: ")+str(tofile))
|
||||
continue
|
||||
|
||||
# -- CONFIGURATION FILE PROTECTION --
|
||||
|
||||
protected = False
|
||||
for x in protect:
|
||||
if tofile.startswith(x):
|
||||
protected = True
|
||||
break
|
||||
if (protected): # check if perhaps, file is masked, so unprotected
|
||||
for x in mask:
|
||||
|
||||
try:
|
||||
protected = False
|
||||
for x in protect:
|
||||
if tofile.startswith(x):
|
||||
protected = False
|
||||
break
|
||||
protected = True
|
||||
break
|
||||
if (protected): # check if perhaps, file is masked, so unprotected
|
||||
for x in mask:
|
||||
if tofile.startswith(x):
|
||||
protected = False
|
||||
break
|
||||
|
||||
if os.access(tofile,os.F_OK):
|
||||
try:
|
||||
if not protected: os.remove(tofile)
|
||||
except:
|
||||
if not protected:
|
||||
rc = os.system("rm -f "+tofile)
|
||||
if (rc != 0):
|
||||
return 3
|
||||
else:
|
||||
protected = False # file doesn't exist
|
||||
if os.access(tofile,os.F_OK):
|
||||
try:
|
||||
if not protected: os.remove(tofile)
|
||||
except:
|
||||
if not protected:
|
||||
rc = os.system("rm -f "+tofile)
|
||||
if (rc != 0):
|
||||
return 3
|
||||
else:
|
||||
protected = False # file doesn't exist
|
||||
|
||||
# check if it's a text file
|
||||
if (protected) and os.path.isfile(tofile):
|
||||
protected = istextfile(tofile)
|
||||
else:
|
||||
protected = False # it's not a file
|
||||
# check if it's a text file
|
||||
if (protected) and os.path.isfile(tofile):
|
||||
protected = istextfile(tofile)
|
||||
else:
|
||||
protected = False # it's not a file
|
||||
|
||||
# check md5
|
||||
if (protected) and os.path.isfile(tofile) and os.path.isfile(fromfile):
|
||||
mymd5 = md5sum(fromfile)
|
||||
sysmd5 = md5sum(tofile)
|
||||
if mymd5 == sysmd5:
|
||||
protected = False # files are the same
|
||||
else:
|
||||
protected = False # a broken symlink inside our image dir
|
||||
# check md5
|
||||
if (protected) and os.path.isfile(tofile) and os.path.isfile(fromfile):
|
||||
mymd5 = md5sum(fromfile)
|
||||
sysmd5 = md5sum(tofile)
|
||||
if mymd5 == sysmd5:
|
||||
protected = False # files are the same
|
||||
else:
|
||||
protected = False # a broken symlink inside our image dir
|
||||
|
||||
# request new tofile then
|
||||
if (protected):
|
||||
print "DEBUG: PROTECTED ->"+str(tofile)
|
||||
tofile = allocateMaskedFile(tofile)
|
||||
# request new tofile then
|
||||
if (protected):
|
||||
print_warning(yellow(" ## ")+red("Protecting config file: ")+str(tofile))
|
||||
tofile = allocateMaskedFile(tofile)
|
||||
|
||||
# -- CONFIGURATION FILE PROTECTION --
|
||||
# -- CONFIGURATION FILE PROTECTION --
|
||||
|
||||
except:
|
||||
pass # some files are buggy encoded
|
||||
|
||||
try:
|
||||
# this also handles symlinks
|
||||
@@ -1269,7 +1277,7 @@ def installPackage(infoDict):
|
||||
try:
|
||||
packageContent.append(tofile.encode("utf-8"))
|
||||
except:
|
||||
print_error("DEBUG!!: file error: "+str(tofile)+" cannot be converted into UTF-8, skipping")
|
||||
print_warning(yellow(" ## ")+red("Cannot convert filename into UTF-8, skipping ")+str(tofile))
|
||||
pass
|
||||
except IOError,(errno,strerror):
|
||||
if errno == 2:
|
||||
|
||||
@@ -57,32 +57,32 @@ def query(options):
|
||||
if not opt.startswith("-"):
|
||||
myopts.append(opt)
|
||||
|
||||
if options[0] == "installed":
|
||||
if myopts[0] == "installed":
|
||||
rc = searchInstalledPackages(myopts[1:], quiet = equoRequestQuiet)
|
||||
|
||||
elif options[0] == "belongs":
|
||||
elif myopts[0] == "belongs":
|
||||
rc = searchBelongs(myopts[1:], quiet = equoRequestQuiet)
|
||||
|
||||
elif options[0] == "depends":
|
||||
elif myopts[0] == "depends":
|
||||
rc = searchDepends(myopts[1:], verbose = equoRequestVerbose, quiet = equoRequestQuiet)
|
||||
|
||||
elif options[0] == "files":
|
||||
elif myopts[0] == "files":
|
||||
rc = searchFiles(myopts[1:], quiet = equoRequestQuiet)
|
||||
|
||||
elif options[0] == "removal":
|
||||
elif myopts[0] == "removal":
|
||||
rc = searchRemoval(myopts[1:], quiet = equoRequestQuiet, deep = equoRequestDeep)
|
||||
|
||||
elif options[0] == "orphans":
|
||||
elif myopts[0] == "orphans":
|
||||
rc = searchOrphans(quiet = equoRequestQuiet)
|
||||
|
||||
elif options[0] == "list":
|
||||
elif myopts[0] == "list":
|
||||
mylistopts = options[1:]
|
||||
if len(mylistopts) > 0:
|
||||
if mylistopts[0] == "installed":
|
||||
rc = searchInstalled(verbose = equoRequestVerbose, quiet = equoRequestQuiet)
|
||||
# add more here
|
||||
|
||||
elif options[0] == "description":
|
||||
elif myopts[0] == "description":
|
||||
rc = searchDescription(myopts[1:], quiet = equoRequestQuiet)
|
||||
|
||||
return rc
|
||||
|
||||
Reference in New Issue
Block a user