summaryrefslogtreecommitdiffstats
path: root/src/lib/Server/Admin/Pull.py
diff options
context:
space:
mode:
authorNarayan Desai <desai@mcs.anl.gov>2007-12-29 04:57:53 +0000
committerNarayan Desai <desai@mcs.anl.gov>2007-12-29 04:57:53 +0000
commit3610288cbcbf4d1adedefa03166cd77ee15aad96 (patch)
tree1588fb78ae1c6e51e4e4ea2dab46a006a3ece0d3 /src/lib/Server/Admin/Pull.py
parent6bf7875bc299a1f81061782c8646c90972e06e5a (diff)
downloadbcfg2-3610288cbcbf4d1adedefa03166cd77ee15aad96.tar.gz
bcfg2-3610288cbcbf4d1adedefa03166cd77ee15aad96.tar.bz2
bcfg2-3610288cbcbf4d1adedefa03166cd77ee15aad96.zip
Refactor of bcfg2-admin (all modes moved to discrete modules in Bcfg2.Server.Admin
git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@4125 ce84e21b-d406-0410-9b95-82705330c041
Diffstat (limited to 'src/lib/Server/Admin/Pull.py')
-rw-r--r--src/lib/Server/Admin/Pull.py99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/lib/Server/Admin/Pull.py b/src/lib/Server/Admin/Pull.py
new file mode 100644
index 000000000..ab334dbf9
--- /dev/null
+++ b/src/lib/Server/Admin/Pull.py
@@ -0,0 +1,99 @@
+
+import binascii, lxml.etree, time
+import Bcfg2.Server.Admin
+
+class Pull(Bcfg2.Server.Admin.Mode):
+ '''Pull mode retrieves entries from clients and integrates the information into the repository'''
+ __shorthelp__ = 'bcfg2-admin pull <client> <entry type> <entry name>'
+ __longhelp__ = __shorthelp__ + '\n\tIntegrate configuration information from clients into the server repository'
+ def __init__(self, configfile):
+ Bcfg2.Server.Admin.Mode.__init__(self, configfile)
+
+ def __call__(self, args):
+ Bcfg2.Server.Admin.Mode.__call__(self, args)
+ self.PullEntry(args[0], args[1], args[2])
+
+ def PullEntry(self, client, etype, ename):
+ '''Make currently recorded client state correct for entry'''
+ # FIXME Pull.py is _way_ too interactive
+ sdata = self.load_stats(client)
+ if sdata.xpath('.//Statistics[@state="dirty"]'):
+ state = 'dirty'
+ else:
+ state = 'clean'
+ # need to pull entry out of statistics
+ sxpath = ".//Statistics[@state='%s']/Bad/ConfigFile[@name='%s']/../.." % (state, ename)
+ sentries = sdata.xpath(sxpath)
+ if not len(sentries):
+ self.errExit("Found %d entries for %s:%s:%s" % \
+ (len(sentries), client, etype, ename))
+ else:
+ print "Found %d entries for %s:%s:%s" % \
+ (len(sentries), client, etype, ename)
+ maxtime = max([time.strptime(stat.get('time')) for stat in sentries])
+ print "Found entry from", time.strftime("%c", maxtime)
+ statblock = [stat for stat in sentries \
+ if time.strptime(stat.get('time')) == maxtime]
+ entry = statblock[0].xpath('.//Bad/ConfigFile[@name="%s"]' % ename)
+ if not entry:
+ self.errExit("Could not find state data for entry; rerun bcfg2 on client system")
+ cfentry = entry[-1]
+
+ badfields = [field for field in ['perms', 'owner', 'group'] \
+ if cfentry.get(field) != cfentry.get('current_' + field) and \
+ cfentry.get('current_' + field)]
+ if badfields:
+ m_updates = dict([(field, cfentry.get('current_' + field)) \
+ for field in badfields])
+ print "got metadata_updates", m_updates
+ else:
+ m_updates = {}
+
+ if 'current_bdiff' in cfentry.attrib:
+ data = False
+ diff = binascii.a2b_base64(cfentry.get('current_bdiff'))
+ elif 'current_diff' in cfentry.attrib:
+ data = False
+ diff = cfentry.get('current_diff')
+ elif 'current_bfile' in cfentry.attrib:
+ data = binascii.a2b_base64(cfentry.get('current_bfile'))
+ diff = False
+ else:
+ if not m_updates:
+ self.errExit("having trouble processing entry. Entry is:\n" \
+ + lxml.etree.tostring(cfentry))
+ else:
+ data = False
+ diff = False
+
+ if diff:
+ print "Located diff:\n %s" % diff
+ elif data:
+ print "Found full (binary) file data"
+ if m_updates:
+ print "Found metadata updates"
+
+ if not diff and not data and not m_updates:
+ self.errExit("Failed to locate diff or full data or metadata updates\nStatistics entry was:\n%s" % lxml.etree.tostring(cfentry))
+
+ try:
+ bcore = Bcfg2.Server.Core.Core({}, self.configfile)
+ except Bcfg2.Server.Core.CoreInitError, msg:
+ self.errExit("Core load failed because %s" % msg)
+ [bcore.fam.Service() for _ in range(10)]
+ while bcore.fam.Service():
+ pass
+ m = bcore.metadata.get_metadata(client)
+ # find appropriate plugin in bcore
+ glist = [gen for gen in bcore.generators if
+ gen.Entries.get(etype, {}).has_key(ename)]
+ if len(glist) != 1:
+ self.errExit("Got wrong numbers of matching generators for entry:" \
+ + "%s" % ([g.__name__ for g in glist]))
+ plugin = glist[0]
+ try:
+ plugin.AcceptEntry(m, 'ConfigFile', ename, diff, data, m_updates)
+ except Bcfg2.Server.Plugin.PluginExecutionError:
+ self.errExit("Configuration upload not supported by plugin %s" \
+ % (plugin.__name__))
+ # svn commit if running under svn