diff options
author | Chris St. Pierre <chris.a.st.pierre@gmail.com> | 2011-08-01 09:48:35 -0400 |
---|---|---|
committer | Chris St. Pierre <chris.a.st.pierre@gmail.com> | 2011-08-01 09:48:35 -0400 |
commit | 066aad5e10c05133b8650a50f18f44c9de276030 (patch) | |
tree | 21a0623660ac97ad49f5efe27602dd2a5c2a2fbf /tools | |
parent | 6fdffa2059e19567fe46d8f48eda6bb3f461caea (diff) | |
download | bcfg2-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-x | tools/packages-convert.py | 117 |
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()) |