Repository: cobbler/cobbler

Issue:
Flags/Settings for 'rsync' commands.
It seems that in the settings, this setting:

```
  # replication rsync options for repos set to override default value of "-avzH"
  replicate_repo_rsync_options: "-avzH"
is ignored and actually set in:
  /usr/lib/python2.6/site-packages/cobbler/action_reposync.py
by:
  # FIXME: wrapper for subprocess that logs to logger
  cmd = "rsync -rltDv --copy-unsafe-links --delete-after
```

I may very well be wrong. My apologies if that's the case. If not this should be documented and/or corrected. At minimum, documented in the settings file until it is addressed.


Discussion:
you are right, should be fixed.
i'll take a look at this one.

well, it seems the settings configuration option is only meant for replication between cobbler instances.
but i don like the hardcoded one for repo mirroring...

I will submit a pull request for this soon. On my build from branch v3.1.2 I moved those rsync options to settings and also added a field "rsync options" to repo for individual support.  I will need to look more closely at the setting reposync_rsync_flags but I think it was being used for something else.

Resolving patch:
diff --git a/cobbler/actions/reposync.py b/cobbler/actions/reposync.py
--- a/cobbler/actions/reposync.py
+++ b/cobbler/actions/reposync.py
@@ -348,13 +348,39 @@ def rsync_sync(self, repo):
         if not repo.mirror.strip().endswith("/"):
             repo.mirror = "%s/" % repo.mirror
 
-        # FIXME: wrapper for subprocess that logs to logger
-        cmd = "rsync -rltDv --copy-unsafe-links --delete-after %s --delete --exclude-from=/etc/cobbler/rsync.exclude %s %s" % (spacer, pipes.quote(repo.mirror), pipes.quote(dest_path))
+        flags = ''
+        for x in repo.rsyncopts:
+            if repo.rsyncopts[x]:
+                flags += " %s %s" % (x, repo.rsyncopts[x])
+            else:
+                flags += " %s" % x
+        
+        if flags == '':
+            flags = self.settings.reposync_rsync_flags
+
+        cmd = "rsync %s --delete-after %s --delete --exclude-from=/etc/cobbler/rsync.exclude %s %s" % (flags, spacer, pipes.quote(repo.mirror), pipes.quote(dest_path))
         rc = utils.subprocess_call(self.logger, cmd)
 
         if rc != 0:
             utils.die(self.logger, "cobbler reposync failed")
-        repo_walker(dest_path, self.createrepo_walker, repo)
+        
+        # if ran in archive mode then repo should already contain all repodata and does not need createrepo run 
+        archive = False
+        if '--archive' in flags:
+            archive = True
+        else:
+            # split flags and skip all --{options} as we need to look for combined flags like -vaH
+            fl = flags.split()
+            for f in fl:
+                if f.startswith('--'):
+                    pass
+                else:
+                    if 'a' in f:
+                        archive = True
+                        break
+        if not archive:
+            repo_walker(dest_path, self.createrepo_walker, repo)
+
         self.create_local_file(dest_path, repo)
 
     # ====================================================================================
diff --git a/cobbler/items/repo.py b/cobbler/items/repo.py
--- a/cobbler/items/repo.py
+++ b/cobbler/items/repo.py
@@ -52,6 +52,7 @@
     ["proxy", "<<inherit>>", 0, "Proxy information", True, "http://example.com:8080, or <<inherit>> to use proxy_url_ext from settings, blank or <<None>> for no proxy", [], "str"],
     ["rpm_list", [], 0, "RPM List", True, "Mirror just these RPMs (yum only)", 0, "list"],
     ["yumopts", {}, 0, "Yum Options", True, "Options to write to yum config file", 0, "dict"],
+    ["rsyncopts", "", 0, "Rsync Options", True, "Options to use with rsync repo", 0, "dict"],
 ]
 
 
@@ -69,6 +70,7 @@ def __init__(self, *args, **kwargs):
         self.arch = None
         self.environment = {}
         self.yumopts = {}
+        self.rsyncopts = {}
 
     #
     # override some base class methods first (item.Item)
@@ -160,6 +162,18 @@ def set_yumopts(self, options):
         else:
             self.yumopts = value
 
+    def set_rsyncopts(self, options):
+        """
+        rsync options are a space delimited list
+
+        :param options: Something like '-a -S -H -v'
+        """
+        (success, value) = utils.input_string_or_dict(options, allow_multiples=False)
+        if not success:
+            raise CX(_("invalid rsync options"))
+        else:
+            self.rsyncopts = value
+
     def set_environment(self, options):
         """
         Yum can take options from the environment. This puts them there before each reposync.
diff --git a/cobbler/web/field_ui_info.py b/cobbler/web/field_ui_info.py
--- a/cobbler/web/field_ui_info.py
+++ b/cobbler/web/field_ui_info.py
@@ -139,7 +139,7 @@
     {"General": ["name", "owners", "arch", "breed", "keep_updated",
                  "mirror", "rpm_list", "comment"]},
     {"Advanced": ["apt_components", "apt_dists", "createrepo_flags",
-                  "environment", "mirror_locally", "priority", "yumopts"]}
+                  "environment", "mirror_locally", "priority", "yumopts", "rsyncopts"]}
 ]
 
 SYSTEM_UI_FIELDS_MAPPING = [


Test patch: