Hello,

I've written a patch to make reposync more modular. The essential thing is moving the argument parsing to the spacewalk-repo-sync script and out of python/site-packages, but there are also a lot of other style improvements.

We've already applied those changes and others in our branch, I just merged some of them into the spacewalk branch now.

I hope you like it,
-Ionuț
>From e8a14d14817f57432c14c1d469bc07559359bf40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ionu=C8=9B=20Ar=C8=9B=C4=83ri=C8=99i?= <iartar...@suse.cz>
Date: Fri, 2 Dec 2011 17:09:13 +0100
Subject: [PATCH] make reposync more modular

- move argument parsing to the spacewalk-repo-sync script
- move repo setup to a special method in yum_src
- fixed other minor issues (indentation, class constructor, other pep-8 issues)
---
 backend/satellite_tools/repo_plugins/yum_src.py |   60 +++++----
 backend/satellite_tools/reposync.py             |  155 +++++++++--------------
 backend/satellite_tools/spacewalk-repo-sync     |   64 +++++++---
 3 files changed, 142 insertions(+), 137 deletions(-)

diff --git a/backend/satellite_tools/repo_plugins/yum_src.py b/backend/satellite_tools/repo_plugins/yum_src.py
index f0949da..8d0a557 100644
--- a/backend/satellite_tools/repo_plugins/yum_src.py
+++ b/backend/satellite_tools/repo_plugins/yum_src.py
@@ -1,6 +1,6 @@
 #
 # Copyright (c) 2008--2011 Red Hat, Inc.
-# Copyright (c) 2010--2011 SUSE Linux Products GmbH
+# Copyright (c) 2010--2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # This software is licensed to you under the GNU General Public License,
 # version 2 (GPLv2). There is NO WARRANTY for this software, express or
@@ -8,15 +8,17 @@
 # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 # along with this software; if not, see
 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
-# 
+#
 # Red Hat trademarks are not licensed under GPLv2. No permission is
 # granted to use or replicate Red Hat trademarks that are incorporated
-# in this software or its documentation. 
+# in this software or its documentation.
 #
-import yum
+
 import shutil
 import sys
 import gzip
+
+import yum
 from yum.update_md import UpdateMetadata, UpdateNoticeException, UpdateNotice
 from yum.yumRepo import YumRepository
 try:
@@ -30,6 +32,8 @@ except ImportError:
 from spacewalk.satellite_tools.reposync import ContentPackage
 from spacewalk.common.rhnConfig import CFG, initCFG
 
+CACHE_DIR = '/var/cache/rhn/reposync/'
+
 class YumWarnings:
     def write(self, s):
         pass
@@ -75,10 +79,10 @@ class YumUpdateMetadata(UpdateMetadata):
                             no.add(un)
 
 class ContentSource:
-    repo = None
-    cache_dir = '/var/cache/rhn/reposync/'
     def __init__(self, url, name):
-        self._clean_cache(self.cache_dir + name)
+        self.url = url
+        self.name = name
+        self._clean_cache(CACHE_DIR + name)
 
         # read the proxy configuration in /etc/rhn/rhn.conf
         initCFG('server.satellite')
@@ -92,15 +96,25 @@ class ContentSource:
             self.proxy_url = "http://%s"; %(self.proxy_addr)
         else:
             self.proxy_url = None
+
         repo = yum.yumRepo.YumRepository(name)
         self.repo = repo
+        self.sack = None
+
+        self.setup_repo(repo)
+        self.num_packages = 0
+        self.num_excluded = 0
+
+    def setup_repo(self, repo):
+        """Fetch repository metadata"""
         repo.cache = 0
         repo.metadata_expire = 0
-        repo.mirrorlist = url
-        repo.baseurl = [url]
-        repo.basecachedir = self.cache_dir
+        repo.mirrorlist = self.url
+        repo.baseurl = [self.url]
+        repo.basecachedir = CACHE_DIR
         if hasattr(repo, 'base_persistdir'):
-            repo.base_persistdir = self.cache_dir
+            repo.base_persistdir = CACHE_DIR
+
         if self.proxy_url is not None:
             repo.proxy = self.proxy_url
 
