diff options
author | James Cammarata <jimi@sngx.net> | 2009-02-13 06:52:58 -0600 |
---|---|---|
committer | James Cammarata <jimi@sngx.net> | 2009-02-13 06:52:58 -0600 |
commit | 3a2a20078789d26263823b2271d3c4ac8ab7f053 (patch) | |
tree | 06a13cec50ab8db2740c1e10d532ac88c4b0d23a /cobbler | |
parent | a389783b113ada0e3e33e8eb22e3b5a4b74db71e (diff) | |
parent | 77924d6840743b8eeefbd269fa860d836e73ff0b (diff) | |
download | cobbler-3a2a20078789d26263823b2271d3c4ac8ab7f053.tar.gz cobbler-3a2a20078789d26263823b2271d3c4ac8ab7f053.tar.xz cobbler-3a2a20078789d26263823b2271d3c4ac8ab7f053.zip |
Merge branch 'devel' of git://git.fedorahosted.org/cobbler into standalone
Diffstat (limited to 'cobbler')
35 files changed, 443 insertions, 57 deletions
diff --git a/cobbler/action_buildiso.py b/cobbler/action_buildiso.py index 65dd4c35..9a72fb23 100644 --- a/cobbler/action_buildiso.py +++ b/cobbler/action_buildiso.py @@ -131,7 +131,13 @@ class BuildIso: cfg.write(HEADER) # fixme, use template print _("- generating profile list...") - for profile in self.api.profiles(): + #sort the profiles + profile_list = [profile for profile in self.profiles] + def sort_name(a,b): + return cmp(a.name,b.name) + profile_list.sort(sort_name) + + for profile in profile_list: use_this = True if profiles is not None: which_profiles = profiles.split(",") @@ -171,7 +177,13 @@ class BuildIso: cfg.write("\nMENU SEPARATOR\n") - for system in self.api.systems(): + #sort the systems + system_list = [system for system in self.systems] + def sort_name(a,b): + return cmp(a.name,b.name) + system_list.sort(sort_name) + + for system in system_list: use_this = False if systems is not None: which_systems = systems.split(",") @@ -215,7 +227,10 @@ class BuildIso: append_line = append_line + " netmask=%s" % data["subnet_" + primary_interface] if data.has_key("gateway") and data["gateway"] != "": - append_line = append_line + " gateway=%s\n" % data["gateway"] + append_line = append_line + " gateway=%s" % data["gateway"] + + if data.has_key("name_servers") and data["name_servers"]: + append_line = append_line + " dns=%s\n" % ",".join(data["name_servers"]) length=len(append_line) if length > 254: diff --git a/cobbler/action_import.py b/cobbler/action_import.py index 24738cb0..19b2f9ae 100644 --- a/cobbler/action_import.py +++ b/cobbler/action_import.py @@ -987,8 +987,11 @@ class RedHatImporter ( BaseImporter ) : data = glob.glob(os.path.join(self.get_pkgdir(), "*release-*")) data2 = [] for x in data: - if x.find("generic") == -1: - data2.append(x) + b = os.path.basename(x) + if b.find("fedora") != -1 or \ + b.find("redhat") != -1 or \ + b.find("centos") != -1: + data2.append(x) return data2 # ================================================================ @@ -1100,13 +1103,14 @@ class RedHatImporter ( BaseImporter ) : # OS_VERSION next # OS_VERSION.MINOR next # ARCH/default.ks next - # default.ks finally. + # FLAVOR.ks next kickstarts = [ "%s/%s/%s.%i.ks" % (kickbase,arch,os_version,int(minor)), "%s/%s/%s.ks" % (kickbase,arch,os_version), "%s/%s.%i.ks" % (kickbase,os_version,int(minor)), "%s/%s.ks" % (kickbase,os_version), "%s/%s/default.ks" % (kickbase,arch), + "%s/%s.ks" % (kickbase,flavor), ] for kickstart in kickstarts: if os.path.exists(kickstart): diff --git a/cobbler/action_litesync.py b/cobbler/action_litesync.py index 5dcd1a71..7773455e 100644 --- a/cobbler/action_litesync.py +++ b/cobbler/action_litesync.py @@ -101,7 +101,7 @@ class BootLiteSync: # get the profile object: profile = self.profiles.find(name=name) if profile is None: - raise CX(_("error in profile lookup")) + raise CX(_("error in profile lookup for %s" % name)) # rebuild the yum configuration files for any attached repos # generate any templates listed in the distro self.sync.pxegen.write_templates(profile) diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py index 4ebe027e..78f3c3d5 100644 --- a/cobbler/action_sync.py +++ b/cobbler/action_sync.py @@ -85,7 +85,7 @@ class BootSync: print "- running pre-sync triggers" # run pre-triggers... - utils.run_triggers(None, "/var/lib/cobbler/triggers/sync/pre/*") + utils.run_triggers(self.api, None, "/var/lib/cobbler/triggers/sync/pre/*") # (paranoid) in case the pre-trigger modified any objects... @@ -141,7 +141,7 @@ class BootSync: # run post-triggers if self.verbose: print "- running post-sync triggers" - utils.run_triggers(None, "/var/lib/cobbler/triggers/sync/post/*") + utils.run_triggers(self.api, None, "/var/lib/cobbler/triggers/sync/post/*") return True def clean_trees(self): diff --git a/cobbler/api.py b/cobbler/api.py index bbaca45a..934ed953 100644 --- a/cobbler/api.py +++ b/cobbler/api.py @@ -265,14 +265,10 @@ class BootAPI: def update(self): """ - This can be called when you expect a cobbler object - to have changed outside of your API call. It does not - have to be called before read operations but should be - called before write operations depending on the last - modification time. For the local API it is not needed. - """ - self.clear() - self.deserialize() + This can be called is no longer used by cobbler. + And is here to just avoid breaking older scripts. + """ + return True def copy_distro(self, ref, newname): self.log("copy_distro",[ref.name, newname]) diff --git a/cobbler/cobblerd.py b/cobbler/cobblerd.py index 77512611..8abe8329 100644 --- a/cobbler/cobblerd.py +++ b/cobbler/cobblerd.py @@ -112,6 +112,7 @@ def do_xmlrpc_rw(bootapi,settings,port): while True: try: + print "SERVING!" server.serve_forever() except IOError: # interrupted? try to serve again diff --git a/cobbler/collection.py b/cobbler/collection.py index 3249555f..d6df28ad 100644 --- a/cobbler/collection.py +++ b/cobbler/collection.py @@ -258,7 +258,7 @@ class Collection(serializable.Serializable): self.log_func("saving %s %s" % (self.collection_type(), ref.name)) # failure of a pre trigger will prevent the object from being added if with_triggers: - self._run_triggers(ref,"/var/lib/cobbler/triggers/add/%s/pre/*" % self.collection_type()) + self._run_triggers(self.api, ref,"/var/lib/cobbler/triggers/add/%s/pre/*" % self.collection_type()) self.listing[ref.name.lower()] = ref # save just this item if possible, if not, save @@ -284,7 +284,7 @@ class Collection(serializable.Serializable): # save the tree, so if neccessary, scripts can examine it. if with_triggers: - self._run_triggers(ref,"/var/lib/cobbler/triggers/add/%s/post/*" % self.collection_type()) + self._run_triggers(self.api, ref,"/var/lib/cobbler/triggers/add/%s/post/*" % self.collection_type()) # update children cache in parent object @@ -298,8 +298,8 @@ class Collection(serializable.Serializable): return True - def _run_triggers(self,ref,globber): - return utils.run_triggers(ref,globber) + def _run_triggers(self,api_handle,ref,globber): + return utils.run_triggers(api_handle,ref,globber) def __duplication_checks(self,ref,check_for_duplicate_names,check_for_duplicate_netinfo): """ diff --git a/cobbler/collection_distros.py b/cobbler/collection_distros.py index d032768f..ae75f407 100644 --- a/cobbler/collection_distros.py +++ b/cobbler/collection_distros.py @@ -64,7 +64,7 @@ class Distros(collection.Collection): if with_delete: if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/distro/pre/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/distro/pre/*") if with_sync: lite_sync = action_litesync.BootLiteSync(self.config) lite_sync.remove_single_profile(name) @@ -75,7 +75,7 @@ class Distros(collection.Collection): if with_delete: self.log_func("deleted distro %s" % name) if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/distro/post/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/distro/post/*") # look through all mirrored directories and find if any directory is holding # this particular distribution's kernel and initrd diff --git a/cobbler/collection_images.py b/cobbler/collection_images.py index b7466e59..64e9df01 100644 --- a/cobbler/collection_images.py +++ b/cobbler/collection_images.py @@ -43,7 +43,7 @@ class Images(collection.Collection): if obj is not None: if with_delete: if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/image/pre/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/image/pre/*") if with_sync: lite_sync = action_litesync.BootLiteSync(self.config) lite_sync.remove_single_image(name) @@ -54,7 +54,7 @@ class Images(collection.Collection): if with_delete: self.log_func("deleted repo %s" % name) if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/image/post/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/image/post/*") return True if with_delete and not self.api.is_cobblerd: diff --git a/cobbler/collection_profiles.py b/cobbler/collection_profiles.py index 57f23d43..bb27dea4 100644 --- a/cobbler/collection_profiles.py +++ b/cobbler/collection_profiles.py @@ -64,7 +64,7 @@ class Profiles(collection.Collection): if with_delete: if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/profile/pre/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/profile/pre/*") if with_sync: lite_sync = action_litesync.BootLiteSync(self.config) lite_sync.remove_single_profile(name) @@ -73,7 +73,7 @@ class Profiles(collection.Collection): if with_delete: self.log_func("deleted profile %s" % name) if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/profile/post/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/profile/post/*") if with_delete and not self.api.is_cobblerd: self.api._internal_cache_update("profile", name, remove=True) diff --git a/cobbler/collection_repos.py b/cobbler/collection_repos.py index 976c61e3..3b2c1c20 100644 --- a/cobbler/collection_repos.py +++ b/cobbler/collection_repos.py @@ -56,7 +56,7 @@ class Repos(collection.Collection): if obj is not None: if with_delete: if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/repo/pre/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/repo/pre/*") del self.listing[name] self.config.serialize_delete(self, obj) @@ -64,7 +64,7 @@ class Repos(collection.Collection): if with_delete: self.log_func("deleted repo %s" % name) if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/repo/post/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/repo/post/*") path = "/var/www/cobbler/repo_mirror/%s" % obj.name if os.path.exists(path): diff --git a/cobbler/collection_systems.py b/cobbler/collection_systems.py index 0c0b2b31..5a628248 100644 --- a/cobbler/collection_systems.py +++ b/cobbler/collection_systems.py @@ -52,7 +52,7 @@ class Systems(collection.Collection): if with_delete: if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/system/pre/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/system/pre/*") if with_sync: lite_sync = action_litesync.BootLiteSync(self.config) lite_sync.remove_single_system(name) @@ -61,7 +61,7 @@ class Systems(collection.Collection): if with_delete: self.log_func("deleted system %s" % name) if with_triggers: - self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/system/post/*") + self._run_triggers(self.config.api, obj, "/var/lib/cobbler/triggers/delete/system/post/*") if with_delete and not self.api.is_cobblerd: self.api._internal_cache_update("system", name, remove=True) diff --git a/cobbler/item.py b/cobbler/item.py index a4ecea5b..fbb1d9d5 100644 --- a/cobbler/item.py +++ b/cobbler/item.py @@ -138,7 +138,7 @@ class Item(serializable.Serializable): like authz_ownership, which ships with Cobbler but is off by default. Consult the Wiki docs for more info on CustomizableAuthorization. """ - owners = utils.input_string_or_list(data) + owners = utils.input_string_or_list(data, delim=" ") self.owners = owners return True diff --git a/cobbler/item_profile.py b/cobbler/item_profile.py index d30eb52a..eafdfa14 100644 --- a/cobbler/item_profile.py +++ b/cobbler/item_profile.py @@ -69,6 +69,7 @@ class Profile(item.Item): self.ctime = 0 self.mtime = 0 self.name_servers = (self.settings.default_name_servers, '<<inherit>>')[is_subobject] + self.name_servers_search = (self.settings.default_name_servers_search, '<<inherit>>')[is_subobject] self.redhat_management_key = "<<inherit>>" def from_datastruct(self,seed_data): @@ -95,6 +96,7 @@ class Profile(item.Item): self.ctime = self.load_item(seed_data,'ctime',0) self.mtime = self.load_item(seed_data,'mtime',0) self.name_servers = self.load_item(seed_data,'name_servers',[]) + self.name_servers_search = self.load_item(seed_data,'name_servers_search',[]) self.redhat_management_key = self.load_item(seed_data,'redhat_management_key', '<<inherit>>') # backwards compatibility @@ -180,10 +182,16 @@ class Profile(item.Item): return utils.set_redhat_management_key(self,key) def set_name_servers(self,data): - data = utils.input_string_or_list(data) + # FIXME: move to utils since shared with system + data = utils.input_string_or_list(data, delim=" ") self.name_servers = data return True + def set_name_servers_search(self,data): + data = utils.input_string_or_list(data, delim=" ") + self.name_servers_search = data + return True + def set_enable_menu(self,enable_menu): """ Sets whether or not the profile will be listed in the default @@ -304,6 +312,7 @@ class Profile(item.Item): 'ctime' : self.ctime, 'mtime' : self.mtime, 'name_servers' : self.name_servers, + 'name_servers_search' : self.name_servers_search, 'uid' : self.uid, 'random_id' : self.random_id, 'redhat_management_key' : self.redhat_management_key @@ -328,6 +337,7 @@ class Profile(item.Item): buf = buf + _("mgmt classes : %s\n") % self.mgmt_classes buf = buf + _("modified : %s\n") % time.ctime(self.mtime) buf = buf + _("name servers : %s\n") % self.name_servers + buf = buf + _("name servers search : %s\n") % self.name_servers_search buf = buf + _("owners : %s\n") % self.owners buf = buf + _("post kernel options : %s\n") % self.kernel_options_post buf = buf + _("redhat mgmt key : %s\n") % self.redhat_management_key @@ -379,6 +389,7 @@ class Profile(item.Item): 'mgmt_classes' : self.set_mgmt_classes, 'comment' : self.set_comment, 'name_servers' : self.set_name_servers, + 'name_servers_search' : self.set_name_servers_search, 'redhat_management_key' : self.set_redhat_management_key } diff --git a/cobbler/item_system.py b/cobbler/item_system.py index 91a7f62b..4445f5ec 100644 --- a/cobbler/item_system.py +++ b/cobbler/item_system.py @@ -74,6 +74,7 @@ class System(item.Item): self.hostname = "" self.gateway = "" self.name_servers = "" + self.name_servers_search = "" self.bonding = "" self.bonding_master = "" self.bonding_opts = "" @@ -175,6 +176,7 @@ class System(item.Item): self.hostname = self.load_item(seed_data, 'hostname', __hostname) self.name_servers = self.load_item(seed_data, 'name_servers', '<<inherit>>') + self.name_servers_search = self.load_item(seed_data, 'name_servers_search', '<<inherit>>') self.redhat_management_key = self.load_item(seed_data, 'redhat_management_key', '<<inherit>>') # virt specific @@ -444,10 +446,15 @@ class System(item.Item): return True def set_name_servers(self,data): - data = utils.input_string_or_list(data) + data = utils.input_string_or_list(data, delim=" ") self.name_servers = data return True + def set_name_servers_search(self,data): + data = utils.input_string_or_list(data, delim=" ") + self.name_servers_search = data + return True + def set_subnet(self,subnet,interface): intf = self.__get_interface(interface) intf["subnet"] = subnet @@ -662,6 +669,7 @@ class System(item.Item): 'hostname' : self.hostname, 'gateway' : self.gateway, 'name_servers' : self.name_servers, + 'name_servers_search' : self.name_servers_search, 'redhat_management_key' : self.redhat_management_key } @@ -681,6 +689,7 @@ class System(item.Item): buf = buf + _("modified : %s\n") % time.ctime(self.mtime) buf = buf + _("name servers : %s\n") % self.name_servers + buf = buf + _("name servers search : %s\n") % self.name_servers_search buf = buf + _("netboot enabled? : %s\n") % self.netboot_enabled buf = buf + _("owners : %s\n") % self.owners buf = buf + _("server : %s\n") % self.server @@ -787,6 +796,7 @@ class System(item.Item): 'hostname' : self.set_hostname, 'gateway' : self.set_gateway, 'name_servers' : self.set_name_servers, + 'name_servers_search' : self.set_name_servers_search, 'redhat_management_key' : self.set_redhat_management_key } diff --git a/cobbler/module_loader.py b/cobbler/module_loader.py index a7be1f68..f50e4bf4 100644 --- a/cobbler/module_loader.py +++ b/cobbler/module_loader.py @@ -82,7 +82,7 @@ def load_modules(module_path=mod_path, blacklist=None): def get_module_by_name(name): return MODULE_CACHE.get(name, None) -def get_module_from_file(category,field,fallback_module_name=None): +def get_module_from_file(category,field,fallback_module_name=None,just_name=False): try: value = cp.get(category,field) @@ -91,6 +91,8 @@ def get_module_from_file(category,field,fallback_module_name=None): value = fallback_module_name else: raise CX(_("Cannot find config file setting for: %s") % field) + if just_name: + return value rc = MODULE_CACHE.get(value, None) if rc is None: raise CX(_("Failed to load module for %s/%s") % (category,field)) diff --git a/cobbler/modules/cli_distro.py b/cobbler/modules/cli_distro.py index 0c1425b1..2472f918 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 diff --git a/cobbler/modules/cli_image.py b/cobbler/modules/cli_image.py index b6b96ff4..8725ca35 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 diff --git a/cobbler/modules/cli_misc.py b/cobbler/modules/cli_misc.py index 5855a0a1..7174cdaf 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 diff --git a/cobbler/modules/cli_profile.py b/cobbler/modules/cli_profile.py index 03efb7bf..f5933938 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") @@ -158,6 +159,8 @@ 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) diff --git a/cobbler/modules/cli_repo.py b/cobbler/modules/cli_repo.py index a8483dcb..0bcb0dba 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 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 0c6499d7..12f81a79 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,6 +73,7 @@ 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("--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") @@ -245,6 +246,8 @@ 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) 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 5acbf208..657a9a77 100644 --- a/cobbler/modules/manage_bind.py +++ b/cobbler/modules/manage_bind.py @@ -81,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: @@ -125,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: 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 + diff --git a/cobbler/pxegen.py b/cobbler/pxegen.py index bbe27ec8..633e5359 100644 --- a/cobbler/pxegen.py +++ b/cobbler/pxegen.py @@ -579,6 +579,23 @@ class PXEGen: listfile.write("%s\n" % profile.name) f2 = os.path.join(self.bootloc, "s390x", "p_%s" % profile.name) self.write_pxe_file(f2,None,profile,distro,distro.arch) + cf = "%s_conf" % f2 + pf = "%s_parm" % f2 + template_cf = open("/etc/cobbler/pxe/s390x_conf.template") + template_pf = open("/etc/cobbler/pxe/s390x_parm.template") + blended = utils.blender(self.api, True, profile) + self.templar.render(template_cf, blended, cf) + # FIXME: profiles also need this data! + kickstart_path = "http://%s/cblr/svc/op/ks/profile/%s" % (blended["http_server"], profile.name) + meta2 = {} + meta2["kickstart_expanded"] = "ks=%s" % kickstart_path + ## FIXME: this may not work right for kernel options with + ## a space in them though there are not many of those. + meta2["kernel_options"] = "\n".join(blended["kernel_options"].split(" ")) + meta2["confname"] = "p_%s_conf" % profile.name + self.templar.render(template_pf, meta2, pf) + + listfile.close() def make_actual_pxe_menu(self): diff --git a/cobbler/remote.py b/cobbler/remote.py index a36ade31..f7f90e9c 100644 --- a/cobbler/remote.py +++ b/cobbler/remote.py @@ -303,7 +303,11 @@ class CobblerXMLRPCInterface: Return the contents of /etc/cobbler/settings, which is a hash. """ self._log("get_settings",token=token) - return self.__get_all("settings") + results = self.api.settings() + self._log("got settings") + data = results.to_datastruct() + self._log("my settings are: %s" % data) + return self.xmlrpc_hacks(results) def get_repo_config_for_profile(self,profile_name,**rest): """ @@ -526,7 +530,7 @@ class CobblerXMLRPCInterface: # time if reinstalling all of a cluster all at once. # we can do that at "cobbler check" time. - utils.run_triggers(None, "/var/lib/cobbler/triggers/install/%s/*" % mode, additional=[objtype,name,ip]) + utils.run_triggers(self.api, None, "/var/lib/cobbler/triggers/install/%s/*" % mode, additional=[objtype,name,ip]) return True @@ -1900,6 +1904,7 @@ def test_xmlrpc_rw(): server.modify_profile(pid, "mgmt-classes", "one two three", token) server.modify_profile(pid, "comment", "...", token) server.modify_profile(pid, "name_servers", ["one","two"], token) + server.modify_profile(pid, "name_servers_search", ["one","two"], token) server.modify_profile(pid, "redhat_management_key", "BETA", token) server.save_profile(pid, token) @@ -1918,6 +1923,7 @@ def test_xmlrpc_rw(): server.modify_system(sid, 'virt-path', "/opt/images", token) server.modify_system(sid, 'virt-type', 'qemu', token) server.modify_system(sid, 'name_servers', 'one two three four', token) + server.modify_system(sid, 'name_servers_search', 'one two three four', token) server.modify_system(sid, 'modify-interface', { "macaddress-eth0" : "AA:BB:CC:EE:EE:EE", "ipaddress-eth0" : "192.168.10.50", diff --git a/cobbler/settings.py b/cobbler/settings.py index e87536c7..816efff3 100644 --- a/cobbler/settings.py +++ b/cobbler/settings.py @@ -30,14 +30,21 @@ TESTMODE = False # we need. DEFAULTS = { + "anamon_enabled" : 0, "allow_duplicate_hostnames" : 0, "allow_duplicate_macs" : 0, "allow_duplicate_ips" : 0, "bind_bin" : "/usr/sbin/named", + "build_reporting_enabled" : 0, + "build_reporting_to_address" : "", + "build_reporting_sender" : "", + "build_reporting_subject" : "", + "build_reporting_smtp_server" : "localhost", "cheetah_import_whitelist" : [ "re", "random", "time" ], "cobbler_master" : '', "default_kickstart" : "/var/lib/cobbler/kickstarts/default.ks", "default_name_servers" : '', + "default_name_servers_search" : '', "default_password_crypted" : "\$1\$mF86/UHC\$WvcIcX2t6crBz2onWxyac.", "default_virt_bridge" : "xenbr0", "default_virt_type" : "auto", @@ -103,8 +110,7 @@ DEFAULTS = { "xmlrpc_port" : 25151, "yum_post_install_mirror" : 1, "yumdownloader_flags" : "--resolve", - "yumreposync_flags" : "-l", - "anamon_enabled" : 0, + "yumreposync_flags" : "-l" } diff --git a/cobbler/templar.py b/cobbler/templar.py index 5cdd4959..f2e4b7f1 100644 --- a/cobbler/templar.py +++ b/cobbler/templar.py @@ -32,13 +32,14 @@ import utils class Templar: - def __init__(self,config): + def __init__(self,config=None): """ Constructor """ - self.config = config - self.api = config.api - self.settings = config.settings() + if config is not None: + self.config = config + self.api = config.api + self.settings = config.settings() def check_for_invalid_imports(self,data): """ diff --git a/cobbler/utils.py b/cobbler/utils.py index a4101cff..6ddde053 100644 --- a/cobbler/utils.py +++ b/cobbler/utils.py @@ -75,8 +75,6 @@ def _(foo): MODULE_CACHE = {} -# import api # factor out - _re_kernel = re.compile(r'vmlinuz(.*)') _re_initrd = re.compile(r'initrd(.*).img') @@ -660,15 +658,34 @@ def hash_to_string(hash): buffer = buffer + str(key) + "=" + str(value) + " " return buffer -def run_triggers(ref,globber,additional=[]): +def run_triggers(api,ref,globber,additional=[]): """ Runs all the trigger scripts in a given directory. ref can be a cobbler object, if not None, the name will be passed to the script. If ref is None, the script will be called with no argumenets. Globber is a wildcard expression indicating which triggers to run. Example: "/var/lib/cobbler/triggers/blah/*" + + As of Cobbler 1.5.X, this also runs cobbler modules that match the globbing paths. """ + # Python triggers first, before shell + + modules = api.get_modules_in_category(globber) + print "DEBUG: trigger modules matching %s are %s" % (globber, [m.__name__ for m in modules]) + for m in modules: + arglist = [] + if ref: + arglist.append(ref.name) + for x in additional: + arglist.append(x) + rc = m.run(api, arglist) + if rc != 0: + raise CX("cobbler trigger failed: %s" % m.__name__) + + # now do the old shell triggers, which are usually going to be slower, but are easier to write + # and support any language + triggers = glob.glob(globber) triggers.sort() for file in triggers: diff --git a/cobbler/webui/CobblerWeb.py b/cobbler/webui/CobblerWeb.py index f29a9496..72f3659a 100644 --- a/cobbler/webui/CobblerWeb.py +++ b/cobbler/webui/CobblerWeb.py @@ -512,7 +512,7 @@ class CobblerWeb(object): def system_save(self,name=None,comment=None,editmode="edit",profile=None, kopts=None, koptspost=None, ksmeta=None, owners=None, server_override=None, netboot='n', virtpath=None,virtram=None,virttype=None,virtcpus=None,virtfilesize=None, - name_servers=None, + name_servers=None,name_servers_search=None, power_type=None, power_user=None, power_pass=None, power_id=None, power_address=None, gateway=None,hostname=None,redhatmanagementkey=None,delete1=None, delete2=None, **args): @@ -565,6 +565,7 @@ class CobblerWeb(object): self.remote.modify_system(system, 'power_id', power_id, self.token) self.remote.modify_system(system, 'power_address', power_address, self.token) self.remote.modify_system(system, 'name_servers', name_servers, self.token) + self.remote.modify_system(system, 'name_servers_search', name_servers_search, self.token) self.remote.modify_system(system, 'gateway', gateway, self.token) self.remote.modify_system(system, 'hostname', hostname, self.token) self.remote.modify_system(system, 'redhat_management_key', redhatmanagementkey, self.token) @@ -678,7 +679,7 @@ class CobblerWeb(object): ksmeta=None,owners=None,enablemenu=None,virtfilesize=None,virtram=None,virttype=None, virtpath=None,repos=None,dhcptag=None,delete1=False,delete2=False, parent=None,virtcpus=None,virtbridge=None,subprofile=None,server_override=None, - name_servers=None,redhatmanagementkey=None,recursive=False,**args): + name_servers=None,name_servers_search=None,redhatmanagementkey=None,recursive=False,**args): if not self.__xmlrpc_setup(): return self.xmlrpc_auth_failure() @@ -745,6 +746,7 @@ class CobblerWeb(object): self.remote.modify_profile(profile, 'server', server_override, self.token) self.remote.modify_profile(profile, 'comment', comment, self.token) self.remote.modify_profile(profile, 'name_servers', name_servers, self.token) + self.remote.modify_profile(profile, 'name_servers_search', name_servers_search, self.token) self.remote.modify_profile(profile, 'redhat_management_key', redhatmanagementkey, self.token) if repos is None: |