summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2011-08-01 09:48:35 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2011-08-01 09:48:35 -0400
commit066aad5e10c05133b8650a50f18f44c9de276030 (patch)
tree21a0623660ac97ad49f5efe27602dd2a5c2a2fbf /tools
parent6fdffa2059e19567fe46d8f48eda6bb3f461caea (diff)
downloadbcfg2-066aad5e10c05133b8650a50f18f44c9de276030.tar.gz
bcfg2-066aad5e10c05133b8650a50f18f44c9de276030.tar.bz2
bcfg2-066aad5e10c05133b8650a50f18f44c9de276030.zip
Lots of improvements to Packages plugin:
* Better config handling: Split into packages.conf (which contains one-time configuration directives) and sources.xml (which contains the actual package sources.) The config file looks like a StructFile, and supports <Client> tags and negated Client and Group tags. Packages.Reload (_not_ Refresh) is run on changes to the sources config. tools/packages-convert.py is provided to convert to the new format. * Automagic handling of GPG keys. The new config format handles association of GPG keys go with repos; Packages then Does The Right Thing and gets them to the clients, gets them installed properly, and handles them in the specification. At the moment this only works for yum repos, not APT (see below). * Automatic generation of yum configs using the sources and GPG keys supplied. APT configs are not done yet (see below). * The early vestiges of integration with Pulp (pulpproject.org). Yet to do: * Better support for Pulp; documentation on Pulp integration. * APT support for key handling and config generation.
Diffstat (limited to 'tools')
-rwxr-xr-xtools/packages-convert.py117
1 files changed, 117 insertions, 0 deletions
diff --git a/tools/packages-convert.py b/tools/packages-convert.py
new file mode 100755
index 000000000..c7b43279f
--- /dev/null
+++ b/tools/packages-convert.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import lxml.etree
+from Bcfg2.Bcfg2Py3k import ConfigParser
+import Bcfg2.Options
+
+XI_NAMESPACE = "http://www.w3.org/2001/XInclude"
+XI = "{%s}" % XI_NAMESPACE
+
+def place_source(xdata, source, groups):
+ """ given a source's group memberships, place it appropriately
+ within the given XML document tree """
+ if not groups:
+ xdata.append(source)
+ else:
+ for group in groups:
+ match = xdata.xpath("Group[@name='%s']" % group)
+ if match:
+ groups.remove(group)
+ xdata.replace(match[0], place_source(match[0], source, groups))
+ return xdata
+
+ # no group found to put this source into
+ group = groups.pop()
+ xdata.append(place_source(lxml.etree.Element("Group", name=group),
+ source, groups))
+
+ return xdata
+
+def main():
+ opts = {'repo': Bcfg2.Options.SERVER_REPOSITORY}
+ setup = Bcfg2.Options.OptionParser(opts)
+ setup.parse(sys.argv[1:])
+ repo = setup['repo']
+ configpath = os.path.join(repo, 'Packages')
+ oldconfigfile = os.path.join(configpath, 'config.xml')
+ newconfigfile = os.path.join(configpath, 'packages.conf')
+ newsourcesfile = os.path.join(configpath, 'sources.xml')
+
+ if not os.path.exists(oldconfigfile):
+ print("%s does not exist, nothing to do" % oldconfigfile)
+ return 1
+
+ if not os.path.exists(configpath):
+ print("%s does not exist, cannot write %s" % (configpath,
+ newconfigfile))
+ return 2
+
+ newconfig = ConfigParser.SafeConfigParser()
+ newconfig.add_section("global")
+
+ oldconfig = lxml.etree.parse(oldconfigfile).getroot()
+
+ config = oldconfig.xpath('//Sources/Config')
+ if config:
+ if config[0].get("resolver", "enabled").lower() == "disabled":
+ newconfig.add_option("global", "resolver", "disabled")
+ if config[0].get("metadata", "enabled").lower() == "disabled":
+ newconfig.add_option("global", "metadata", "disabled")
+ newconfig.write(open(newconfigfile, "w"))
+ print("%s written" % newconfigfile)
+
+ oldsources = [oldconfigfile]
+ while oldsources:
+ oldfile = oldsources.pop()
+ oldsource = lxml.etree.parse(oldfile).getroot()
+
+ if oldfile == oldconfigfile:
+ newfile = newsourcesfile
+ else:
+ newfile = os.path.join(configpath,
+ oldfile.replace("%s/" % configpath, ''))
+ newsource = lxml.etree.Element("Sources", nsmap=oldsource.nsmap)
+
+ for el in oldsource.getchildren():
+ if el.tag == lxml.etree.Comment or el.tag == 'Config':
+ # skip comments and Config
+ continue
+
+ if el.tag == XI + 'include':
+ oldsources.append(os.path.join(configpath, el.get('href')))
+ newsource.append(el)
+ continue
+
+ # element must be a *Source
+ newel = lxml.etree.Element("Source",
+ type=el.tag.replace("Source",
+ "").lower())
+ try:
+ newel.set('recommended', el.find('Recommended').text.lower())
+ except AttributeError:
+ pass
+
+ for tag in ['RawURL', 'URL', 'Version']:
+ try:
+ newel.set(tag.lower(), el.find(tag).text)
+ except AttributeError:
+ pass
+
+ for child in el.getchildren():
+ if child.tag in ['Component', 'Blacklist', 'Whitelist', 'Arch']:
+ newel.append(child)
+
+ groups = [e.text for e in el.findall("Group")]
+ newsource = place_source(newsource, newel, groups)
+
+ try:
+ open(newfile, 'w').write(lxml.etree.tostring(newsource,
+ pretty_print=True))
+ print("%s written" % newfile)
+ except IOError:
+ print("Failed to write %s" % newfile)
+
+if __name__ == '__main__':
+ sys.exit(main())