@@ -108,28 +122,24 @@ class ContentSource:
         warnings.disable()
         repo.baseurlSetup()
         warnings.restore()
-
         repo.setup(False)
-        self.num_packages = 0
-        self.num_excluded = 0
-
+        self.sack = self.repo.getPackageSack()
 
     def list_packages(self, filters):
         """ list packages"""
-        sack = self.repo.getPackageSack()
-        sack.populate(self.repo, 'metadata', None, 0)
-        list = sack.returnPackages()
+        self.sack.populate(self.repo, 'metadata', None, 0)
+        list = self.sack.returnPackages()
         self.num_packages = len(list)
         if filters:
             list = self._filter_packages(list, filters)
-            list = self._get_package_dependencies(sack, list)
+            list = self._get_package_dependencies(self.sack, list)
             self.num_excluded = self.num_packages - len(list)
         to_return = []
         for pack in list:
             if pack.arch == 'src':
                 continue
             new_pack = ContentPackage()
-            new_pack.setNVREA(pack.name, pack.version, pack.release, 
+            new_pack.setNVREA(pack.name, pack.version, pack.release,
                               pack.epoch, pack.arch)
             new_pack.unique_id = pack
             new_pack.checksum_type = pack.checksums[0][0]
@@ -201,8 +211,8 @@ class ContentSource:
         shutil.rmtree(directory, True)
 
     def get_updates(self):
-      if not self.repo.repoXML.repoData.has_key('updateinfo'):
-        return []
-      um = YumUpdateMetadata()
-      um.add(self.repo, all=True)
-      return um.notices
+        if not self.repo.repoXML.repoData.has_key('updateinfo'):
+            return []
+        um = YumUpdateMetadata()
+        um.add(self.repo, all=True)
+        return um.notices
diff --git a/backend/satellite_tools/reposync.py b/backend/satellite_tools/reposync.py
index 2ba1d7d..1893545 100644
--- a/backend/satellite_tools/reposync.py
+++ b/backend/satellite_tools/reposync.py
@@ -13,12 +13,13 @@
 # granted to use or replicate Red Hat trademarks that are incorporated
 # in this software or its documentation.
 #
-import sys, os, time
 import hashlib
+import os
 import re
+import sys
+import time
 from datetime import datetime
-import traceback
-from optparse import OptionParser
+
 from spacewalk.server import rhnPackage, rhnSQL, rhnChannel, rhnPackageUpload
 from spacewalk.common import rhnLog
 from spacewalk.common.rhnLog import log_debug
@@ -40,84 +41,66 @@ def set_filter_opt(option, opt_str, value, parser):
     else:                               f_type = '-'
     parser.values.filters.append((f_type, re.split('[,\s]+', value)))
 
-class RepoSync:
 
-    parser = None
-    type = None
-    urls = None
-    channel_label = None
-    channel = None
-    fail = False
-    quiet = False
-    regen = False
-    filters = []
+class RepoSync(object):
+    def __init__(self, channel_label, repo_type, url=None, fail=False,
+                 quiet=False, filters=[]):
+        self.regen = False
+        self.fail = fail
+        self.quiet = quiet
+        self.filters = filters
 
-    def main(self):
         initCFG('server')
         db_string = CFG.DEFAULT_DB #"rhnsat/rhnsat@rhnsat"
         rhnSQL.initDB(db_string)
-        (options, args) = self.process_args()
 
+        # setup logging
         log_filename = 'reposync.log'
-        if options.channel_label:
-            date = time.localtime()
-            datestr = '%d.%02d.%02d-%02d:%02d:%02d' % (date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec)
-            log_filename = options.channel_label + '-' +  datestr + '.log'
-
+        date = time.localtime()
+        datestr = '%d.%02d.%02d-%02d:%02d:%02d' % (
+            date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour,
+            date.tm_min, date.tm_sec)
+        log_filename = channel_label + '-' +  datestr + '.log'
         rhnLog.initLOG(default_log_location + log_filename)
         #os.fchown isn't in 2.4 :/
         os.system("chgrp apache " + default_log_location + log_filename)
 
-        if options.type not in ["yum"]:
-            print "Error: Unknown type %s" % options.type
-            sys.exit(2)
-
-        quit = False
-        if not options.url:
-            if options.channel_label:
-                # TODO:need to look at user security across orgs
-                h = rhnSQL.prepare("""select s.id, s.source_url
-                                      from rhnContentSource s,
-                                           rhnChannelContentSource cs,
-                                           rhnChannel c
-                                     where s.id = cs.source_id
-                                       and cs.channel_id = c.id
-                                       and c.label = :label""")
-                h.execute(label=options.channel_label)
-                source_data = h.fetchall_dict() or []
-                if source_data:
-                    self.urls = [(row['id'], row['source_url']) for row in source_data]
-                else:
-                    quit = True
-                    self.error_msg("Channel has no URL associated")
-        else:
-            self.urls = [(None, options.url)]
-        if not options.channel_label:
-            quit = True
-            self.error_msg("--channel must be specified")
-
-        self.filters = options.filters
         self.log_msg("\nSync started: %s" % (time.asctime(time.localtime())))
         self.log_msg(str(sys.argv))
 
+        if not url:
+            # TODO:need to look at user security across orgs
+            h = rhnSQL.prepare("""select s.id, s.source_url
+                                  from rhnContentSource s,
+                                       rhnChannelContentSource cs,
+                                       rhnChannel c
+                                 where s.id = cs.source_id
+                                   and cs.channel_id = c.id
+                                   and c.label = :label""")
+            h.execute(label=channel_label)
+            source_data = h.fetchall_dict()
+            if source_data:
+                self.urls = [(row['id'], row['source_url']) for row in source_data]
+            else:
+                self.error_msg("Channel has no URL associated")
+                sys.exit(1)
+        else:
+            self.urls = [(None, url)]
 
-        if quit:
-            sys.exit(1)
+        self.repo_plugin = self.load_plugin(repo_type)
+        self.channel_label = channel_label
 
-        self.type = options.type
-        self.channel_label = options.channel_label
-        self.fail = options.fail
-        self.quiet = options.quiet
         self.channel = self.load_channel()
-
         if not self.channel or not rhnChannel.isCustomChannel(self.channel['id']):
-            print "Channel does not exist or is not custom"
+            self.print_msg("Channel does not exist or is not custom.")
             sys.exit(1)
 
+    def sync(self):
+        """Trigger a reposync"""
         start_time = datetime.now()
-        for (id, url) in self.urls:
-            plugin = self.load_plugin()(url, self.channel_label)
-            self.import_packages(plugin, id, url)
+        for (repo_id, url) in self.urls:
+            plugin = self.repo_plugin(url, self.channel_label)
+            self.import_packages(plugin, repo_id, url)
             self.import_updates(plugin, url)
         if self.regen:
             taskomatic.add_to_repodata_queue_for_channel_package_subscription(
@@ -136,29 +119,17 @@ class RepoSync:
                              where label = :channel""")
         h.execute(channel=self.channel['label'])
 
-    def process_args(self):
-        self.parser = OptionParser()
-        self.parser.add_option('-u', '--url', action='store', dest='url', help='The url to sync')
-        self.parser.add_option('-c', '--channel', action='store', dest='channel_label', help='The label of the channel to sync packages to')
-        self.parser.add_option('-t', '--type', action='store', dest='type', help='The type of repo, currently only "yum" is supported', default='yum')
-        self.parser.add_option('-f', '--fail', action='store_true', dest='fail', default=False , help="If a package import fails, fail the entire operation")
-        self.parser.add_option('-q', '--quiet', action='store_true', dest='quiet', default=False, help="Print no output, still logs output")
-        self.parser.add_option('-i', '--include', action='callback', callback=set_filter_opt, type='str', nargs=1, dest='filters', default=[], help="List of included packages")
-        self.parser.add_option('-e', '--exclude', action='callback', callback=set_filter_opt, type='str', nargs=1, dest='filters', default=[], help="List of excluded packages")
-
-        return self.parser.parse_args()
-
-    def load_plugin(self):
-        name = self.type + "_src"
+    def load_plugin(self, repo_type):
+        name = repo_type + "_src"
         mod = __import__('spacewalk.satellite_tools.repo_plugins', globals(), locals(), [name])
         submod = getattr(mod, name)
         return getattr(submod, "ContentSource")
 
     def import_updates(self, plug, url):
-      notices = plug.get_updates()
-      self.print_msg("Repo " + url + " has " + str(len(notices)) + " errata.")
-      if len(notices) > 0:
-        self.upload_updates(notices)
+        notices = plug.get_updates()
+        self.print_msg("Repo %s has %s errata." % (url, len(notices)))
+        if notices:
+            self.upload_updates(notices)
 
     def upload_updates(self, notices):
         batch = []
@@ -240,7 +211,7 @@ class RepoSync:
                        and at.label = 'rpm'
                        and ch.label = :channel_label
                 """ % (orgStatement, epochStatement))
-                apply(h.execute, (), param_dict)
+                h.execute(**param_dict)
                 cs = h.fetchone_dict() or None
 
                 if not cs:
@@ -358,9 +329,9 @@ class RepoSync:
                     if db_pack['channel_label'] == self.channel_label:
                         # package is already in the channel
                         to_link = False
-		elif db_pack['channel_label'] == self.channel_label:
+                elif db_pack['channel_label'] == self.channel_label:
 		    # different package with SAME NVREA
-		    self.disassociate_package(db_pack)
+                    self.disassociate_package(db_pack)
 
             if to_download or to_link:
                 to_process.append((pack, to_download, to_link))
@@ -376,11 +347,12 @@ class RepoSync:
 
         self.regen=True
         is_non_local_repo = (url.find("file://") < 0)
-        # try/except/finally doesn't work in python 2.4 (RHEL5), so here's a hack
+
         def finally_remove(path):
             if is_non_local_repo and path and os.path.exists(path):
                 os.remove(path)
 
+        # try/except/finally doesn't work in python 2.4 (RHEL5), so here's a hack
         for (index, what) in enumerate(to_process):
             pack, to_download, to_link = what
             localpath = None
@@ -469,22 +441,19 @@ class RepoSync:
 		  checksum_type=pack['checksum_type'], checksum=pack['checksum'])
 
     def _importer_run(self, package, caller, backend):
