diff options
author | James Cammarata <jimi@sngx.net> | 2009-03-07 21:44:00 -0600 |
---|---|---|
committer | James Cammarata <jimi@sngx.net> | 2009-03-07 21:44:00 -0600 |
commit | d3fdc6d4965b02ce18346f067c14080115943a38 (patch) | |
tree | d2fa630d3f0e941acb7f5115c31ea91aabb4ae11 /cobbler/modules | |
parent | 54e462f3dca472d8bb8dc8a2b0a69c60ed9fe2ec (diff) | |
parent | 61db7baa541acc32b305ea6977a14ee8f5b3f470 (diff) | |
download | cobbler-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.py | 4 | ||||
-rw-r--r-- | cobbler/modules/authn_ldap.py | 1 | ||||
-rw-r--r-- | cobbler/modules/authn_spacewalk.py | 111 | ||||
-rw-r--r-- | cobbler/modules/cli_distro.py | 5 | ||||
-rw-r--r-- | cobbler/modules/cli_image.py | 4 | ||||
-rw-r--r-- | cobbler/modules/cli_misc.py | 19 | ||||
-rw-r--r-- | cobbler/modules/cli_profile.py | 10 | ||||
-rw-r--r-- | cobbler/modules/cli_repo.py | 4 | ||||
-rw-r--r-- | cobbler/modules/cli_report.py | 2 | ||||
-rw-r--r-- | cobbler/modules/cli_system.py | 10 | ||||
-rw-r--r-- | cobbler/modules/install_post_log.py | 29 | ||||
-rwxr-xr-x | cobbler/modules/install_post_report.py | 101 | ||||
-rwxr-xr-x | cobbler/modules/install_pre_clear_anamon_logs.py | 51 | ||||
-rw-r--r-- | cobbler/modules/install_pre_log.py | 29 | ||||
-rw-r--r-- | cobbler/modules/manage_bind.py | 31 | ||||
-rw-r--r-- | cobbler/modules/manage_dnsmasq.py | 1 | ||||
-rw-r--r-- | cobbler/modules/manage_isc.py | 6 | ||||
-rw-r--r-- | cobbler/modules/serializer_catalog.py | 24 | ||||
-rw-r--r-- | cobbler/modules/serializer_yaml.py | 6 | ||||
-rw-r--r-- | cobbler/modules/sync_post_restart_services.py | 70 |
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 + |