diff options
-rw-r--r-- | CHANGELOG | 4 | ||||
-rw-r--r-- | cobbler/action_litesync.py | 11 | ||||
-rw-r--r-- | cobbler/api.py | 8 | ||||
-rw-r--r-- | cobbler/collection.py | 1 | ||||
-rw-r--r-- | cobbler/collection_distros.py | 18 | ||||
-rw-r--r-- | cobbler/collection_profiles.py | 22 | ||||
-rw-r--r-- | cobbler/collection_repos.py | 2 | ||||
-rw-r--r-- | cobbler/collection_systems.py | 2 | ||||
-rw-r--r-- | cobbler/commands.py | 9 | ||||
-rw-r--r-- | cobbler/modules/cli_distro.py | 3 | ||||
-rw-r--r-- | cobbler/modules/cli_profile.py | 2 | ||||
-rw-r--r-- | cobbler/remote.py | 8 |
12 files changed, 68 insertions, 22 deletions
@@ -1,12 +1,14 @@ Cobbler CHANGELOG (all entries mdehaan@redhat.com unless noted otherwise) -* Mon Jan 21 2007 - 0.7.2 +* Thu Jan 31 2007 - 0.7.2 - default_virt_file_size and default_virt_ram added to settings - enforce permissions/selinux context after reposync - better API for copying/renames, API consistancy cleanup - support for renames that resolve dependencies, inclusion in CLI+webapp - remove leading newline in rendered template files, which apparently breaks AutoYAST? +- recursive syncs automatically sync all subobjects when editing parent objects (default behavior) +- deletes can now be done recursively (optional --recursive on distro/profile remove) * Wed Jan 09 2007 - 0.7.1 - allow imports to force usage of a specific kickstart template with --kickstart diff --git a/cobbler/action_litesync.py b/cobbler/action_litesync.py index 37d5bd5..457f3af 100644 --- a/cobbler/action_litesync.py +++ b/cobbler/action_litesync.py @@ -60,6 +60,10 @@ class BootLiteSync: self.sync.write_distro_file(distro) # copy image files to images/$name in webdir & tftpboot: self.sync.copy_single_distro_files(distro) + # cascade sync + kids = distro.get_children() + for k in kids: + self.add_single_profile(k.name) def remove_single_distro(self, name): # delete distro YAML file in distros/$name in webdir @@ -84,6 +88,13 @@ class BootLiteSync: self.sync.validate_kickstart_for_specific_profile(profile) # rebuild the yum configuration files for any attached repos self.sync.retemplate_yum_repos(profile,True) + # cascade sync + kids = profile.get_children() + for k in kids: + if k.COLLECTION_TYPE == "profile": + self.add_single_profile(k.name) + else: + self.add_single_system(k.name) def remove_single_profile(self, name): # rebuild profile_list YAML file in webdir diff --git a/cobbler/api.py b/cobbler/api.py index aaec876..3b4296e 100644 --- a/cobbler/api.py +++ b/cobbler/api.py @@ -167,13 +167,13 @@ class BootAPI: self.log("copy_repo",[ref.name, newname]) return self._config.repos().copy(ref,newname) - def remove_distro(self, ref): + def remove_distro(self, ref, recursive=False): self.log("remove_distro",[ref.name]) - return self._config.distros().remove(ref.name) + return self._config.distros().remove(ref.name, recursive=recursive) - def remove_profile(self,ref): + def remove_profile(self,ref, recursive=False): self.log("remove_profile",[ref.name]) - return self._config.profiles().remove(ref.name) + return self._config.profiles().remove(ref.name, recursive=recursive) def remove_system(self,ref): self.log("remove_system",[ref.name]) diff --git a/cobbler/collection.py b/cobbler/collection.py index 90f6969..339a4b2 100644 --- a/cobbler/collection.py +++ b/cobbler/collection.py @@ -214,6 +214,7 @@ class Collection(serializable.Serializable): parent = ref.get_parent() if parent != None: parent.children[ref.name] = ref + return True def _run_triggers(self,ref,globber): diff --git a/cobbler/collection_distros.py b/cobbler/collection_distros.py index a2a0464..f78dd64 100644 --- a/cobbler/collection_distros.py +++ b/cobbler/collection_distros.py @@ -31,17 +31,25 @@ class Distros(collection.Collection): """ return distro.Distro(config).from_datastruct(seed_data) - def remove(self,name,with_delete=True,with_sync=True,with_triggers=True): + def remove(self,name,with_delete=True,with_sync=True,with_triggers=True,recursive=False): """ Remove element named 'name' from the collection """ name = name.lower() + # first see if any Groups use this distro - for v in self.config.profiles(): - if v.distro.lower() == name: - raise CX(_("removal would orphan profile: %s") % v.name) + if not recursive: + for v in self.config.profiles(): + if v.distro.lower() == name: + raise CX(_("removal would orphan profile: %s") % v.name) + obj = self.find(name=name) if obj is not None: + if recursive: + kids = obj.get_children() + for k in kids: + self.config.api.remove_profile(k, recursive=True) + if with_delete: if with_triggers: self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/distro/pre/*") @@ -55,5 +63,5 @@ class Distros(collection.Collection): if with_triggers: self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/distro/post/*") return True - raise CX(_("cannot delete object that does not exist")) + raise CX(_("cannot delete object that does not exist: %s") % name) diff --git a/cobbler/collection_profiles.py b/cobbler/collection_profiles.py index dcfd701..f00a8dc 100644 --- a/cobbler/collection_profiles.py +++ b/cobbler/collection_profiles.py @@ -32,16 +32,28 @@ class Profiles(collection.Collection): def factory_produce(self,config,seed_data): return profile.Profile(config).from_datastruct(seed_data) - def remove(self,name,with_delete=True,with_sync=True,with_triggers=True): + def remove(self,name,with_delete=True,with_sync=True,with_triggers=True,recursive=False): """ Remove element named 'name' from the collection """ + name = name.lower() - for v in self.config.systems(): - if v.profile.lower() == name: - raise CX(_("removal would orphan system: %s") % v.name) + + if not recursive: + for v in self.config.systems(): + if v.profile.lower() == name: + raise CX(_("removal would orphan system: %s") % v.name) + obj = self.find(name=name) if obj is not None: + if recursive: + kids = obj.get_children() + for k in kids: + if k.COLLECTION_TYPE == "profile": + self.config.api.remove_profile(k, recursive=True) + else: + self.config.api.remove_system(k) + if with_delete: if with_triggers: self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/profile/pre/*") @@ -55,5 +67,5 @@ class Profiles(collection.Collection): if with_triggers: self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/profile/post/*") return True - raise CX(_("cannot delete an object that does not exist")) + raise CX(_("cannot delete an object that does not exist: %s") % name) diff --git a/cobbler/collection_repos.py b/cobbler/collection_repos.py index 6e24983..44bef2a 100644 --- a/cobbler/collection_repos.py +++ b/cobbler/collection_repos.py @@ -58,5 +58,5 @@ class Repos(collection.Collection): if with_triggers: self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/repo/post/*") return True - raise CX(_("cannot delete an object that does not exist")) + raise CX(_("cannot delete an object that does not exist: %s") % name) diff --git a/cobbler/collection_systems.py b/cobbler/collection_systems.py index bdc8228..140a981 100644 --- a/cobbler/collection_systems.py +++ b/cobbler/collection_systems.py @@ -56,6 +56,6 @@ class Systems(collection.Collection): self._run_triggers(obj, "/var/lib/cobbler/triggers/delete/system/post/*") return True - raise CX(_("cannot delete an object that does not exist")) + raise CX(_("cannot delete an object that does not exist: %s") % name) diff --git a/cobbler/commands.py b/cobbler/commands.py index 294cc29..a566433 100644 --- a/cobbler/commands.py +++ b/cobbler/commands.py @@ -196,9 +196,16 @@ class CobblerFunction: """ if "remove" in self.args: + recursive = False + # only applies to distros/profiles and is not supported elsewhere + if hasattr(self.options, "recursive"): + recursive = self.options.recursive if not self.options.name: raise CX(_("name is required")) - collect_fn().remove(self.options.name,with_delete=True) + if not recursive: + collect_fn().remove(self.options.name,with_delete=True) + else: + collect_fn().remove(self.options.name,with_delete=True,recursive=True) return None # signal that we want no further processing on the object if "list" in self.args: diff --git a/cobbler/modules/cli_distro.py b/cobbler/modules/cli_distro.py index d3b32f8..35f5a4b 100644 --- a/cobbler/modules/cli_distro.py +++ b/cobbler/modules/cli_distro.py @@ -54,6 +54,9 @@ class DistroFunction(commands.CobblerFunction): if not self.matches_args(args,["report","list"]): p.add_option("--no-triggers", action="store_true", dest="notriggers", help="suppress trigger execution") + if self.matches_args(args,["remove"]): + p.add_option("--recursive", action="store_true", dest="recursive", help="also delete child objects") + def run(self): obj = self.object_manipulator_start(self.api.new_distro,self.api.distros) diff --git a/cobbler/modules/cli_profile.py b/cobbler/modules/cli_profile.py index 19d9ab4..e9d1d23 100644 --- a/cobbler/modules/cli_profile.py +++ b/cobbler/modules/cli_profile.py @@ -54,6 +54,8 @@ class ProfileFunction(commands.CobblerFunction): if not self.matches_args(args,["report", "list"]): p.add_option("--no-triggers", action="store_true", dest="notriggers", help="suppress trigger execution") + if self.matches_args(args,["remove"]): + p.add_option("--recursive", action="store_true", dest="recursive", help="also delete child objects") if not self.matches_args(args,["remove","report","list"]): p.add_option("--repos", dest="repos", help="names of cobbler repos") diff --git a/cobbler/remote.py b/cobbler/remote.py index c65bd83..221cf0c 100644 --- a/cobbler/remote.py +++ b/cobbler/remote.py @@ -863,24 +863,24 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): obj = self.__get_object(object_id) return self.__call_method(obj, attribute, arg) - def remove_distro(self,name,token): + def remove_distro(self,name,token,recursive=1): """ Deletes a distro from a collection. Note that this just requires the name of the distro, not a handle. """ self.log("remove_distro",name=name,token=token) self.check_access(token, "remove_distro", name) - rc = self.api._config.distros().remove(name) + rc = self.api._config.distros().remove(name,recursive) return rc - def remove_profile(self,name,token): + def remove_profile(self,name,token,recursive=1): """ Deletes a profile from a collection. Note that this just requires the name of the profile, not a handle. """ self.log("remove_profile",name=name,token=token) self.check_access(token, "remove_profile", name) - rc = self.api._config.profiles().remove(name) + rc = self.api._config.profiles().remove(name,recursive) return rc def remove_system(self,name,token): |