-            importer = ChannelPackageSubscription(
-                       [IncompletePackage().populate(package)],
-                       backend, caller=caller, repogen=False)
-            importer.run()
-
+        importer = ChannelPackageSubscription(
+            [IncompletePackage().populate(package)],
+            backend, caller=caller, repogen=False)
+        importer.run()
 
     def load_channel(self):
         return rhnChannel.channel_info(self.channel_label)
 
-
     def print_msg(self, message):
         rhnLog.log_clean(0, message)
         if not self.quiet:
             print message
 
-
     def error_msg(self, message):
         rhnLog.log_clean(0, message)
         if not self.quiet:
@@ -499,10 +468,10 @@ class RepoSync:
     def _to_db_date(self, date):
         ret = ""
         if date.isdigit():
-          ret = datetime.fromtimestamp(float(date)).isoformat(' ')
+            ret = datetime.fromtimestamp(float(date)).isoformat(' ')
         else:
-          # we expect to get ISO formated date
-          ret = date
+            # we expect to get ISO formated date
+            ret = date
         return ret
 
     def fix_notice(self, notice):
@@ -614,7 +583,7 @@ class ContentPackage:
 
     def load_checksum_from_header(self):
         if self.path is None:
-           raise rhnFault(50, "Unable to load package", explain=0)
+            raise rhnFault(50, "Unable to load package", explain=0)
         self.file = open(self.path, 'rb')
         self.header, self.payload_stream, self.header_start, self.header_end = \
                 rhnPackageUpload.load_package(self.file)
