summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alexander@sulfrian.net>2012-11-01 02:25:57 +0100
committerAlexander Sulfrian <alexander@sulfrian.net>2013-01-30 01:22:51 +0100
commita128b27aabc246c74fc407c93fc8b696f8f1bd92 (patch)
tree0acd3fa94007be86e3468b5c08f56933e65669d3
parent540e2bc637ac99e60bc236a62ff8e885a705b562 (diff)
downloadbcfg2-a128b27aabc246c74fc407c93fc8b696f8f1bd92.tar.gz
bcfg2-a128b27aabc246c74fc407c93fc8b696f8f1bd92.tar.bz2
bcfg2-a128b27aabc246c74fc407c93fc8b696f8f1bd92.zip
Packages: ability to overwrite recommended flag per package
-rw-r--r--schemas/pkgtype.xsd1
-rw-r--r--src/lib/Server/Plugins/Packages/Apt.py49
-rw-r--r--src/lib/Server/Plugins/Packages/Collection.py12
-rw-r--r--src/lib/Server/Plugins/Packages/Source.py2
-rw-r--r--src/lib/Server/Plugins/Packages/Yum.py8
-rw-r--r--src/lib/Server/Plugins/Packages/__init__.py5
6 files changed, 62 insertions, 15 deletions
diff --git a/schemas/pkgtype.xsd b/schemas/pkgtype.xsd
index c49b4f53b..2dceb8419 100644
--- a/schemas/pkgtype.xsd
+++ b/schemas/pkgtype.xsd
@@ -20,6 +20,7 @@
<xsd:attribute type="PackageGroupTypeEnum" name="type"
use="optional"/>
<xsd:attribute type="xsd:string" name="src" use="optional"/>
+ <xsd:attribute type="xsd:boolean" name="recommended" use="optional"/>
<xsd:attributeGroup ref="py:genshiAttrs"/>
</xsd:complexType>
diff --git a/src/lib/Server/Plugins/Packages/Apt.py b/src/lib/Server/Plugins/Packages/Apt.py
index d999e21c8..0c0c95e70 100644
--- a/src/lib/Server/Plugins/Packages/Apt.py
+++ b/src/lib/Server/Plugins/Packages/Apt.py
@@ -17,6 +17,7 @@ class AptSource(Source):
Source.__init__(self, basepath, xsource, config)
self.pkgnames = set()
self.versions = dict()
+ self.recommends = dict()
self.url_map = [{'rawurl': self.rawurl, 'url': self.url,
'version': self.version,
@@ -25,13 +26,13 @@ class AptSource(Source):
def save_state(self):
cache = file(self.cachefile, 'wb')
cPickle.dump((self.pkgnames, self.deps, self.provides,
- self.versions),
+ self.versions, self.recommends),
cache, 2)
cache.close()
def load_state(self):
data = file(self.cachefile)
- self.pkgnames, self.deps, self.provides, self.versions = cPickle.load(data)
+ self.pkgnames, self.deps, self.provides, self.versions, self.recommends = cPickle.load(data)
def filter_unknown(self, unknown):
filtered = set([u for u in unknown if u.startswith('choice')])
@@ -51,6 +52,7 @@ class AptSource(Source):
def read_files(self):
bdeps = dict()
+ brecs = dict()
bprov = dict()
self.versions = dict()
if self.recommended:
@@ -68,6 +70,7 @@ class AptSource(Source):
barch = self.arches[0]
if barch not in bdeps:
bdeps[barch] = dict()
+ brecs[barch] = dict()
bprov[barch] = dict()
self.versions[barch] = dict()
try:
@@ -81,7 +84,8 @@ class AptSource(Source):
pkgname = words[1].strip().rstrip()
self.pkgnames.add(pkgname)
bdeps[barch][pkgname] = []
- elif words[0] in depfnames:
+ brecs[barch][pkgname] = []
+ elif words[0] in ['Depends', 'Pre-Depends', 'Recommends']:
vindex = 0
for dep in words[1].split(','):
if '|' in dep:
@@ -92,12 +96,19 @@ class AptSource(Source):
barch,
vindex)
vindex += 1
- bdeps[barch][pkgname].append(dyn_dname)
+
+ if words[0] == 'Recommends':
+ brecs[barch][pkgname].append(dyn_dname)
+ else:
+ bdeps[barch][pkgname].append(dyn_dname)
bprov[barch][dyn_dname] = set(cdeps)
else:
raw_dep = re.sub('\(.*\)', '', dep)
raw_dep = raw_dep.rstrip().strip()
- bdeps[barch][pkgname].append(raw_dep)
+ if words[0] == 'Recommends':
+ brecs[barch][pkgname].append(raw_dep)
+ else:
+ bdeps[barch][pkgname].append(raw_dep)
elif words[0] == 'Provides':
for pkg in words[1].split(','):
dname = pkg.rstrip().strip()
@@ -108,12 +119,15 @@ class AptSource(Source):
self.versions[barch][pkgname] = words[1].rstrip().strip()
self.deps['global'] = dict()
+ self.recommends['global'] = dict()
self.provides['global'] = dict()
for barch in bdeps:
self.deps[barch] = dict()
+ self.recommends[barch] = dict()
self.provides[barch] = dict()
for pkgname in self.pkgnames:
pset = set()
+ rset = set()
for barch in bdeps:
if pkgname not in bdeps[barch]:
bdeps[barch][pkgname] = []
@@ -123,6 +137,17 @@ class AptSource(Source):
else:
for barch in bdeps:
self.deps[barch][pkgname] = bdeps[barch][pkgname]
+
+ for barch in brecs:
+ if pkgname not in brecs[barch]:
+ brecs[barch][pkgname] = []
+ rset.add(tuple(brecs[barch][pkgname]))
+ if len(rset) == 1:
+ self.recommends['global'][pkgname] = rset.pop()
+ else:
+ for barch in brecs:
+ self.recommends[barch][pkgname] = brecs[barch][pkgname]
+
provided = set()
for bprovided in list(bprov.values()):
provided.update(set(bprovided))
@@ -139,6 +164,20 @@ class AptSource(Source):
self.provides[barch][prov] = bprov[barch].get(prov, ())
self.save_state()
+ def get_deps(self, metadata, pkgname, recommended=None):
+ recs = []
+ if ((recommended is None and self.recommended) or
+ (recommended and recommended.lower() == 'true')):
+ for arch in self.get_arches(metadata):
+ if pkgname in self.recommends[arch]:
+ recs.extend(self.recommends[arch][pkgname])
+
+ for arch in self.get_arches(metadata):
+ if pkgname in self.deps[arch]:
+ recs.extend(self.deps[arch][pkgname])
+
+ return recs
+
def is_package(self, _, pkg):
return (pkg in self.pkgnames and
pkg not in self.blacklist and
diff --git a/src/lib/Server/Plugins/Packages/Collection.py b/src/lib/Server/Plugins/Packages/Collection.py
index e0c7e338f..d2d8a015d 100644
--- a/src/lib/Server/Plugins/Packages/Collection.py
+++ b/src/lib/Server/Plugins/Packages/Collection.py
@@ -91,20 +91,24 @@ class Collection(Bcfg2.Server.Plugin.Debuggable):
return True
return False
- def get_deps(self, package, pinnings=None):
+ def get_deps(self, package, pinnings=None, recs=None):
pin_found = False
pin_source = None
if pinnings and package in pinnings:
pin_source = pinnings[package]
+ recommended = None
+ if recs and package in recs:
+ recommended = recs[package]
+
for source in self.sources:
if pin_source and pin_source != source.name:
continue
pin_found = True
if source.is_package(self.metadata, package):
- return source.get_deps(self.metadata, package)
+ return source.get_deps(self.metadata, package, recommended)
if not pin_found:
self.logger.error("Packages: Source '%s' for package '%s' not found" %
@@ -152,7 +156,7 @@ class Collection(Bcfg2.Server.Plugin.Debuggable):
""" do any collection-level data setup tasks """
pass
- def complete(self, packagelist, pinnings=None):
+ def complete(self, packagelist, pinnings=None, recommended=None):
'''Build the transitive closure of all package dependencies
Arguments:
@@ -213,7 +217,7 @@ class Collection(Bcfg2.Server.Plugin.Debuggable):
self.debug_log("Packages: handling package requirement %s" %
current)
packages.add(current)
- deps = self.get_deps(current, pinnings)
+ deps = self.get_deps(current, pinnings, recommended)
newdeps = set(deps).difference(examined)
if newdeps:
self.debug_log("Packages: Package %s added requirements %s"
diff --git a/src/lib/Server/Plugins/Packages/Source.py b/src/lib/Server/Plugins/Packages/Source.py
index d94bcca14..d19d23442 100644
--- a/src/lib/Server/Plugins/Packages/Source.py
+++ b/src/lib/Server/Plugins/Packages/Source.py
@@ -250,7 +250,7 @@ class Source(Bcfg2.Server.Plugin.Debuggable):
def get_arches(self, metadata):
return ['global'] + [a for a in self.arches if a in metadata.groups]
- def get_deps(self, metadata, pkgname):
+ def get_deps(self, metadata, pkgname, recommended=None):
for arch in self.get_arches(metadata):
if pkgname in self.deps[arch]:
return self.deps[arch][pkgname]
diff --git a/src/lib/Server/Plugins/Packages/Yum.py b/src/lib/Server/Plugins/Packages/Yum.py
index 8543b44e4..74eee2662 100644
--- a/src/lib/Server/Plugins/Packages/Yum.py
+++ b/src/lib/Server/Plugins/Packages/Yum.py
@@ -355,9 +355,9 @@ class YumCollection(Collection):
# for API completeness
return self.call_helper("is_virtual_package", package)
- def get_deps(self, package, pinnings):
+ def get_deps(self, package, pinnings=None, recommended=None):
if not self.use_yum:
- return Collection.get_deps(self, package, pinnings)
+ return Collection.get_deps(self, package, pinnings, recommended)
else:
# this should really never get called; it's just provided
# for API completeness
@@ -383,9 +383,9 @@ class YumCollection(Collection):
pkgs = self.call_helper("get_group", dict(group=group, type=ptype))
return pkgs
- def complete(self, packagelist, pinnings):
+ def complete(self, packagelist, pinnings=None, recommended=None):
if not self.use_yum:
- return Collection.complete(self, packagelist, pinnings)
+ return Collection.complete(self, packagelist, pinnings, recommended)
packages = set()
unknown = set(packagelist)
diff --git a/src/lib/Server/Plugins/Packages/__init__.py b/src/lib/Server/Plugins/Packages/__init__.py
index 637560de5..e94b79c6d 100644
--- a/src/lib/Server/Plugins/Packages/__init__.py
+++ b/src/lib/Server/Plugins/Packages/__init__.py
@@ -150,6 +150,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
# base is the set of initial packages with groups expanded
base = set()
pinned_src = dict()
+ recommended = dict()
to_remove = []
for struct in structures:
for pkg in struct.xpath('//Package | //BoundPackage'):
@@ -158,6 +159,8 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
if pkg.get("src"):
pinned_src[pkg.get("name")] = pkg.get("src")
+ if pkg.get("recommended"):
+ recommended[pkg.get("name")] = pkg.get("recommended")
elif pkg.get("group"):
try:
if pkg.get("type"):
@@ -178,7 +181,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
for el in to_remove:
el.getparent().remove(el)
- packages, unknown = collection.complete(base, pinned_src)
+ packages, unknown = collection.complete(base, pinned_src, recommended)
if unknown:
self.logger.info("Packages: Got %d unknown entries" % len(unknown))
self.logger.info("Packages: %s" % list(unknown))