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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
""" Base classes for admin modes """
__all__ = [
'Backup',
'Bundle',
'Client',
'Compare',
'Group',
'Init',
'Minestruct',
'Perf',
'Pull',
'Query',
'Reports',
'Syncdb',
'Tidy',
'Viz',
'Xcmd'
]
import re
import sys
import logging
import lxml.etree
import Bcfg2.Server.Core
import Bcfg2.Options
from Bcfg2.Compat import ConfigParser
class Mode(object):
""" Base object for admin modes. Docstrings are used as help
messages, so if you are seeing this, a help message has not yet
been added for this mode. """
__usage__ = None
__args__ = []
def __init__(self):
self.setup = Bcfg2.Options.get_option_parser()
self.configfile = self.setup['configfile']
self.__cfp = False
self.log = logging.getLogger('Bcfg2.Server.Admin.Mode')
usage = "bcfg2-admin %s" % self.__class__.__name__.lower()
if self.__usage__ is not None:
usage += " " + self.__usage__
self.setup.hm = usage
def getCFP(self):
""" get a config parser for the Bcfg2 config file """
if not self.__cfp:
self.__cfp = ConfigParser.ConfigParser()
self.__cfp.read(self.configfile)
return self.__cfp
cfp = property(getCFP)
def __call__(self, args):
raise NotImplementedError
@classmethod
def usage(cls, rv=1):
""" Exit with a long usage message """
print(re.sub(r'\s{2,}', ' ', cls.__doc__.strip()))
print("")
print("Usage:")
usage = "bcfg2-admin %s" % cls.__name__.lower()
if cls.__usage__ is not None:
usage += " " + cls.__usage__
print(" %s" % usage)
raise SystemExit(rv)
def shutdown(self):
""" Perform any necessary shtudown tasks for this mode """
pass
def errExit(self, emsg):
""" exit with an error """
print(emsg)
raise SystemExit(1)
def load_stats(self, client):
""" Load static statistics from the repository """
stats = lxml.etree.parse("%s/etc/statistics.xml" % self.setup['repo'])
hostent = stats.xpath('//Node[@name="%s"]' % client)
if not hostent:
self.errExit("Could not find stats for client %s" % (client))
return hostent[0]
def print_table(self, rows, justify='left', hdr=True, vdelim=" ",
padding=1):
"""Pretty print a table
rows - list of rows ([[row 1], [row 2], ..., [row n]])
hdr - if True the first row is treated as a table header
vdelim - vertical delimiter between columns
padding - # of spaces around the longest element in the column
justify - may be left,center,right
"""
hdelim = "="
justify = {'left': str.ljust,
'center': str.center,
'right': str.rjust}[justify.lower()]
# Calculate column widths (longest item in each column
# plus padding on both sides)
cols = list(zip(*rows))
col_widths = [max([len(str(item)) + 2 * padding for \
item in col]) for col in cols]
borderline = vdelim.join([w * hdelim for w in col_widths])
# Print out the table
print(borderline)
for row in rows:
print(vdelim.join([justify(str(item), width) for \
(item, width) in zip(row, col_widths)]))
if hdr:
print(borderline)
hdr = False
# pylint wants MetadataCore and StructureMode to be concrete classes
# and implement __call__, but they aren't and they don't, so we
# disable that warning
# pylint: disable=W0223
class MetadataCore(Mode):
"""Base class for admin-modes that handle metadata."""
__plugin_whitelist__ = None
__plugin_blacklist__ = None
def __init__(self):
Mode.__init__(self)
if self.__plugin_whitelist__ is not None:
self.setup['plugins'] = [p for p in self.setup['plugins']
if p in self.__plugin_whitelist__]
elif self.__plugin_blacklist__ is not None:
self.setup['plugins'] = [p for p in self.setup['plugins']
if p not in self.__plugin_blacklist__]
# admin modes don't need to watch for changes. one shot is fine here.
self.setup['filemonitor'] = 'pseudo'
try:
self.bcore = Bcfg2.Server.Core.BaseCore()
except Bcfg2.Server.Core.CoreInitError:
msg = sys.exc_info()[1]
self.errExit("Core load failed: %s" % msg)
self.bcore.fam.handle_event_set()
self.metadata = self.bcore.metadata
def shutdown(self):
if hasattr(self, 'bcore'):
self.bcore.shutdown()
class StructureMode(MetadataCore): # pylint: disable=W0223
""" Base class for admin modes that handle structure plugins """
pass
|