-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpcsd_template.py
247 lines (216 loc) · 8.88 KB
/
pcsd_template.py
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# This file is part of Fork of crcnetd - CRCnet Configuration System Daemon
#
# Copyright (c) 2012 sun-exploit <[email protected]>
#
# Fork of crcnetd is free software: you may copy, redistribute
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 2 of the
# License, or (at your option) any later version.
#
# This file is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This file incorporates work covered by the following copyright and
# permission notice:
#
# Copyright (C) 2006 The University of Waikato
#
# This file is part of crcnetd - CRCnet Configuration System Daemon
#
# CFengine Configuration Setup
#
# Manages the cfengine configuration for the configuration system. The two
# primary tasks involved in this are:
# - Configuration file generation from templates
# - Controling cfengine runs and collecting output on demand
#
# Author: Matt Brown <[email protected]>
# Version: $Id$
#
# crcnetd is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License version 2 as published by the Free
# Software Foundation.
#
# crcnetd is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# crcnetd; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import sys
import os
import os.path
from stat import *
import imp
import time
import threading
from Cheetah.Template import Template
from pcsd_common import *
from pcsd_log import *
from pcsd_service import getServiceInstance, pcsd_service_error
class pcsd_template_error(pcsd_error):
pass
#####################################################################
# General Cfengine Integration Helper Functions
#####################################################################
def loadTemplates(moduleDir, baseStrip=""):
"""Creates a dictionary of template modules from the specified dir"""
# Dictionary of template objects
templates = {}
if baseStrip == "":
baseStrip = moduleDir
# Get a list of possible templates
if os.access(moduleDir, os.R_OK) != 1:
raise pcsd_template_exception("Unable to access directory! - %s" % \
moduleDir)
ptempls = os.listdir(moduleDir)
# Scan through the list and load valid modules
for tfile in ptempls:
# Ignore hidden files
if tfile.startswith("."):
continue
tfilename = "%s/%s" % (moduleDir, tfile)
# Recurse into directories
if os.path.isdir(tfilename):
templates.update(loadTemplates(tfilename, baseStrip))
continue
# Ignore non module files
if not tfile.endswith(".py"):
continue
# Load the template module
tname = os.path.basename(tfilename)[:-3]
if tname == "__init__":
# Ignore python framework stuff
continue
m = None
try:
m = imp.load_source(tname, tfilename)
# Don't want the module in the system module list
if tname in sys.modules.keys():
del sys.modules[tname]
except:
log_debug("Module import failed for %s template" % tname, \
sys.exc_info())
pass
if not m:
log_error("Failed to import template: %s" % tname)
continue
# If an explicit output filename was specified use that, otherwise
# prepend path information and store the template filename.
path = "%s/" % os.path.dirname(tfilename[len(baseStrip)+1:])
if len(path) == 1:
path = ""
tclass = eval("m.%s" % tname)
m.fileName = "%s%s" % (path, getattr(tclass, "fileName", tname))
m.multiFile = getattr(tclass, "multiFile", False)
m.templateName = tname
# Store the template for future use, prepend path for uniqueness
templateID = "%s%s" % (path, tname)
if templateID in templates.keys():
log_error("Could not import duplicate template: %s" % tname)
continue
templates[templateID] = m
# Return the templates
return templates
#####################################################################
# Template Mixin
#####################################################################
class pcsd_template(Template):
"""Config System Template Processor
All templates that expect to be processed by the configuration system
must derive from this class. It provides helper functions that are required
to determine where and when each template should be generated and how to
store it to disk.
"""
def __init__(self):
"""Initialise the class
You must call this method from your subclass
"""
# Call Cheetah's init
Template.__init__(self)
def writeTemplate(self, filename, multiFile):
"""Writes the template output to the specified file"""
files = []
# Ensure the output directory exists
ensureDirExists(os.path.dirname(filename))
# Get the template contents
self._CHEETAH__searchList += self._searchList
template = self.writeBody().strip()
if not template.endswith("\n"): template += "\n"
# Write it out to a file
if not multiFile:
f = open(filename, "w")
f.write(template)
f.close()
files.append(filename)
else:
# Handle templates that generate multiple output files
lines = template.split("\n")
f = None
for line in lines:
if line.startswith(".newfile"):
# New file starting, close previous file
if f is not None: f.close()
# Open new file
parts = line.split(" ")
if len(parts) != 2:
raise pcsd_template_error("Invalid multifile template!")
fname = "%s%s" % (filename, parts[1])
f = open(fname, "w")
files.append(fname)
continue
elif f is not None:
# Write the line out
f.write("%s\n" % line)
# Close the file
if f is not None: f.close()
return files
def __str__(self):
return self.writeBody()
def enabledOnHost(self, session_id, host_id):
"""Returns true if the template is applicable to the specified host
By default this method looks to see if the template has defined a
serviceName parameter. If it has then the function checks to see if
that service is enabled on the specified host. If it is not the
function returns False.
This function may be overriden by other classes/templates if you want
to implement more logic than the default implementation provides.
"""
serviceName = getattr(self, "serviceName", None)
if serviceName is None:
return True
from modules.pcs_host import pcs_host
host = pcs_host(session_id, host_id)
return host.hasServiceEnabledByName(serviceName)
def enabledOnNetwork(self, session_id):
"""Returns true if the template is able to be processed
By default this method looks to see if the template has defined a
serviceName parameter. If it has then the function checks to see if
that service is enabled. If it is not the function returns False.
This function may be overriden by other classes/templates if you want
to implement more logic than the default implementation provides.
"""
serviceName = getattr(self, "serviceName", None)
if serviceName is None:
return True
try:
service = getServiceInstance(session_id, serviceName)
except pcsd_service_error:
# Named service not known
return False
return service.getState()
def getTemplateVariables(self):
"""Returns a dictionary of variables that can be used by the template
The dictionary is passed to Cheetah's searchList so that it's entries
can be used as placeholders in the template.
This function retains an empty list. You should override this in your
implementing class.
"""
return []