From 4f608872f119e6954779c4e96e356d8baa1c6017 Mon Sep 17 00:00:00 2001 From: Narayan Desai Date: Mon, 12 Feb 2007 20:48:21 +0000 Subject: Merge crosscheck script into bcfg2-admin git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@2801 ce84e21b-d406-0410-9b95-82705330c041 --- man/bcfg2-admin.8 | 1 + src/sbin/bcfg2-admin | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++- tools/crosscheck.py | 58 +++++++++++++++++++++------------- 3 files changed, 125 insertions(+), 23 deletions(-) diff --git a/man/bcfg2-admin.8 b/man/bcfg2-admin.8 index 9918b1048..f5a8241db 100644 --- a/man/bcfg2-admin.8 +++ b/man/bcfg2-admin.8 @@ -4,6 +4,7 @@ bcfg2-admin \- Perform repository administration tasks .SH SYNOPSIS .B bcfg2-server .I init +.I compare .I mineentry .I minestruct .I viz [-h] [-b] [-k] [-o output.png] [-r] diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin index a8236a55f..549d89176 100755 --- a/src/sbin/bcfg2-admin +++ b/src/sbin/bcfg2-admin @@ -159,6 +159,91 @@ def load_stats(client): err_exit("Could not find stats for client %s" % (client)) return hostent[0] +important = {'Package':['name', 'version'], + 'Service':['name', 'status'], + 'Directory':['name', 'owner', 'group', 'perms'], + 'SymLink':['name', 'to'], + 'ConfigFile':['name', 'owner', 'group', 'perms'], + 'Permissions':['name', 'perms'], + 'PostInstall':['name']} + +def compare(new, old): + for child in new.getchildren(): + equiv = old.xpath('%s[@name="%s"]' % (child.tag, child.get('name'))) + if not important.has_key(child.tag): + print "tag type %s not handled" % (child.tag) + continue + if len(equiv) == 0: + print "didn't find matching %s %s" % (child.tag, child.get('name')) + continue + elif len(equiv) >= 1: + if child.tag == 'ConfigFile': + if child.text != equiv[0].text: + print "%s %s contents differ" \ + % (child.tag, child.get('name')) + continue + noattrmatch = [field for field in important[child.tag] if \ + child.get(field) != equiv[0].get(field)] + if not noattrmatch: + new.remove(child) + old.remove(equiv[0]) + else: + print "%s %s attributes %s do not match" % \ + (child.tag, child.get('name'), noattrmatch) + if len(old.getchildren()) == 0 and len(new.getchildren()) == 0: + return True + if new.tag == 'Independant': + name = 'Indep' + else: + name = new.get('name') + both = [] + oldl = ["%s %s" % (entry.tag, entry.get('name')) for entry in old] + newl = ["%s %s" % (entry.tag, entry.get('name')) for entry in new] + for entry in newl: + if entry in oldl: + both.append(entry) + newl.remove(entry) + oldl.remove(entry) + for entry in both: + print "%s differs (in bundle %s)" % (entry, name) + for entry in oldl: + print "%s only in old configuration (in bundle %s)" % (entry, name) + for entry in newl: + print "%s only in new configuration (in bundle %s)" % (entry, name) + return False + +def do_compare(args): + '''run file comparison''' + try: + (old, new) = args + except IndexError: + print "Usage: bcfg2-admin compare " + raise SystemExit + + new = lxml.etree.parse(new).getroot() + old = lxml.etree.parse(old).getroot() + for src in [new, old]: + for bundle in src.findall('./Bundle'): + if bundle.get('name')[-4:] == '.xml': + bundle.set('name', bundle.get('name')[:-4]) + + for bundle in new.findall('./Bundle'): + equiv = old.xpath('Bundle[@name="%s"]' % (bundle.get('name'))) + if len(equiv) == 0: + print "couldnt find matching bundle for %s" % bundle.get('name') + continue + if len(equiv) == 1: + if compare(bundle, equiv[0]): + new.remove(bundle) + old.remove(equiv[0]) + else: + print "dunno what is going on for bundle %s" % (bundle.get('name')) + i1 = new.find('./Independant') + i2 = old.find('./Independant') + if compare(i1, i2): + new.remove(i1) + old.remove(i2) + def do_pull(client, etype, ename): '''Make currently recorded client state correct for entry''' cfile = '/etc/bcfg2.conf' @@ -320,7 +405,7 @@ def do_viz(args): for group in egroups: color = categories[group.get('category', 'default')] if group.get('profile', 'false') == 'true': - style="filled, bold" + style = "filled, bold" else: style = "filled" gseen.append(group.get('name')) @@ -376,6 +461,8 @@ if __name__ == '__main__': do_tidy(sys.argv[2:]) elif sys.argv[1] == 'viz': do_viz(sys.argv[2:]) + elif sys.argv[1] == 'compare': + do_compare(sys.argv[2:]) else: print usage diff --git a/tools/crosscheck.py b/tools/crosscheck.py index 109a3a950..c1447acd4 100644 --- a/tools/crosscheck.py +++ b/tools/crosscheck.py @@ -12,34 +12,48 @@ important = {'Package':['name', 'version'], 'PostInstall':['name']} def compare(new, old): - for i in range(2): #this is hardcoded.. may be a better looping method - for child in new.getchildren(): - equiv = old.xpath('%s[@name="%s"]' % (child.tag, child.get('name'))) - if not important.has_key(child.tag): - print "tag type %s not handled" % (child.tag) - continue - if len(equiv) == 0: - print "didn't find matching %s %s" % (child.tag, child.get('name')) - continue - elif len(equiv) >= 1: - if child.tag == 'ConfigFile': - if child.text != equiv[0].text: - continue - if [child.get(field) for field in important[child.tag]] == \ - [equiv[0].get(field) for field in important[child.tag]]: - new.remove(child) - old.remove(equiv[0]) - else: - print "+", lxml.etree.tostring(child), - print "-", lxml.etree.tostring(equiv[0]), + for child in new.getchildren(): + equiv = old.xpath('%s[@name="%s"]' % (child.tag, child.get('name'))) + if not important.has_key(child.tag): + print "tag type %s not handled" % (child.tag) + continue + if len(equiv) == 0: + print "didn't find matching %s %s" % (child.tag, child.get('name')) + continue + elif len(equiv) >= 1: + if child.tag == 'ConfigFile': + if child.text != equiv[0].text: + print "%s %s contents differ" \ + % (child.tag, child.get('name')) + continue + noattrmatch = [field for field in important[child.tag] if \ + child.get(field) != equiv[0].get(field)] + if not noattrmatch: + new.remove(child) + old.remove(equiv[0]) + else: + print "%s %s attributes %s do not match" % \ + (child.tag, child.get('name'), noattrmatch) if len(old.getchildren()) == 0 and len(new.getchildren()) == 0: return True if new.tag == 'Independant': name = 'Indep' else: name = new.get('name') - print name, ["%s.%s" % (child.tag, child.get('name')) for child in old.getchildren()], - print ["%s.%s" % (child.tag, child.get('name')) for child in new.getchildren()] + both = [] + oldl = ["%s %s" % (entry.tag, entry.get('name')) for entry in old] + newl = ["%s %s" % (entry.tag, entry.get('name')) for entry in new] + for entry in newl: + if entry in oldl: + both.append(entry) + newl.remove(entry) + oldl.remove(entry) + for entry in both: + print "%s differs (in bundle %s)" % (entry, name) + for entry in oldl: + print "%s only in old configuration (in bundle %s)" % (entry, name) + for entry in newl: + print "%s only in new configuration (in bundle %s)" % (entry, name) return False -- cgit v1.2.3-1-g7c22