summaryrefslogtreecommitdiffstats
path: root/cobbler/modules
diff options
context:
space:
mode:
authorJames Cammarata <jimi@sngx.net>2009-03-07 21:44:00 -0600
committerJames Cammarata <jimi@sngx.net>2009-03-07 21:44:00 -0600
commitd3fdc6d4965b02ce18346f067c14080115943a38 (patch)
treed2fa630d3f0e941acb7f5115c31ea91aabb4ae11 /cobbler/modules
parent54e462f3dca472d8bb8dc8a2b0a69c60ed9fe2ec (diff)
parent61db7baa541acc32b305ea6977a14ee8f5b3f470 (diff)
downloadcobbler-d3fdc6d4965b02ce18346f067c14080115943a38.tar.gz
cobbler-d3fdc6d4965b02ce18346f067c14080115943a38.tar.xz
cobbler-d3fdc6d4965b02ce18346f067c14080115943a38.zip
Merge branch 'devel' of git://git.fedorahosted.org/cobbler into ris-devel
Conflicts: cobbler/utils.py
Diffstat (limited to 'cobbler/modules')
-rw-r--r--cobbler/modules/authn_configfile.py4
-rw-r--r--cobbler/modules/authn_ldap.py1
-rw-r--r--cobbler/modules/authn_spacewalk.py111
-rw-r--r--cobbler/modules/cli_distro.py5
-rw-r--r--cobbler/modules/cli_image.py4
-rw-r--r--cobbler/modules/cli_misc.py19
-rw-r--r--cobbler/modules/cli_profile.py10
-rw-r--r--cobbler/modules/cli_repo.py4
-rw-r--r--cobbler/modules/cli_report.py2
-rw-r--r--cobbler/modules/cli_system.py10
-rw-r--r--cobbler/modules/install_post_log.py29
-rwxr-xr-xcobbler/modules/install_post_report.py101
-rwxr-xr-xcobbler/modules/install_pre_clear_anamon_logs.py51
-rw-r--r--cobbler/modules/install_pre_log.py29
-rw-r--r--cobbler/modules/manage_bind.py31
-rw-r--r--cobbler/modules/manage_dnsmasq.py1
-rw-r--r--cobbler/modules/manage_isc.py6
-rw-r--r--cobbler/modules/serializer_catalog.py24
-rw-r--r--cobbler/modules/serializer_yaml.py6
-rw-r--r--cobbler/modules/sync_post_restart_services.py70
20 files changed, 467 insertions, 51 deletions
diff --git a/cobbler/modules/authn_configfile.py b/cobbler/modules/authn_configfile.py
index 1f4cdb26..b9d2996e 100644
--- a/cobbler/modules/authn_configfile.py
+++ b/cobbler/modules/authn_configfile.py
@@ -26,7 +26,7 @@ import ConfigParser
import sys
import os
from utils import _
-import md5
+from utils import md5
import traceback
plib = distutils.sysconfig.get_python_lib()
@@ -75,7 +75,7 @@ def authenticate(api_handle,username,password):
for (user,realm,actual_blob) in userlist:
if user == username and realm == "Cobbler":
input = ":".join([user,realm,password])
- input_blob = md5.md5(input).hexdigest()
+ input_blob = md5(input).hexdigest()
if input_blob.lower() == actual_blob.lower():
return True
diff --git a/cobbler/modules/authn_ldap.py b/cobbler/modules/authn_ldap.py
index e4313e07..a8718c5b 100644
--- a/cobbler/modules/authn_ldap.py
+++ b/cobbler/modules/authn_ldap.py
@@ -23,7 +23,6 @@ import distutils.sysconfig
import sys
import os
from utils import _
-import md5
import traceback
# we'll import this just a bit later
diff --git a/cobbler/modules/authn_spacewalk.py b/cobbler/modules/authn_spacewalk.py
index 45a26a01..eec3bd7c 100644
--- a/cobbler/modules/authn_spacewalk.py
+++ b/cobbler/modules/authn_spacewalk.py
@@ -29,35 +29,126 @@ plib = distutils.sysconfig.get_python_lib()
mod_path="%s/cobbler" % plib
sys.path.insert(0, mod_path)
-
def register():
"""
The mandatory cobbler module registration hook.
"""
return "authn"
+def __looks_like_a_token(password):
+
+ # what spacewalk sends us could be an internal token or it could be a password
+ # if it's long and lowercase hex, it's /likely/ a token, and we should try to treat
+ # it as a token first, if not, we should treat it as a password. All of this
+ # code is there to avoid extra XMLRPC calls, which are slow.
+
+ # we can't use binascii.unhexlify here as it's an "odd length string"
+
+ if password.lower() != password:
+ # tokens are always lowercase, this isn't a token
+ return False
+
+ #try:
+ # #data = binascii.unhexlify(password)
+ # return True # looks like a token, but we can't be sure
+ #except:
+ # return False # definitely not a token
+
+ return (len(password) > 45)
+
def authenticate(api_handle,username,password):
"""
Validate a username/password combo, returning True/False
This will pass the username and password back to Spacewalk
to see if this authentication request is valid.
+
+ See also: http://www.redhat.com/spacewalk/documentation/api/0.4/
+
"""
- #spacewalk_url = api_handle.settings().spacewalk_url
- server = api_handle.settings().redhat_management_server
+ if api_handle is not None:
+ server = api_handle.settings().redhat_management_server
+ user_enabled = api_handle.settings().redhat_management_permissive
+ else:
+ server = "columbia.devel.redhat.com"
+ user_enabled = True
+
if server == "xmlrpc.rhn.redhat.com":
- return False # don't bother RHN!
+ return False # emergency fail, don't bother RHN!
+
spacewalk_url = "https://%s/rpc/api" % server
client = xmlrpclib.Server(spacewalk_url, verbose=0)
- valid = client.auth.checkAuthToken(username,password)
-
- if valid is None:
- return False
+ if __looks_like_a_token(password) or username == 'taskomatic_user':
+
+ # The tokens
+ # are lowercase hex, but a password can also be lowercase hex,
+ # so we have to try it as both a token and then a password if
+ # we are unsure. We do it this way to be faster but also to avoid
+ # any login failed stuff in the logs that we don't need to send.
+
+ try:
+ valid = client.auth.checkAuthToken(username,password)
+ except:
+ # if the token is not a token this will raise an exception
+ # rather than return an integer.
+ valid = 0
+
+ # problem at this point, 0xdeadbeef is valid as a token but if that
+ # fails, it's also a valid password, so we must try auth system #2
+
+ if valid != 1:
+ # first API code returns 1 on success
+ # the second uses exceptions for login failed.
+ #
+ # so... token check failed, but maybe the username/password
+ # is just a simple username/pass!
+
+ if user_enabled == 0:
+ # this feature must be explicitly enabled.
+ return False
+
+
+ session = ""
+ try:
+ session = client.auth.login(username,password)
+ except:
+ # FIXME: should log exceptions that are not excepted
+ # as we could detect spacewalk java errors here that
+ # are not login related.
+ return False
+
+ # login success by username, role must also match
+ roles = client.user.listRoles(session, username)
+ if not ("config_admin" in roles or "org_admin" in roles):
+ return False
+
+ return True
- return (valid == 1)
-
+ else:
+
+ # it's an older version of spacewalk, so just try the username/pass
+ # OR: we know for sure it's not a token because it's not lowercase hex.
+
+ if user_enabled == 0:
+ # this feature must be explicitly enabled.
+ return False
+
+
+ session = ""
+ try:
+ session = client.auth.login(username,password)
+ except:
+ return False
+
+ # login success by username, role must also match
+ roles = client.user.listRoles(session, username)
+ if not ("config_admin" in roles or "org_admin" in roles):
+ return False
+ return True
+if __name__ == "__main__":
+ print authenticate(None,"admin","redhat")
diff --git a/cobbler/modules/cli_distro.py b/cobbler/modules/cli_distro.py
index 0c1425b1..7105b403 100644
--- a/cobbler/modules/cli_distro.py
+++ b/cobbler/modules/cli_distro.py
@@ -28,7 +28,7 @@ mod_path="%s/cobbler" % plib
sys.path.insert(0, mod_path)
from utils import _
-import commands
+import cobbler.commands as commands
import cexceptions
@@ -61,6 +61,7 @@ class DistroFunction(commands.CobblerFunction):
p.add_option("--ksmeta", dest="ksmeta", help="ex: 'blippy=7'")
p.add_option("--mgmt-classes", dest="mgmt_classes", help="list of config management classes (for Puppet, etc)")
p.add_option("--redhat-management-key", dest="redhat_management_key", help="authentication token for RHN/Spacewalk/Satellite")
+ p.add_option("--redhat-management-server", dest="redhat_management_server", help="RHN/Spacewalk/Satellite server")
p.add_option("--template-files", dest="template_files", help="specify files to be generated from templates during a sync")
p.add_option("--name", dest="name", help="ex: 'RHEL-5-i386' (REQUIRED)")
@@ -118,6 +119,8 @@ class DistroFunction(commands.CobblerFunction):
obj.set_template_files(self.options.template_files,self.options.inplace)
if self.options.redhat_management_key is not None:
obj.set_redhat_management_key(self.options.redhat_management_key)
+ if self.options.redhat_management_server is not None:
+ obj.set_redhat_management_server(self.options.redhat_management_server)
return self.object_manipulator_finish(obj, self.api.distros, self.options)
diff --git a/cobbler/modules/cli_image.py b/cobbler/modules/cli_image.py
index b6b96ff4..0265bd78 100644
--- a/cobbler/modules/cli_image.py
+++ b/cobbler/modules/cli_image.py
@@ -20,7 +20,7 @@ mod_path="%s/cobbler" % plib
sys.path.insert(0, mod_path)
from utils import _
-import commands
+import cobbler.commands as commands
import cexceptions
@@ -54,6 +54,8 @@ class ImageFunction(commands.CobblerFunction):
if not self.matches_args(args,["dumpvars","remove","report","list"]):
p.add_option("--os-version", dest="os_version", help="ex: rhel4, fedora 9")
+ if self.matches_args(args,["remove"]):
+ p.add_option("--recursive", action="store_true", dest="recursive", help="also delete child objects")
if self.matches_args(args,["copy","rename"]):
diff --git a/cobbler/modules/cli_misc.py b/cobbler/modules/cli_misc.py
index 94ccc0d1..f83b5c8c 100644
--- a/cobbler/modules/cli_misc.py
+++ b/cobbler/modules/cli_misc.py
@@ -21,7 +21,7 @@ mod_path="%s/cobbler" % plib
sys.path.insert(0, mod_path)
from utils import _
-import commands
+import cobbler.commands as commands
from cexceptions import *
HELP_FORMAT = commands.HELP_FORMAT
@@ -63,7 +63,7 @@ class CheckFunction(commands.CobblerFunction):
if len(status) == 0:
self.logprint(fd,"No setup problems found")
- self.logprint(fd,"Manual review and editing of /var/lib/cobbler/settings is recommended to tailor cobbler to your particular configuration.")
+ self.logprint(fd,"Manual review and editing of /etc/cobbler/settings is recommended to tailor cobbler to your particular configuration.")
self.logprint(fd,"Good luck.")
return True
else:
@@ -172,7 +172,10 @@ class StatusFunction(commands.CobblerFunction):
########################################################
class SyncFunction(commands.CobblerFunction):
-
+
+ def add_options(self, p, args):
+ p.add_option("--verbose", dest="verbose", action="store_true", help="run sync with more output")
+
def help_me(self):
return HELP_FORMAT % ("cobbler sync","")
@@ -180,7 +183,7 @@ class SyncFunction(commands.CobblerFunction):
return "sync"
def run(self):
- return self.api.sync()
+ return self.api.sync(verbose=self.options.verbose)
########################################################
@@ -222,6 +225,9 @@ class BuildIsoFunction(commands.CobblerFunction):
p.add_option("--profiles", dest="profiles", help="(OPTIONAL) use these profiles only")
p.add_option("--systems", dest="systems", help="(OPTIONAL) use these systems only")
p.add_option("--tempdir", dest="tempdir", help="(OPTIONAL) working directory")
+ p.add_option("--distro", dest="distro", help="(OPTIONAL) used with --standalone to create a distro-based ISO including all associated profiles/systems")
+ p.add_option("--standalone", dest="standalone", action="store_true", help="(OPTIONAL) creates a standalone ISO with all required distro files on it")
+ p.add_option("--source", dest="source", help="(OPTIONAL) used with --standalone to specify a source for the distribution files")
def help_me(self):
return HELP_FORMAT % ("cobbler buildiso","[ARGS]")
@@ -234,7 +240,10 @@ class BuildIsoFunction(commands.CobblerFunction):
iso=self.options.isoname,
profiles=self.options.profiles,
systems=self.options.systems,
- tempdir=self.options.tempdir
+ tempdir=self.options.tempdir,
+ distro=self.options.distro,
+ standalone=self.options.standalone,
+ source=self.options.source
)
########################################################
diff --git a/cobbler/modules/cli_profile.py b/cobbler/modules/cli_profile.py
index 1f8a5655..a3ca5d4c 100644
--- a/cobbler/modules/cli_profile.py
+++ b/cobbler/modules/cli_profile.py
@@ -28,7 +28,7 @@ mod_path="%s/cobbler" % plib
sys.path.insert(0, mod_path)
from utils import _
-import commands
+import cobbler.commands as commands
import cexceptions
@@ -72,6 +72,7 @@ class ProfileFunction(commands.CobblerFunction):
if not self.matches_args(args,["dumpvars","remove","report","getks","list"]):
p.add_option("--name-servers", dest="name_servers", help="name servers for static setups")
+ p.add_option("--name-servers-search", dest="name_servers_search", help="name servers search path for static setups")
if "copy" in args or "rename" in args:
p.add_option("--newname", dest="newname")
@@ -88,6 +89,7 @@ class ProfileFunction(commands.CobblerFunction):
if not self.matches_args(args,["dumpvars","remove","report","getks","list"]):
p.add_option("--redhat-management-key", dest="redhat_management_key", help="authentication token for RHN/Spacewalk/Satellite")
+ p.add_option("--redhat-management-server", dest="redhat_management_server", help="RHN/Spacewalk/Satellite server")
p.add_option("--repos", dest="repos", help="names of cobbler repos")
p.add_option("--server", dest="server_override", help="overrides value in settings file")
p.add_option("--template-files", dest="template_files", help="specify files to be generated from templates during a sync")
@@ -148,7 +150,7 @@ class ProfileFunction(commands.CobblerFunction):
if self.options.dhcp_tag is not None:
obj.set_dhcp_tag(self.options.dhcp_tag)
if self.options.server_override is not None:
- obj.set_server(self.options.server)
+ obj.set_server(self.options.server_overide)
if self.options.owners is not None:
obj.set_owners(self.options.owners)
@@ -158,8 +160,12 @@ class ProfileFunction(commands.CobblerFunction):
obj.set_template_files(self.options.template_files,self.options.inplace)
if self.options.name_servers is not None:
obj.set_name_servers(self.options.name_servers)
+ if self.options.name_servers_search is not None:
+ obj.set_name_servers_search(self.options.name_servers_search)
if self.options.redhat_management_key is not None:
obj.set_redhat_management_key(self.options.redhat_management_key)
+ if self.options.redhat_management_server is not None:
+ obj.set_redhat_management_server(self.options.redhat_management_server)
return self.object_manipulator_finish(obj, self.api.profiles, self.options)
diff --git a/cobbler/modules/cli_repo.py b/cobbler/modules/cli_repo.py
index a8483dcb..53c0232c 100644
--- a/cobbler/modules/cli_repo.py
+++ b/cobbler/modules/cli_repo.py
@@ -28,7 +28,7 @@ mod_path="%s/cobbler" % plib
sys.path.insert(0, mod_path)
from utils import _
-import commands
+import cobbler.commands as commands
import cexceptions
@@ -83,7 +83,7 @@ class RepoFunction(commands.CobblerFunction):
def run(self):
if self.args and "find" in self.args:
- items = self.api.find_system(return_list=True, no_errors=True, **self.options.__dict__)
+ items = self.api.find_repo(return_list=True, no_errors=True, **self.options.__dict__)
for x in items:
print x.name
return True
diff --git a/cobbler/modules/cli_report.py b/cobbler/modules/cli_report.py
index 82060dda..4bec4b5d 100644
--- a/cobbler/modules/cli_report.py
+++ b/cobbler/modules/cli_report.py
@@ -20,7 +20,7 @@ mod_path="%s/cobbler" % plib
sys.path.insert(0, mod_path)
from utils import _, get_random_mac
-import commands
+import cobbler.commands as commands
from cexceptions import *
HELP_FORMAT = commands.HELP_FORMAT
diff --git a/cobbler/modules/cli_system.py b/cobbler/modules/cli_system.py
index 4805f9c9..7c0924ed 100644
--- a/cobbler/modules/cli_system.py
+++ b/cobbler/modules/cli_system.py
@@ -28,7 +28,7 @@ mod_path="%s/cobbler" % plib
sys.path.insert(0, mod_path)
from utils import _, get_random_mac
-import commands
+import cobbler.commands as commands
from cexceptions import *
@@ -73,7 +73,9 @@ class SystemFunction(commands.CobblerFunction):
p.add_option("--mac", dest="mac", help="ex: 'AA:BB:CC:DD:EE:FF', (RECOMMENDED)")
p.add_option("--mgmt-classes", dest="mgmt_classes", help="list of config management classes (for Puppet, etc)")
p.add_option("--name-servers", dest="name_servers", help="name servers for static setups")
+ p.add_option("--name-servers-search", dest="name_servers_search", help="name servers search path for static setups")
p.add_option("--redhat-management-key", dest="redhat_management_key", help="authentication token for RHN/Spacewalk/Satellite")
+ p.add_option("--redhat-management-server", dest="redhat_management_server", help="RHN/Spacewalk/Satellite server")
p.add_option("--static-routes", dest="static_routes", help="sets static routes (see manpage)")
p.add_option("--template-files", dest="template_files",help="specify files to be generated from templates during a sync")
@@ -101,7 +103,7 @@ class SystemFunction(commands.CobblerFunction):
if not self.matches_args(args,["dumpvars","remove","report","getks","list"]):
p.add_option("--power-pass", dest="power_pass", help="password for power management interface")
if not self.matches_args(args,["dumpvars","poweron","poweroff","reboot","remove","report","getks","list"]):
- p.add_option("--power-type", dest="power_type", help="one of: none, apc_snmp, bullpap, drac, ether-wake, ilo, ipmilan, ipmitool, wti, lpar, bladecenter, virsh")
+ p.add_option("--power-type", dest="power_type", help="one of: none, apc_snmp, bullpap, drac, ether-wake, ilo, ipmilan, ipmitool, wti, lpar, bladecenter, virsh, integrity")
if not self.matches_args(args,["dumpvars","remove","report","getks","list"]):
p.add_option("--power-user", dest="power_user", help="username for power management interface, if required")
@@ -245,8 +247,12 @@ class SystemFunction(commands.CobblerFunction):
obj.set_template_files(self.options.template_files,self.options.inplace)
if self.options.name_servers is not None:
obj.set_name_servers(self.options.name_servers)
+ if self.options.name_servers_search is not None:
+ obj.set_name_servers_search(self.options.name_servers_search)
if self.options.redhat_management_key is not None:
obj.set_redhat_management_key(self.options.redhat_management_key)
+ if self.options.redhat_management_server is not None:
+ obj.set_redhat_management_server(self.options.redhat_management_server)
rc = self.object_manipulator_finish(obj, self.api.systems, self.options)
diff --git a/cobbler/modules/install_post_log.py b/cobbler/modules/install_post_log.py
new file mode 100644
index 00000000..02c0b55e
--- /dev/null
+++ b/cobbler/modules/install_post_log.py
@@ -0,0 +1,29 @@
+import distutils.sysconfig
+import sys
+import os
+from utils import _
+import traceback
+import cexceptions
+import os
+import sys
+import time
+
+plib = distutils.sysconfig.get_python_lib()
+mod_path="%s/cobbler" % plib
+sys.path.insert(0, mod_path)
+
+def register():
+ # this pure python trigger acts as if it were a legacy shell-trigger, but is much faster.
+ # the return of this method indicates the trigger type
+ return "/var/lib/cobbler/triggers/install/post/*"
+
+def run(api, args):
+ objtype = args[0] # "system" or "profile"
+ name = args[1] # name of system or profile
+ ip = args[2] # ip or "?"
+
+ fd = open("/var/log/cobbler/install.log","a+")
+ fd.write("%s\t%s\t%s\tstop\t%s\n" % (objtype,name,ip,time.time()))
+ fd.close()
+
+ return 0
diff --git a/cobbler/modules/install_post_report.py b/cobbler/modules/install_post_report.py
new file mode 100755
index 00000000..b42753b4
--- /dev/null
+++ b/cobbler/modules/install_post_report.py
@@ -0,0 +1,101 @@
+# (c) 2008-2009
+# Jeff Schroeder <jeffschroeder@computer.org>
+# Michael DeHaan <mdehaan@redhat.com>
+#
+# License: GPLv2+
+
+# Post install trigger for cobbler to
+# send out a pretty email report that
+# contains target information.
+
+import distutils.sysconfig
+import sys
+import os
+import traceback
+
+plib = distutils.sysconfig.get_python_lib()
+mod_path="%s/cobbler" % plib
+sys.path.insert(0, mod_path)
+
+from utils import _
+import smtplib
+import sys
+import cobbler.templar as templar
+from cobbler.cexceptions import CX
+import utils
+
+def register():
+ # this pure python trigger acts as if it were a legacy shell-trigger, but is much faster.
+ # the return of this method indicates the trigger type
+ return "/var/lib/cobbler/triggers/install/post/*"
+
+def run(api, args):
+
+ settings = api.settings()
+
+ # go no further if this feature is turned off
+ if not str(settings.build_reporting_enabled).lower() in [ "1", "yes", "y", "true"]:
+ print "not enabled"
+ return 0
+
+ objtype = args[0] # "target" or "profile"
+ name = args[1] # name of target or profile
+ boot_ip = args[2] # ip or "?"
+
+ if objtype == "system":
+ target = api.find_system(name)
+ else:
+ target = api.find_profile(name)
+
+ # collapse the object down to a rendered datastructure
+ target = utils.blender(api, False, target)
+
+ if target == {}:
+ raise CX("failure looking up target")
+
+ to_addr = settings.build_reporting_email
+ if to_addr == "":
+ return 0
+
+ # add the ability to specify an MTA for servers that don't run their own
+ smtp_server = settings.build_reporting_smtp_server
+ if smtp_server == "":
+ smtp_server = "localhost"
+
+ # use a custom from address or fall back to a reasonable default
+ from_addr = settings.build_reporting_sender
+ if from_addr == "":
+ from_addr = "cobbler@%s" % settings.server
+
+ subject = settings.build_reporting_subject
+ if subject == "":
+ subject = '[Cobbler] install complete '
+
+ to_addr = ", ".join(to_addr)
+ metadata = {
+ "from_addr" : from_addr,
+ "to_addr" : to_addr,
+ "subject" : subject,
+ "boot_ip" : boot_ip
+ }
+ metadata.update(target)
+
+ input_template = open("/etc/cobbler/reporting/build_report_email.template")
+ input_data = input_template.read()
+ input_template.close()
+
+ message = templar.Templar().render(input_data, metadata, None)
+ # for debug, call
+ # print message
+
+ # Send the mail
+ # FIXME: on error, return non-zero
+ server_handle = smtplib.SMTP(smtp_server)
+ server_handle.sendmail(from_addr, to_addr, message)
+ server_handle.quit()
+
+ return 0
+
+
+
+
diff --git a/cobbler/modules/install_pre_clear_anamon_logs.py b/cobbler/modules/install_pre_clear_anamon_logs.py
new file mode 100755
index 00000000..381759aa
--- /dev/null
+++ b/cobbler/modules/install_pre_clear_anamon_logs.py
@@ -0,0 +1,51 @@
+import distutils.sysconfig
+import sys
+import os
+from utils import _
+import traceback
+import cexceptions
+
+plib = distutils.sysconfig.get_python_lib()
+mod_path="%s/cobbler" % plib
+sys.path.insert(0, mod_path)
+
+import os
+import glob
+import sys
+
+
+def register():
+ # this pure python trigger acts as if it were a legacy shell-trigger, but is much faster.
+ # the return of this method indicates the trigger type
+ return "/var/lib/cobbler/triggers/install/pre/*"
+
+def run(api, args):
+
+ if len(args) < 3:
+ raise CX("invalid invocation")
+
+ objtype = args[0] # "system" or "profile"
+ name = args[1] # name of system or profile
+ ip = args[2] # ip or "?"
+
+ settings = api.settings()
+ anamon_enabled = str(settings.anamon_enabled)
+
+ # Remove any files matched with the given glob pattern
+ def unlink_files(globex):
+ for f in glob.glob(globex):
+ if os.path.isfile(f):
+ try:
+ os.unlink(f)
+ except OSError, e:
+ pass
+
+ if str(anamon_enabled) in [ "true", "1", "y", "yes"]:
+ dirname = "/var/log/cobbler/anamon/%s" % name
+ if os.path.isdir(dirname):
+ unlink_files(os.path.join(dirname, "*"))
+
+ # TODO - log somewhere that we cleared a systems anamon logs
+ return 0
+
+
diff --git a/cobbler/modules/install_pre_log.py b/cobbler/modules/install_pre_log.py
new file mode 100644
index 00000000..4469a514
--- /dev/null
+++ b/cobbler/modules/install_pre_log.py
@@ -0,0 +1,29 @@
+import distutils.sysconfig
+import sys
+import os
+from utils import _
+import traceback
+import cexceptions
+import os
+import sys
+import time
+
+plib = distutils.sysconfig.get_python_lib()
+mod_path="%s/cobbler" % plib
+sys.path.insert(0, mod_path)
+
+def register():
+ # this pure python trigger acts as if it were a legacy shell-trigger, but is much faster.
+ # the return of this method indicates the trigger type
+ return "/var/lib/cobbler/triggers/install/pre/*"
+
+def run(api, args):
+ objtype = args[0] # "system" or "profile"
+ name = args[1] # name of system or profile
+ ip = args[2] # ip or "?"
+
+ fd = open("/var/log/cobbler/install.log","a+")
+ fd.write("%s\t%s\t%s\tstart\t%s\n" % (objtype,name,ip,time.time()))
+ fd.close()
+
+ return 0
diff --git a/cobbler/modules/manage_bind.py b/cobbler/modules/manage_bind.py
index e7cdc3a7..657a9a77 100644
--- a/cobbler/modules/manage_bind.py
+++ b/cobbler/modules/manage_bind.py
@@ -30,7 +30,6 @@ import sys
import glob
import traceback
import errno
-import popen2
import re
from shlex import shlex
@@ -82,7 +81,13 @@ class BindManager:
in them
"""
zones = {}
- for zone in self.settings.manage_forward_zones:
+ forward_zones = self.settings.manage_forward_zones
+ if type(forward_zones) != type([]):
+ # gracefully handle when user inputs only a single zone
+ # as a string instead of a list with only a single item
+ forward_zones = [forward_zones]
+
+ for zone in forward_zones:
zones[zone] = {}
for system in self.systems:
@@ -126,7 +131,13 @@ class BindManager:
in them
"""
zones = {}
- for zone in self.settings.manage_reverse_zones:
+ reverse_zones = self.settings.manage_reverse_zones
+ if type(reverse_zones) != type([]):
+ # gracefully handle when user inputs only a single zone
+ # as a string instead of a list with only a single item
+ reverse_zones = [reverse_zones]
+
+ for zone in reverse_zones:
zones[zone] = {}
for sys in self.systems:
@@ -223,14 +234,14 @@ zone "%(arpa)s." {
octets = map(lambda x: [str(i) for i in x], octets)
return ['.'.join(i) for i in octets]
- def __pretty_print_host_records(self, hosts, type='A', rclass='IN'):
+ def __pretty_print_host_records(self, hosts, rectype='A', rclass='IN'):
"""
Format host records by order and with consistent indentation
"""
names = [k for k,v in hosts.iteritems()]
if not names: return '' # zones with no hosts
- if type == 'PTR':
+ if rectype == 'PTR':
names = self.__ip_sort(names)
else:
names.sort()
@@ -239,10 +250,10 @@ zone "%(arpa)s." {
s = ""
for name in names:
- s += "%s %s %s %s\n" % (name + (" " * (max_name - len(name))),
- rclass,
- type,
- hosts[name])
+ spacing = " " * (max_name - len(name))
+ my_name = "%s%s" % (name, spacing)
+ my_host = hosts[name]
+ s += "%s %s %s %s\n" % (my_name, rclass, rectype, my_host)
return s
def __write_zone_files(self):
@@ -297,7 +308,7 @@ zone "%(arpa)s." {
except:
template_data = default_template_data
- metadata['host_record'] = self.__pretty_print_host_records(hosts, type='PTR')
+ metadata['host_record'] = self.__pretty_print_host_records(hosts, rectype='PTR')
self.templar.render(template_data, metadata, '/var/named/' + zone, None)
diff --git a/cobbler/modules/manage_dnsmasq.py b/cobbler/modules/manage_dnsmasq.py
index 344020f8..4a9b47d5 100644
--- a/cobbler/modules/manage_dnsmasq.py
+++ b/cobbler/modules/manage_dnsmasq.py
@@ -31,7 +31,6 @@ import sys
import glob
import traceback
import errno
-import popen2
from shlex import shlex
import utils
from cexceptions import *
diff --git a/cobbler/modules/manage_isc.py b/cobbler/modules/manage_isc.py
index fb22a380..9846314b 100644
--- a/cobbler/modules/manage_isc.py
+++ b/cobbler/modules/manage_isc.py
@@ -30,7 +30,7 @@ import sys
import glob
import traceback
import errno
-import popen2
+from utils import popen2
from shlex import shlex
@@ -83,7 +83,7 @@ class IscManager:
if ip.find("/") != -1:
return
try:
- fromchild, tochild = popen2.popen2(self.settings.omshell_bin)
+ fromchild, tochild = popen2([self.settings.omshell_bin])
tochild.write("port %s\n" % port)
tochild.flush()
tochild.write("connect\n")
@@ -111,7 +111,7 @@ class IscManager:
Use DHCP's API to delete a DHCP entry in
the /var/lib/dhcpd/dhcpd.leases file
"""
- fromchild, tochild = popen2.popen2(self.settings.omshell_bin)
+ fromchild, tochild = popen2([self.settings.omshell_bin])
try:
tochild.write("port %s\n" % port)
tochild.flush()
diff --git a/cobbler/modules/serializer_catalog.py b/cobbler/modules/serializer_catalog.py
index 35d1517a..72ab2cc3 100644
--- a/cobbler/modules/serializer_catalog.py
+++ b/cobbler/modules/serializer_catalog.py
@@ -25,6 +25,7 @@ import os
import sys
import glob
import traceback
+import yaml # PyYAML
plib = distutils.sysconfig.get_python_lib()
mod_path="%s/cobbler" % plib
@@ -32,8 +33,7 @@ sys.path.insert(0, mod_path)
from utils import _
import utils
-import yaml # Howell-Clark version
-import cexceptions
+from cexceptions import *
import os
def register():
@@ -46,7 +46,10 @@ def serialize_item(obj, item):
filename = "/var/lib/cobbler/config/%ss.d/%s" % (obj.collection_type(),item.name)
datastruct = item.to_datastruct()
fd = open(filename,"w+")
- fd.write(yaml.dump(datastruct))
+ ydata = yaml.dump(datastruct)
+ if ydata is None or ydata == "":
+ raise CX("internal yaml error, tried to write empty file to %s, data was %s" % (filename, datastruct))
+ fd.write(ydata)
fd.close()
return True
@@ -63,7 +66,7 @@ def deserialize_item_raw(collection_type, item_name):
if not os.path.exists(filename):
return None
fd = open(filename)
- datastruct = yaml.load(fd.read()).next()
+ datastruct = yaml.load(fd.read())
fd.close()
return datastruct
@@ -84,14 +87,14 @@ def deserialize_raw(collection_type):
old_filename = "/var/lib/cobbler/%ss" % collection_type
if collection_type == "settings":
fd = open("/etc/cobbler/settings")
- datastruct = yaml.load(fd.read()).next()
+ datastruct = yaml.load(fd.read())
fd.close()
return datastruct
elif os.path.exists(old_filename):
# for use in migration
sys.stderr.write("reading from old config format: %s\n" % old_filename)
fd = open(old_filename)
- datastruct = yaml.load(fd.read()).next()
+ datastruct = yaml.load(fd.read())
fd.close()
return datastruct
else:
@@ -99,7 +102,14 @@ def deserialize_raw(collection_type):
files = glob.glob("/var/lib/cobbler/config/%ss.d/*" % collection_type)
for f in files:
fd = open(f)
- results.append(yaml.load(fd.read()).next())
+ ydata = fd.read()
+ if ydata is None or ydata == "":
+ raise CX("error, empty file %s" % f)
+ try:
+ datastruct = yaml.load(ydata)
+ except:
+ raise CX("error parsing yaml file: %s" % f)
+ results.append(datastruct)
fd.close()
return results
diff --git a/cobbler/modules/serializer_yaml.py b/cobbler/modules/serializer_yaml.py
index 75f89cf9..f583c7cc 100644
--- a/cobbler/modules/serializer_yaml.py
+++ b/cobbler/modules/serializer_yaml.py
@@ -25,6 +25,7 @@ import os
import sys
import glob
import traceback
+import yaml # PyYAML
plib = distutils.sysconfig.get_python_lib()
mod_path="%s/cobbler" % plib
@@ -32,7 +33,6 @@ sys.path.insert(0, mod_path)
from utils import _
import utils
-import yaml # Howell-Clark version
import cexceptions
import os
@@ -87,7 +87,7 @@ def deserialize_raw(collection_type):
except IOError, ioe:
return [{}]
data = fd.read()
- datastruct = yaml.load(data).next() # first record
+ datastruct = yaml.load(data) # first record
fd.close()
return datastruct
@@ -120,7 +120,7 @@ def deserialize(obj,topological=False):
raise cexceptions.CX(_("Need permissions to read %s") % obj.filename())
data = fd.read()
try:
- datastruct = yaml.load(data).next() # first record
+ datastruct = yaml.load(data) # first record
except:
# load failure, make empty list
datastruct = []
diff --git a/cobbler/modules/sync_post_restart_services.py b/cobbler/modules/sync_post_restart_services.py
new file mode 100644
index 00000000..fa9699b9
--- /dev/null
+++ b/cobbler/modules/sync_post_restart_services.py
@@ -0,0 +1,70 @@
+import distutils.sysconfig
+import sys
+import os
+from utils import _
+import traceback
+import cexceptions
+import os
+import sys
+import xmlrpclib
+import cobbler.module_loader as module_loader
+
+plib = distutils.sysconfig.get_python_lib()
+mod_path="%s/cobbler" % plib
+sys.path.insert(0, mod_path)
+
+def register():
+ # this pure python trigger acts as if it were a legacy shell-trigger, but is much faster.
+ # the return of this method indicates the trigger type
+ return "/var/lib/cobbler/triggers/sync/post/*"
+
+def run(api,args):
+
+ settings = api.settings()
+
+ manage_dhcp = str(settings.manage_dhcp).lower()
+ manage_dns = str(settings.manage_dns).lower()
+ manage_xinetd = str(settings.manage_xinetd).lower()
+ restart_dhcp = str(settings.restart_dhcp).lower()
+ restart_dns = str(settings.restart_dns).lower()
+ restart_xinetd = str(settings.restart_xinetd).lower()
+ omapi_enabled = str(settings.omapi_enabled).lower()
+ omapi_port = str(settings.omapi_port).lower()
+
+ which_dhcp_module = module_loader.get_module_from_file("dhcp","module",just_name=True).strip()
+ which_dns_module = module_loader.get_module_from_file("dns","module",just_name=True).strip()
+
+ # special handling as we don't want to restart it twice
+ has_restarted_dnsmasq = False
+
+ rc = 0
+ if manage_dhcp != "0":
+ if which_dhcp_module == "manage_isc":
+ if not omapi_enabled in [ "1", "true", "yes", "y" ] and restart_dhcp:
+ rc = os.system("/usr/sbin/dhcpd -t")
+ if rc != 0:
+ print "/usr/sbin/dhcpd -t failed"
+ return 1
+ rc = os.system("/sbin/service dhcpd restart")
+ elif which_dhcp_module == "manage_dnsmasq":
+ if restart_dhcp:
+ rc = os.system("/sbin/service dnsmasq restart")
+ has_restarted_dnsmasq = True
+ else:
+ print "- error: unknown DHCP engine: %s" % which_dhcp_module
+ rc = 411
+
+ if manage_dns != "0" and restart_dns != "0":
+ if which_dns_module == "manage_bind":
+ rc = os.system("/sbin/service named restart")
+ elif which_dns_module == "manage_dnsmasq" and not has_restarted_dnsmasq:
+ rc = os.ssytem("/sbin/service dnsmasq restart")
+ else:
+ print "- error: unknown DNS engine: %s" % which_dns_module
+ rc = 412
+
+ if manage_xinetd != "0" and restart_xinetd != "0":
+ rc = os.system("/sbin/service xinetd restart")
+
+ return rc
+