summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG4
-rw-r--r--cobbler/action_litesync.py11
-rw-r--r--cobbler/api.py8
-rw-r--r--cobbler/collection.py1
-rw-r--r--cobbler/collection_distros.py18
-rw-r--r--cobbler/collection_profiles.py22
-rw-r--r--cobbler/collection_repos.py2
-rw-r--r--cobbler/collection_systems.py2
-rw-r--r--cobbler/commands.py9
-rw-r--r--cobbler/modules/cli_distro.py3
-rw-r--r--cobbler/modules/cli_profile.py2
-rw-r--r--cobbler/remote.py8
12 files changed, 68 insertions, 22 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 0a524de..005f8c2 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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):