1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
import getopt
import Bcfg2.Server.Admin
class Pull(Bcfg2.Server.Admin.MetadataCore):
'''
Pull mode retrieves entries from clients and
integrates the information into the repository
'''
__shorthelp__ = ("Integrate configuration information "
"from clients into the server repository")
__longhelp__ = (__shorthelp__ + "\n\nbcfg2-admin pull [-v] [-f][-I] "
"<client> <entry type> <entry name>")
__usage__ = ("bcfg2-admin pull [options] <client> <entry type> "
"<entry name>\n\n"
" %-25s%s\n"
" %-25s%s\n"
" %-25s%s\n" %
("-v",
"be verbose",
"-f",
"force",
"-I",
"interactive"))
allowed = ['Metadata', 'BB', "DBStats", "Statistics", "Cfg", "SSHbase"]
def __init__(self, configfile):
Bcfg2.Server.Admin.MetadataCore.__init__(self, configfile,
self.__usage__)
self.log = False
self.mode = 'interactive'
def __call__(self, args):
Bcfg2.Server.Admin.Mode.__call__(self, args)
try:
opts, gargs = getopt.getopt(args, 'vfI')
except:
print self.__shorthelp__
raise SystemExit(1)
for opt in opts:
if opt[0] == '-v':
self.log = True
elif opt[0] == '-f':
self.mode = 'force'
elif opt[0] == '-I':
self.mode == 'interactive'
self.PullEntry(gargs[0], gargs[1], gargs[2])
def BuildNewEntry(self, client, etype, ename):
'''construct a new full entry for given client/entry from statistics'''
new_entry = {'type':etype, 'name':ename}
for plugin in self.bcore.pull_sources:
try:
(owner, group, perms, contents) = \
plugin.GetCurrentEntry(client, etype, ename)
break
except Bcfg2.Server.Plugin.PluginExecutionError:
if plugin == self.bcore.pull_sources[-1]:
print "Pull Source failure; could not fetch current state"
raise SystemExit(1)
try:
data = {'owner':owner, 'group':group, 'perms':perms, 'text':contents}
except UnboundLocalError:
print("Unable to build entry. "
"Do you have a statistics plugin enabled?")
raise SystemExit(1)
for k, v in data.iteritems():
if v:
new_entry[k] = v
#print new_entry
return new_entry
def Choose(self, choices):
'''Determine where to put pull data'''
if self.mode == 'interactive':
for choice in choices:
print "Plugin returned choice:"
if id(choice) == id(choices[0]):
print "(current entry)",
if choice.all:
print " => global entry"
elif choice.group:
print (" => group entry: %s (prio %d)" %
(choice.group, choice.prio))
else:
print " => host entry: %s" % (choice.hostname)
if raw_input("Use this entry? [yN]: ") in ['y', 'Y']:
return choice
return False
else:
# mode == 'force'
if not choices:
return False
return choices[0]
def PullEntry(self, client, etype, ename):
'''Make currently recorded client state correct for entry'''
new_entry = self.BuildNewEntry(client, etype, ename)
meta = self.bcore.build_metadata(client)
# find appropriate plugin in bcore
glist = [gen for gen in self.bcore.generators if
ename in gen.Entries.get(etype, {})]
if len(glist) != 1:
self.errExit("Got wrong numbers of matching generators for entry:" \
+ "%s" % ([g.name for g in glist]))
plugin = glist[0]
if not isinstance(plugin, Bcfg2.Server.Plugin.PullTarget):
self.errExit("Configuration upload not supported by plugin %s" \
% (plugin.name))
try:
choices = plugin.AcceptChoices(new_entry, meta)
specific = self.Choose(choices)
if specific:
plugin.AcceptPullData(specific, new_entry, self.log)
except Bcfg2.Server.Plugin.PluginExecutionError:
self.errExit("Configuration upload not supported by plugin %s" \
% (plugin.name))
# FIXME svn commit if running under svn
|