summaryrefslogtreecommitdiffstats
path: root/src/lib/Client/Frame.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Client/Frame.py')
-rw-r--r--src/lib/Client/Frame.py120
1 files changed, 75 insertions, 45 deletions
diff --git a/src/lib/Client/Frame.py b/src/lib/Client/Frame.py
index 545d4b584..e33e1a7df 100644
--- a/src/lib/Client/Frame.py
+++ b/src/lib/Client/Frame.py
@@ -5,9 +5,11 @@ installs entries, and generates statistics.
__revision__ = '$Revision$'
import logging
+import sys
import time
import Bcfg2.Client.Tools
+
def cmpent(ent1, ent2):
"""Sort entries."""
if ent1.tag != ent2.tag:
@@ -15,6 +17,7 @@ def cmpent(ent1, ent2):
else:
return cmp(ent1.get('name'), ent2.get('name'))
+
def promptFilter(prompt, entries):
"""Filter a supplied list based on user input."""
ret = []
@@ -25,7 +28,12 @@ def promptFilter(prompt, entries):
else:
iprompt = prompt % (entry.tag, entry.get('name'))
try:
- if raw_input(iprompt) in ['y', 'Y']:
+ # py3k compatibility
+ try:
+ ans = raw_input(iprompt.encode(sys.stdout.encoding, 'replace'))
+ except NameError:
+ ans = input(iprompt)
+ if ans in ['y', 'Y']:
ret.append(entry)
except EOFError:
# python 2.4.3 on CentOS doesn't like ^C for some reason
@@ -35,6 +43,7 @@ def promptFilter(prompt, entries):
continue
return ret
+
def matches_entry(entryspec, entry):
# both are (tag, name)
if entryspec == entry:
@@ -52,11 +61,16 @@ def matches_entry(entryspec, entry):
return False
return True
+
def matches_white_list(entry, whitelist):
- return True in [matches_entry(we, (entry.tag, entry.get('name'))) for we in whitelist]
+ return True in [matches_entry(we, (entry.tag, entry.get('name')))
+ for we in whitelist]
+
def passes_black_list(entry, blacklist):
- return True not in [matches_entry(be, (entry.tag, entry.get('name'))) for be in blacklist]
+ return True not in [matches_entry(be, (entry.tag, entry.get('name')))
+ for be in blacklist]
+
class Frame:
"""Frame is the container for all Tool objects and state information."""
@@ -109,22 +123,7 @@ class Frame:
self.logger.info("Loaded tool drivers:")
self.logger.info([tool.name for tool in self.tools])
- if not self.dryrun and not self.setup['bundle']:
- for cfile in [cfl for cfl in config.findall(".//Path") \
- if cfl.get('name') in self.__important__ and \
- cfl.get('type') == 'file']:
- tl = [t for t in self.tools if t.handlesEntry(cfile) \
- and t.canVerify(cfile)]
- if tl:
- if not tl[0].VerifyPath(cfile, []):
- if self.setup['interactive'] and not \
- promptFilter("Install %s: %s? (y/N):", [cfile]):
- continue
- try:
- self.states[cfile] = tl[0].InstallPath(cfile)
- except:
- self.logger.error("Unexpected tool failure",
- exc_info=1)
+
# find entries not handled by any tools
problems = [entry for struct in config for \
entry in struct if entry not in self.handled]
@@ -134,8 +133,10 @@ class Frame:
self.logger.error(["%s:%s:%s" % (entry.tag, entry.get('type'), \
entry.get('name')) for entry in problems])
self.logger.error("")
- entries = [(entry.tag, entry.get('name')) for struct in config for entry in struct]
- pkgs = [(entry.get('name'), entry.get('origin')) for struct in config for entry in struct if entry.tag == 'Package']
+ entries = [(entry.tag, entry.get('name'))
+ for struct in config for entry in struct]
+ pkgs = [(entry.get('name'), entry.get('origin'))
+ for struct in config for entry in struct if entry.tag == 'Package']
multi = []
for entry in entries[:]:
if entries.count(entry) > 1:
@@ -151,7 +152,6 @@ class Frame:
self.logger.debug("The following packages are prereqs added by Packages:")
self.logger.debug([pkg[0] for pkg in pkgs if pkg[1] == 'Packages'])
-
def __getattr__(self, name):
if name in ['extra', 'handled', 'modified', '__important__']:
ret = []
@@ -162,6 +162,54 @@ class Frame:
return self.__dict__[name]
raise AttributeError(name)
+ def InstallImportant(self):
+ """Install important entries
+
+ We also process the decision mode stuff here because we want to prevent
+ non-whitelisted/blacklisted 'important' entries from being installed
+ prior to determining the decision mode on the client.
+ """
+ # Need to process decision stuff early so that dryrun mode works with it
+ self.whitelist = [entry for entry in self.states \
+ if not self.states[entry]]
+ if self.setup['decision'] == 'whitelist':
+ dwl = self.setup['decision_list']
+ w_to_rem = [e for e in self.whitelist \
+ if not matches_white_list(e, dwl)]
+ if w_to_rem:
+ self.logger.info("In whitelist mode: suppressing installation of:")
+ self.logger.info(["%s:%s" % (e.tag, e.get('name')) for e in w_to_rem])
+ self.whitelist = [x for x in self.whitelist \
+ if x not in w_to_rem]
+
+ elif self.setup['decision'] == 'blacklist':
+ b_to_rem = [e for e in self.whitelist \
+ if not passes_black_list(e, self.setup['decision_list'])]
+ if b_to_rem:
+ self.logger.info("In blacklist mode: suppressing installation of:")
+ self.logger.info(["%s:%s" % (e.tag, e.get('name')) for e in b_to_rem])
+ self.whitelist = [x for x in self.whitelist if x not in b_to_rem]
+
+ # take care of important entries first
+ if not self.dryrun and not self.setup['bundle']:
+ for cfile in [cfl for cfl in self.config.findall(".//Path") \
+ if cfl.get('name') in self.__important__ and \
+ cfl.get('type') == 'file']:
+ if cfile not in self.whitelist:
+ continue
+ tl = [t for t in self.tools if t.handlesEntry(cfile) \
+ and t.canVerify(cfile)]
+ if tl:
+ if not tl[0].VerifyPath(cfile, []):
+ if self.setup['interactive'] and not \
+ promptFilter("Install %s: %s? (y/N):", [cfile]):
+ continue
+ try:
+ self.states[cfile] = tl[0].InstallPath(cfile)
+ except:
+ self.logger.error("Unexpected tool failure",
+ exc_info=1)
+
def Inventory(self):
"""
Verify all entries,
@@ -186,35 +234,15 @@ class Frame:
if self.setup['remove']:
if self.setup['remove'] == 'all':
self.removal = self.extra
- elif self.setup['remove'] == 'services':
+ elif self.setup['remove'] in ['services', 'Services']:
self.removal = [entry for entry in self.extra \
if entry.tag == 'Service']
- elif self.setup['remove'] == 'packages':
+ elif self.setup['remove'] in ['packages', 'Packages']:
self.removal = [entry for entry in self.extra \
if entry.tag == 'Package']
candidates = [entry for entry in self.states \
if not self.states[entry]]
- self.whitelist = [entry for entry in self.states \
- if not self.states[entry]]
- # Need to process decision stuff early so that dryrun mode works with it
- if self.setup['decision'] == 'whitelist':
- dwl = self.setup['decision_list']
- w_to_rem = [e for e in self.whitelist \
- if not matches_white_list(e, dwl)]
- if w_to_rem:
- self.logger.info("In whitelist mode: suppressing installation of:")
- self.logger.info(["%s:%s" % (e.tag, e.get('name')) for e in w_to_rem])
- self.whitelist = [x for x in self.whitelist \
- if x not in w_to_rem]
-
- elif self.setup['decision'] == 'blacklist':
- b_to_rem = [e for e in self.whitelist \
- if not passes_black_list(e, self.setup['decision_list'])]
- if b_to_rem:
- self.logger.info("In blacklist mode: suppressing installation of:")
- self.logger.info(["%s:%s" % (e.tag, e.get('name')) for e in b_to_rem])
- self.whitelist = [x for x in self.whitelist if x not in b_to_rem]
if self.dryrun:
if self.whitelist:
@@ -268,7 +296,8 @@ class Frame:
if b_to_remv:
self.logger.info("Not installing entries from Bundle %s" % \
(bundle.get('name')))
- self.logger.info(["%s:%s" % (e.tag, e.get('name')) for e in b_to_remv])
+ self.logger.info(["%s:%s" % (e.tag, e.get('name'))
+ for e in b_to_remv])
[self.whitelist.remove(ent) for ent in b_to_remv]
if self.setup['interactive']:
@@ -373,6 +402,7 @@ class Frame:
self.Inventory()
self.times['inventory'] = time.time()
self.CondDisplayState('initial')
+ self.InstallImportant()
self.Decide()
self.Install()
self.times['install'] = time.time()