diff --git a/backend/satellite_tools/spacewalk-repo-sync b/backend/satellite_tools/spacewalk-repo-sync
index ae06a96..69c9568 100755
--- a/backend/satellite_tools/spacewalk-repo-sync
+++ b/backend/satellite_tools/spacewalk-repo-sync
@@ -1,6 +1,7 @@
 #!/usr/bin/python -u
 #
 # Copyright (c) 2008--2011 Red Hat, Inc.
+# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # This software is licensed to you under the GNU General Public License,
 # version 2 (GPLv2). There is NO WARRANTY for this software, express or
@@ -8,30 +9,25 @@
 # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
 # along with this software; if not, see
 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
-# 
+#
 # Red Hat trademarks are not licensed under GPLv2. No permission is
 # granted to use or replicate Red Hat trademarks that are incorporated
-# in this software or its documentation. 
+# in this software or its documentation.
 #
 
-LOCK = None
+import sys
+import os
+import socket
+from optparse import OptionParser
 
-if __name__ != '__main__':
-    raise ImportError, "module cannot be imported"
+LOCK = None
 
-import sys
-def systemExit(code, msgs=None):
+def systemExit(code, msg=None):
     "Exit with a code and optional message(s). Saved a few lines of code."
-    if msgs:
-        if type(msgs) not in [type([]), type(())]:
-            msgs = (msgs, )
-        for msg in msgs:
-            sys.stderr.write(str(msg)+'\n')
+    sys.stderr.write(str(msg)+'\n')
     sys.exit(code)
 
 try:
