4
Copyright 2010 Kelsey Hightower
5
Kelsey Hightower <kelsey.hightower@gmail.com>
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
module for configuring repos, ldap, packages, files, and monit
37
import simplejson as json
38
sys.path.append('/usr/share/yum-cli')
44
Used for all configuration methods, used by koan
45
to configure repos, ldap, files, packages, and monit.
48
def __init__(self, config):
49
"""Constructor. Requires json config object."""
50
self.config = json.JSONDecoder().decode(config)
53
#----------------------------------------------------------------------
55
def configure_repos(self):
56
"""Configure YUM repositories."""
57
print "- Configuring Repos"
58
old_repo = '/etc/yum.repos.d/config.repo'
60
# Stage a tempfile to hold new file contents
61
_tempfile = tempfile.NamedTemporaryFile()
62
_tempfile.write(self.config['repo_data'])
64
new_repo = _tempfile.name
66
# Check if repo resource exist, create if missing
67
if os.path.isfile(old_repo):
68
if not filecmp.cmp(old_repo, new_repo):
69
utils.sync_file(old_repo, new_repo, 0, 0, 644)
70
self.stats['repos_status'] = "Success: Repos in sync"
72
self.stats['repos_status'] = "Success: Repos in sync"
74
print " %s not found, creating..." % (old_repo)
75
open(old_repo,'w').close()
76
utils.sync_file(old_repo, new_repo, 0, 0, 644)
77
self.stats['repos_status'] = "Success: Repos in sync"
80
#----------------------------------------------------------------------
82
def configure_ldap(self):
83
"""Configure LDAP by running the specified LDAP command."""
84
print "- Configuring LDAP"
85
rc = subprocess.call(self.config['ldap_data'],shell="True")
87
self.stats['ldap_status'] = "Success: LDAP has been configured"
89
self.stats['ldap_status'] = "ERROR: configuring LDAP failed"
91
#----------------------------------------------------------------------
93
def configure_monit(self):
94
"""Start or reload Monit"""
95
print "- Configuring Monit"
96
ret = subprocess.call(['/sbin/service', 'monit', 'status'])
98
_ret = subprocess.call(['/usr/bin/monit', 'reload'])
100
self.stats['monit_status'] = "Running: Monit has been reloaded"
102
_ret = subprocess.call(['/sbin/service', 'monit', 'start'])
104
self.stats['monit_status'] = "Running: Monit has been started"
106
self.stats['monit_status'] = "Stopped: Failed to start monit"
108
#----------------------------------------------------------------------
110
def configure_packages(self):
111
"""Configure package resources."""
112
print "- Configuring Packages"
113
runtime_start = time.time()
117
packages = self.config['packages']
120
yb.preconf.debuglevel = 0
121
yb.preconf.errorlevel = 0
125
ybc = cli.YumBaseCli()
126
ybc.preconf.debuglevel = 0
127
ybc.preconf.errorlevel = 0
128
ybc.conf.assumeyes = True
134
for package in packages:
135
action = packages[package]['action']
136
# In the near future, will use install_name vs package
137
# as it includes a more specific package name: "package-version"
138
install_name = packages[package]['install_name']
140
if yb.isPackageInstalled(package):
141
if action == 'create':
143
if action == 'remove':
144
remove_pkg_list.append(package)
145
if not yb.isPackageInstalled(package):
146
if action == 'create':
147
create_pkg_list.append(package)
148
if action == 'remove':
151
# Don't waste time with YUM if there is nothing to do.
152
doTransaction = False
155
print " Packages out of sync: %s" % create_pkg_list
156
ybc.installPkgs(create_pkg_list)
157
osync += len(create_pkg_list)
160
print " Packages out of sync: %s" % remove_pkg_list
161
ybc.erasePkgs(remove_pkg_list)
162
osync += len(remove_pkg_list)
165
ybc.buildTransaction()
168
runtime_end = time.time()
169
runtime = (runtime_end - runtime_start)
170
self.stats['pkg'] = {'runtime': runtime,'nsync': nsync,'osync': osync,'fail' : fail}
172
#----------------------------------------------------------------------
174
def configure_directories(self):
175
""" Configure directory resources."""
176
print "- Configuring Directories"
177
runtime_start = time.time()
181
files = self.config['files']
182
# Split out directories
183
_dirs = [d for d in files if files[d]['is_dir']]
185
# Configure directories first
187
action = files[dir]['action']
188
odir = files[dir]['path']
190
protected_dirs = ['/','/bin','/boot','/dev','/etc','/lib','/lib64','/proc','/sbin','/sys','/usr','/var']
191
if os.path.isdir(odir):
192
if os.path.realpath(odir) in protected_dirs:
193
print " %s is a protected directory, skipping..." % os.path.realpath(odir)
197
if action == 'create':
198
nmode = int(files[dir]['mode'],8)
199
nuid = pwd.getpwnam(files[dir]['owner'])[2]
200
ngid = grp.getgrnam(files[dir]['group'])[2]
202
# Compare old and new directories, sync if permissions mismatch
203
if os.path.isdir(odir):
204
dstat = os.stat(odir)
205
omode = stat.S_IMODE(dstat.st_mode)
206
ouid = pwd.getpwuid(dstat.st_uid)[2]
207
ogid = grp.getgrgid(dstat.st_gid)[2]
208
if omode != nmode or ouid != nuid or ogid != ngid:
210
os.chown(odir,nuid,ngid)
215
print " Directory out of sync, creating %s" % odir
216
os.makedirs(odir,nmode)
217
os.chown(odir,nuid,ngid)
219
elif action == 'remove':
220
if os.path.isdir(odir):
221
print " Directory out of sync, removing %s" % odir
228
runtime_end = time.time()
229
runtime = (runtime_end - runtime_start)
230
self.stats['dir'] = {'runtime': runtime,'nsync': nsync,'osync': osync,'fail': fail}
232
#----------------------------------------------------------------------
234
def configure_files(self):
235
""" Configure file resources."""
236
print "- Configuring Files"
237
runtime_start = time.time()
241
files = self.config['files']
243
_files = [f for f in files if files[f]['is_dir'] is False]
246
action = files[file]['action']
247
ofile = files[file]['path']
249
if action == 'create':
250
nmode = int(files[file]['mode'],8)
251
nuid = pwd.getpwnam(files[file]['owner'])[2]
252
ngid = grp.getgrnam(files[file]['group'])[2]
254
# Stage a tempfile to hold new file contents
255
_tempfile = tempfile.NamedTemporaryFile()
256
_tempfile.write(files[file]['content'])
258
nfile = _tempfile.name
260
# Compare new and old files, sync if permissions or contents mismatch
261
if os.path.isfile(ofile):
262
fstat = os.stat(ofile)
263
omode = stat.S_IMODE(fstat.st_mode)
264
ouid = pwd.getpwuid(fstat.st_uid)[2]
265
ogid = grp.getgrgid(fstat.st_gid)[2]
266
if not filecmp.cmp(ofile, nfile) or omode != nmode or ogid != ngid or ouid != nuid:
267
utils.sync_file(ofile, nfile, nuid, ngid, nmode)
271
elif os.path.dirname(ofile):
272
# Create the file only if the base directory exists
273
open(ofile,'w').close()
274
utils.sync_file(ofile, nfile, nuid, ngid, nmode)
277
print " Base directory not found, %s required." % (os.path.dirname(ofile))
280
elif action == 'remove':
281
if os.path.isfile(file):
289
runtime_end = time.time()
290
runtime = (runtime_end - runtime_start)
291
self.stats['files'] = {'runtime': runtime,'nsync': nsync,'osync': osync,'fail': fail}
293
#----------------------------------------------------------------------
296
# Configure resources in a specific order: repos, ldap, packages, directories, files, monit
297
if self.config['repos_enabled']:
298
self.configure_repos()
299
if self.config['ldap_enabled']:
300
self.configure_ldap()
301
self.configure_packages()
302
self.configure_directories()
303
self.configure_files()
304
if self.config['monit_enabled']:
305
self.configure_monit()
b'\\ No newline at end of file'