-    import os
-    import socket
     from rhn import rhnLockfile
     from spacewalk.common.rhnConfig import CFG
     from spacewalk.common.rhnTB import fetchTraceback
@@ -39,8 +35,8 @@ try:
 except KeyboardInterrupt:
     systemExit(0, "\nUser interrupted process.")
 except ImportError:
-    sys.stderr.write("Unable to find RHN code tree.\n"
-                     "Path not correct? '%s'\n" % _LIBPATH)
+    systemExit(1, "Unable to find code tree.\n"
+               "Path not correct? '%s'" % sys.path)
 
 def releaseLOCK():
     global LOCK
@@ -49,22 +45,52 @@ def releaseLOCK():
         LOCK = None
 
 def main():
-
     # quick check to see if you are a super-user.
     if os.getuid() != 0:
         sys.stderr.write('ERROR: must be root to execute\n')
         sys.exit(8)
 
+    global LOCK
     LOCK = None
     try:
         LOCK = rhnLockfile.Lockfile('/var/run/spacewalk-repo-sync.pid')
     except rhnLockfile.LockfileLockedException:
         systemExit(1, "ERROR: attempting to run more than one instance of spacewalk-repo-sync Exiting.")
-    sync = reposync.RepoSync()
-    sync.main()
+
+    parser = OptionParser()
+    parser.add_option('-u', '--url', action='store', dest='url',
+                      help='The url to sync')
+    parser.add_option('-c', '--channel', action='store',
+                      dest='channel_label',
+                      help='The label of the channel to sync packages to')
+    parser.add_option('-t', '--type', action='store', dest='repo_type',
+                      help='The type of repo, currently only "yum" is supported',
+                      default='yum')
+    parser.add_option('-f', '--fail', action='store_true', dest='fail',
+                      default=False ,
+                      help="If a package import fails, fail the entire operation")
+    parser.add_option('-q', '--quiet', action='store_true', dest='quiet',
+                      default=False, help="Print no output, still logs output")
+    parser.add_option('-i', '--include', action='callback', callback=reposync.set_filter_opt,
+                      type='str', nargs=1, dest='filters', default=[], help="List of included packages")
+    parser.add_option('-e', '--exclude', action='callback', callback=reposync.set_filter_opt,
+                      type='str', nargs=1, dest='filters', default=[], help="List of excluded packages")
+    (options, args) = parser.parse_args()
+
+    if not options.channel_label:
+        systemExit(1, "--channel must be specified")
+
+    sync = reposync.RepoSync(channel_label=options.channel_label,
+                             repo_type=options.repo_type,
+                             url=options.url,
+                             fail=options.fail,
+                             quiet=options.quiet,
+                             filters=options.filters)
+    sync.sync()
     releaseLOCK()
     return 0
 
+
 if __name__ == '__main__':
     try:
         sys.exit(abs(main() or 0))
-- 
1.7.3.4

_______________________________________________
Spacewalk-devel mailing list
Spacewalk-devel@redhat.com
https://www.redhat.com/mailman/listinfo/spacewalk-devel

Reply via email to