aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Dolbec <dolsen@gentoo.org>2012-11-11 19:29:16 -0800
committerBrian Dolbec <dolsen@gentoo.org>2012-11-11 23:23:09 -0800
commit50e5e2dd9972dd7ac0a4eeb79ef43ab8d4101dd6 (patch)
treecca6ef4363d6e9c264233aa0337ed3186cf0f104 /mirrorselect
parentmove the selector classes to their own file (diff)
downloadmirrorselect-50e5e2dd9972dd7ac0a4eeb79ef43ab8d4101dd6.tar.gz
mirrorselect-50e5e2dd9972dd7ac0a4eeb79ef43ab8d4101dd6.tar.bz2
mirrorselect-50e5e2dd9972dd7ac0a4eeb79ef43ab8d4101dd6.zip
move main's code into a MirrorSelect class, eliminate the global variable 'output'.
Diffstat (limited to 'mirrorselect')
-rwxr-xr-xmirrorselect/main.py523
-rw-r--r--mirrorselect/output.py17
-rw-r--r--mirrorselect/selectors.py97
3 files changed, 323 insertions, 314 deletions
diff --git a/mirrorselect/main.py b/mirrorselect/main.py
index 25c73ae..2f257a6 100755
--- a/mirrorselect/main.py
+++ b/mirrorselect/main.py
@@ -32,273 +32,278 @@ import string
import sys
from optparse import OptionParser
from mirrorselect.mirrorparser3 import MIRRORS_3_XML, MIRRORS_RSYNC_DATA
-from mirrorselect.output import output, ColoredFormatter
+from mirrorselect.output import Output, ColoredFormatter
from mirrorselect.selectors import Deep, Shallow, Extractor, Interactive
-def _have_bin(name):
- """
- Determines whether a particular binary is available on the host system.
- """
- for path_dir in os.environ.get("PATH", "").split(":"):
- if not path_dir:
- continue
- file_path = os.path.join(path_dir, name)
- if os.path.isfile(file_path) and os.access(file_path, os.X_OK):
- return file_path
- return None
-
-
-def write_config(hosts, out, path, sync=False):
- """
- Writes the make.conf style string to the given file, or to stdout.
- """
- if sync:
- var = 'SYNC'
- else:
- var = 'GENTOO_MIRRORS'
-
- mirror_string = '%s="%s"' % (var, ' '.join(hosts))
-
- if out:
- print
- print mirror_string
- sys.exit(0)
+class MirrorSelect(object):
+ '''Main operational class'''
+
+ def __init__(self, output=None):
+ '''Main class init'''
+ self.output = output or Output()
+
+ @staticmethod
+ def _have_bin(name):
+ """
+ Determines whether a particular binary is available on the host system.
+ """
+ for path_dir in os.environ.get("PATH", "").split(":"):
+ if not path_dir:
+ continue
+ file_path = os.path.join(path_dir, name)
+ if os.path.isfile(file_path) and os.access(file_path, os.X_OK):
+ return file_path
+ return None
+
+
+ def write_config(self, hosts, out, path, sync=False):
+ """
+ Writes the make.conf style string to the given file, or to stdout.
+ """
+ if sync:
+ var = 'SYNC'
+ else:
+ var = 'GENTOO_MIRRORS'
+
+ mirror_string = '%s="%s"' % (var, ' '.join(hosts))
+
+ if out:
+ print
+ print mirror_string
+ sys.exit(0)
+
+
+ self.output.write('\n')
+ self.output.print_info('Modifying %s with new mirrors...\n' % path)
+ try:
+ config = open(path, 'r')
+ self.output.write('\tReading make.conf\n')
+ lines = config.readlines()
+ config.close()
+ self.output.write('\tMoving to %s.backup\n' % path)
+ shutil.move(path, path + '.backup')
+ except IOError:
+ lines = []
+
+ regex = re.compile('^%s=.*' % var)
+ for line in lines:
+ if regex.match(line):
+ lines.remove(line)
+
+ lines.append(mirror_string)
+
+ self.output.write('\tWriting new %s\n' % path)
+ config = open(path, 'w')
+ for line in lines:
+ config.write(line)
+ config.write('\n')
+ config.close()
+ self.output.print_info('Done.\n')
+ sys.exit(0)
- output.write('\n')
- output.print_info('Modifying %s with new mirrors...\n' % path)
- try:
- config = open(path, 'r')
- output.write('\tReading make.conf\n')
- lines = config.readlines()
- config.close()
- output.write('\tMoving to %s.backup\n' % path)
- shutil.move(path, path + '.backup')
- except IOError:
- lines = []
-
- regex = re.compile('^%s=.*' % var)
- for line in lines:
- if regex.match(line):
- lines.remove(line)
-
- lines.append(mirror_string)
-
- output.write('\tWriting new %s\n' % path)
- config = open(path, 'w')
- for line in lines:
- config.write(line)
- config.write('\n')
- config.close()
-
- output.print_info('Done.\n')
- sys.exit(0)
-
-def get_filesystem_mirrors(out, path, sync=False):
- """
- Read the current mirrors and retain mounted filesystems mirrors
- """
- fsmirrors = []
-
- if sync:
- var = 'SYNC'
- else:
- var = 'GENTOO_MIRRORS'
-
- try:
- f = open(path,'r')
- except IOError:
- return fsmirrors
+ def get_filesystem_mirrors(self, out, path, sync=False):
+ """
+ Read the current mirrors and retain mounted filesystems mirrors
+ """
+ fsmirrors = []
- """ Search for 'var' in make.conf and extract value """
- try:
- lex = shlex.shlex(f, posix=True)
- lex.wordchars = string.digits+string.letters+"~!@#$%*_\:;?,./-+{}"
- lex.quotes = "\"'"
- while 1:
- key = lex.get_token()
- if key == var:
- equ = lex.get_token()
-
- if (equ == ''):
+ if sync:
+ var = 'SYNC'
+ else:
+ var = 'GENTOO_MIRRORS'
+
+ try:
+ f = open(path,'r')
+ except IOError:
+ return fsmirrors
+
+ """ Search for 'var' in make.conf and extract value """
+ try:
+ lex = shlex.shlex(f, posix=True)
+ lex.wordchars = string.digits+string.letters+"~!@#$%*_\:;?,./-+{}"
+ lex.quotes = "\"'"
+ while 1:
+ key = lex.get_token()
+ if key == var:
+ equ = lex.get_token()
+
+ if (equ == ''):
+ break
+ elif (equ != '='):
+ break
+
+ val = lex.get_token()
+ if val is None:
+ break
+
+ """ Look for mounted filesystem in value """
+ mirrorlist = val.rsplit()
+ p = re.compile('rsync://|http://|ftp://', re.IGNORECASE)
+ for mirror in mirrorlist:
+ if (p.match(mirror) == None):
+ fsmirrors.append(mirror)
break
- elif (equ != '='):
+ elif key is None:
break
+ except Exception:
+ fsmirrors = []
- val = lex.get_token()
- if val is None:
- break
+ return fsmirrors
- """ Look for mounted filesystem in value """
- mirrorlist = val.rsplit()
- p = re.compile('rsync://|http://|ftp://', re.IGNORECASE)
- for mirror in mirrorlist:
- if (p.match(mirror) == None):
- fsmirrors.append(mirror)
- break
- elif key is None:
- break
- except Exception:
- fsmirrors = []
+ def parse_args(self, argv, config_path):
+ """
+ Does argument parsing and some sanity checks.
+ Returns an optparse Options object.
+
+ The descriptions, grouping, and possibly the amount sanity checking
+ need some finishing touches.
+ """
+ desc = "\n".join((
+ self.output.white("examples:"),
+ "",
+ self.output.white(" automatic:"),
+ " # mirrorselect -s5",
+ " # mirrorselect -s3 -b10 -o >> /mnt/gentoo/etc/portage/make.conf",
+ " # mirrorselect -D -s4",
+ "",
+ self.output.white(" interactive:"),
+ " # mirrorselect -i -r",
+ ))
+ parser = OptionParser(
+ formatter=ColoredFormatter(self.output), description=desc,
+ version='Mirrorselect version: %s' % __revision__)
+
+ group = parser.add_option_group("Main modes")
+ group.add_option(
+ "-i", "--interactive", action="store_true", default=False,
+ help="Interactive Mode, this will present a list "
+ "to make it possible to select mirrors you wish to use.")
+ group.add_option(
+ "-D", "--deep", action="store_true", default=False,
+ help="Deep mode. This is used to give a more accurate "
+ "speed test. It will download a 100k file from "
+ "each server. Because of this you should only use "
+ "this option if you have a good connection.")
+
+ group = parser.add_option_group(
+ "Server type selection (choose at most one)")
+ group.add_option(
+ "-F", "--ftp", action="store_true", default=False,
+ help="ftp only mode. Will not consider hosts of other "
+ "types.")
+ group.add_option(
+ "-H", "--http", action="store_true", default=False,
+ help="http only mode. Will not consider hosts of other types")
+ group.add_option(
+ "-r", "--rsync", action="store_true", default=False,
+ help="rsync mode. Allows you to interactively select your"
+ " rsync mirror. Requires -i to be used.")
+ group.add_option(
+ "-4", "--ipv4", action="store_true", default=False,
+ help="only use IPv4")
+ group.add_option(
+ "-6", "--ipv6", action="store_true", default=False,
+ help="only use IPv6")
+
+ group = parser.add_option_group("Other options")
+ group.add_option(
+ "-o", "--output", action="store_true", default=False,
+ help="Output Only Mode, this is especially useful "
+ "when being used during installation, to redirect "
+ "output to a file other than %s" % config_path)
+ group.add_option(
+ "-b", "--blocksize", action="store", type="int",
+ help="This is to be used in automatic mode "
+ "and will split the hosts into blocks of BLOCKSIZE for "
+ "use with netselect. This is required for certain "
+ "routers which block 40+ requests at any given time. "
+ "Recommended parameters to pass are: -s3 -b10")
+ group.add_option(
+ "-t", "--timeout", action="store", type="int",
+ default="10", help="Timeout for deep mode. Defaults to 10 seconds.")
+ group.add_option(
+ "-s", "--servers", action="store", type="int", default=1,
+ help="Specify Number of servers for Automatic Mode "
+ "to select. this is only valid for download mirrors. "
+ "If this is not specified, a default of 1 is used.")
+ group.add_option(
+ "-d", "--debug", action="store_const", const=2, dest="verbosity",
+ default=1, help="debug mode")
+ group.add_option(
+ "-q", "--quiet", action="store_const", const=0, dest="verbosity",
+ help="Quiet mode")
+
+ if len(argv) == 1:
+ parser.print_help()
+ sys.exit(1)
+
+ options, args = parser.parse_args(argv[1:])
+
+ # sanity checks
+
+ # hack: check if more than one of these is set
+ if options.http + options.ftp + options.rsync > 1:
+ self.output.print_err('Choose at most one of -H, -f and -r')
+
+ if options.ipv4 and options.ipv6:
+ self.output.print_err('Choose at most one of --ipv4 and --ipv6')
+
+ if (options.ipv6 and not socket.has_ipv6) and not options.interactive:
+ options.ipv6 = False
+ self.output.print_err('The --ipv6 option requires python ipv6 support')
+
+ if options.rsync and not options.interactive:
+ self.output.print_err('rsync servers can only be selected with -i')
+
+ if options.interactive and (
+ options.deep or
+ options.blocksize or
+ options.servers > 1):
+ self.output.print_err('Invalid option combination with -i')
+
+ if (not options.deep) and (not self._have_bin('netselect') ):
+ self.output.print_err(
+ 'You do not appear to have netselect on your system. '
+ 'You must use the -D flag')
+
+ if (os.getuid() != 0) and not options.output:
+ self.output.print_err('Must be root to write to %s!\n' % config_path)
+
+ if args:
+ self.output.print_err('Unexpected arguments passed.')
+
+ # return results
+ return options
+
+
+ def main(self, argv):
+ """Lets Rock!"""
+ # start with the new location
+ config_path = '/etc/portage/make.conf'
+ if not os.access(config_path, os.F_OK):
+ # check if the old location is what is used
+ if os.access('/etc/make.conf', os.F_OK):
+ config_path = '/etc/make.conf'
+
+ #self.output.print_info("config_path set to :", config_path)
+
+ options = self.parse_args(argv, config_path)
+ self.output.verbosity = options.verbosity
+
+ fsmirrors = self.get_filesystem_mirrors(options.output, config_path, options.rsync)
+ if options.rsync:
+ hosts = Extractor(MIRRORS_RSYNC_DATA, options, self.output).hosts
+ else:
+ hosts = Extractor(MIRRORS_3_XML, options, self.output).hosts
+
+ if options.interactive:
+ selector = Interactive(hosts, options, self.output)
+ elif options.deep:
+ selector = Deep(hosts, options, self.output)
+ else:
+ selector = Shallow(hosts, options, self.output)
+
+ self.write_config(fsmirrors + selector.urls, options.output, config_path, options.rsync)
- return fsmirrors
-
-def parse_args(argv, config_path):
- """
- Does argument parsing and some sanity checks.
- Returns an optparse Options object.
-
- The descriptions, grouping, and possibly the amount sanity checking
- need some finishing touches.
- """
- desc = "\n".join((
- output.white("examples:"),
- "",
- output.white(" automatic:"),
- " # mirrorselect -s5",
- " # mirrorselect -s3 -b10 -o >> /mnt/gentoo/etc/portage/make.conf",
- " # mirrorselect -D -s4",
- "",
- output.white(" interactive:"),
- " # mirrorselect -i -r",
- ))
- parser = OptionParser(
- formatter=ColoredFormatter(), description=desc,
- version='Mirrorselect version: %s' % __revision__)
-
- group = parser.add_option_group("Main modes")
- group.add_option(
- "-i", "--interactive", action="store_true", default=False,
- help="Interactive Mode, this will present a list "
- "to make it possible to select mirrors you wish to use.")
- group.add_option(
- "-D", "--deep", action="store_true", default=False,
- help="Deep mode. This is used to give a more accurate "
- "speed test. It will download a 100k file from "
- "each server. Because of this you should only use "
- "this option if you have a good connection.")
-
- group = parser.add_option_group(
- "Server type selection (choose at most one)")
- group.add_option(
- "-F", "--ftp", action="store_true", default=False,
- help="ftp only mode. Will not consider hosts of other "
- "types.")
- group.add_option(
- "-H", "--http", action="store_true", default=False,
- help="http only mode. Will not consider hosts of other types")
- group.add_option(
- "-r", "--rsync", action="store_true", default=False,
- help="rsync mode. Allows you to interactively select your"
- " rsync mirror. Requires -i to be used.")
- group.add_option(
- "-4", "--ipv4", action="store_true", default=False,
- help="only use IPv4")
- group.add_option(
- "-6", "--ipv6", action="store_true", default=False,
- help="only use IPv6")
-
- group = parser.add_option_group("Other options")
- group.add_option(
- "-o", "--output", action="store_true", default=False,
- help="Output Only Mode, this is especially useful "
- "when being used during installation, to redirect "
- "output to a file other than %s" % config_path)
- group.add_option(
- "-b", "--blocksize", action="store", type="int",
- help="This is to be used in automatic mode "
- "and will split the hosts into blocks of BLOCKSIZE for "
- "use with netselect. This is required for certain "
- "routers which block 40+ requests at any given time. "
- "Recommended parameters to pass are: -s3 -b10")
- group.add_option(
- "-t", "--timeout", action="store", type="int",
- default="10", help="Timeout for deep mode. Defaults to 10 seconds.")
- group.add_option(
- "-s", "--servers", action="store", type="int", default=1,
- help="Specify Number of servers for Automatic Mode "
- "to select. this is only valid for download mirrors. "
- "If this is not specified, a default of 1 is used.")
- group.add_option(
- "-d", "--debug", action="store_const", const=2, dest="verbosity",
- default=1, help="debug mode")
- group.add_option(
- "-q", "--quiet", action="store_const", const=0, dest="verbosity",
- help="Quiet mode")
-
- if len(argv) == 1:
- parser.print_help()
- sys.exit(1)
-
- options, args = parser.parse_args(argv[1:])
-
- # sanity checks
-
- # hack: check if more than one of these is set
- if options.http + options.ftp + options.rsync > 1:
- output.print_err('Choose at most one of -H, -f and -r')
-
- if options.ipv4 and options.ipv6:
- output.print_err('Choose at most one of --ipv4 and --ipv6')
-
- if (options.ipv6 and not socket.has_ipv6) and not options.interactive:
- options.ipv6 = False
- output.print_err('The --ipv6 option requires python ipv6 support')
-
- if options.rsync and not options.interactive:
- output.print_err('rsync servers can only be selected with -i')
-
- if options.interactive and (
- options.deep or
- options.blocksize or
- options.servers > 1):
- output.print_err('Invalid option combination with -i')
-
- if (not options.deep) and (not _have_bin('netselect') ):
- output.print_err(
- 'You do not appear to have netselect on your system. '
- 'You must use the -D flag')
-
- if (os.getuid() != 0) and not options.output:
- output.print_err('Must be root to write to %s!\n' % config_path)
-
- if args:
- output.print_err('Unexpected arguments passed.')
-
- # return results
- return options
-
-
-def main(argv):
- """Lets Rock!"""
- # start with the new location
- config_path = '/etc/portage/make.conf'
- if not os.access(config_path, os.F_OK):
- # check if the old location is what is used
- if os.access('/etc/make.conf', os.F_OK):
- config_path = '/etc/make.conf'
-
- #output.print_info("config_path set to :", config_path)
-
- options = parse_args(argv, config_path)
- output.verbosity = options.verbosity
-
- fsmirrors = get_filesystem_mirrors(options.output, config_path, options.rsync)
- if options.rsync:
- hosts = Extractor(MIRRORS_RSYNC_DATA, options).hosts
- else:
- hosts = Extractor(MIRRORS_3_XML, options).hosts
-
- if options.interactive:
- selector = Interactive(hosts, options)
- elif options.deep:
- selector = Deep(hosts, options)
- else:
- selector = Shallow(hosts, options)
-
- write_config(fsmirrors + selector.urls, options.output, config_path, options.rsync)
-
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/mirrorselect/output.py b/mirrorselect/output.py
index b00226a..a9d49bb 100644
--- a/mirrorselect/output.py
+++ b/mirrorselect/output.py
@@ -27,7 +27,6 @@ Distributed under the terms of the GNU General Public License v2
"""
-from __future__ import print_function
import sys
import re
@@ -106,9 +105,12 @@ class ColoredFormatter(IndentedHelpFormatter):
Overrides format_heading.
"""
+ def __init__(self, output):
+ self.output = output
+
def format_heading(self, heading):
"""Return a colorful heading."""
- return "%*s%s:\n" % (self.current_indent, "", output.white(heading))
+ return "%*s%s:\n" % (self.current_indent, "", self.output.white(heading))
def format_option(self, option):
"""Return colorful formatted help for an option."""
@@ -116,17 +118,18 @@ class ColoredFormatter(IndentedHelpFormatter):
# long options with args
option = re.sub(
r"--([a-zA-Z]*)=([a-zA-Z]*)",
- lambda m: "-%s %s" % (output.green(m.group(1)),
- output.blue(m.group(2))),
+ lambda m: "-%s %s" % (self.output.green(m.group(1)),
+ self.output.blue(m.group(2))),
option)
# short options with args
option = re.sub(
r"-([a-zA-Z]) ?([0-9A-Z]+)",
- lambda m: " -" + output.green(m.group(1)) + ' ' + output.blue(m.group(2)),
+ lambda m: " -" + self.output.green(m.group(1)) + ' ' + \
+ self.output.blue(m.group(2)),
option)
# options without args
option = re.sub(
- r"-([a-zA-Z\d]+)", lambda m: "-" + output.green(m.group(1)),
+ r"-([a-zA-Z\d]+)", lambda m: "-" + self.output.green(m.group(1)),
option)
return option
@@ -134,5 +137,3 @@ class ColoredFormatter(IndentedHelpFormatter):
"""Do not wrap."""
return description + '\n'
-
-output = Output() #the only FUCKING global. Damnit.
diff --git a/mirrorselect/selectors.py b/mirrorselect/selectors.py
index d2e7e63..9593848 100644
--- a/mirrorselect/selectors.py
+++ b/mirrorselect/selectors.py
@@ -38,7 +38,6 @@ import urllib
import urlparse
import hashlib
from mirrorselect.mirrorparser3 import MirrorParser3
-from mirrorselect.output import output
import codecs
@@ -48,12 +47,13 @@ class Extractor(object):
mirrors, and then filters them. Only the mirrors that should be tested, based on
user input are saved. They will be in the hosts attribute."""
- def __init__(self, list_url, options):
+ def __init__(self, list_url, options, output):
+ self.output = output
parser = MirrorParser3()
self.hosts = []
hosts = self.getlist(parser, list_url)
- output.write('Extractor(): fetched mirrors.xml,'
+ self.output.write('Extractor(): fetched mirrors.xml,'
' %s hosts before filtering\n' % len(hosts), 2)
if not options.rsync:
@@ -71,13 +71,13 @@ class Extractor(object):
"""
myhosts = []
- output.print_info('Limiting test to %s hosts. ' % prot )
+ self.output.print_info('Limiting test to %s hosts. ' % prot )
for host in hosts:
if host[0].startswith(prot):
myhosts.append(host)
- output.write('%s of %s removed.\n' % (len(hosts) - len(myhosts),
+ self.output.write('%s of %s removed.\n' % (len(hosts) - len(myhosts),
len(hosts)) )
return myhosts
@@ -89,9 +89,9 @@ class Extractor(object):
Takes a parser object, url, and filering options.
"""
- output.write('getlist(): fetching ' + url + '\n', 2)
+ self.output.write('getlist(): fetching ' + url + '\n', 2)
- output.print_info('Downloading a list of mirrors...')
+ self.output.print_info('Downloading a list of mirrors...')
try:
parser.parse(urllib.urlopen(url).read())
@@ -99,10 +99,10 @@ class Extractor(object):
pass
if len(parser.tuples()) == 0:
- output.print_err('Could not get mirror list. Check your internet'
+ self.output.print_err('Could not get mirror list. Check your internet'
' connection.')
- output.write(' Got %d mirrors.\n' % len(parser.tuples()))
+ self.output.write(' Got %d mirrors.\n' % len(parser.tuples()))
return parser.tuples()
@@ -110,7 +110,8 @@ class Extractor(object):
class Shallow(object):
"""handles rapid server selection via netselect"""
- def __init__(self, hosts, options):
+ def __init__(self, hosts, options, output):
+ self.output = output
self.urls = []
if options.blocksize is not None:
@@ -120,7 +121,7 @@ class Shallow(object):
self.netselect(hosts, options.servers)
if len(self.urls) == 0:
- output.print_err('Netselect failed to return any mirrors.'
+ self.output.print_err('Netselect failed to return any mirrors.'
' Try again using block mode.')
@@ -134,12 +135,12 @@ class Shallow(object):
top_hosts = []
if not quiet:
- output.print_info('Using netselect to choose the top %d mirrors...' \
+ self.output.print_info('Using netselect to choose the top %d mirrors...' \
% number)
host_string = ' '.join(hosts)
- output.write('\nnetselect(): running "netselect -s%d %s"\n' % (int(number),
+ self.output.write('\nnetselect(): running "netselect -s%d %s"\n' % (int(number),
host_string), 2)
proc = subprocess.Popen( ['netselect', '-s%d' % (number,)] + hosts,
@@ -148,7 +149,7 @@ class Shallow(object):
out, err = proc.communicate()
if err:
- output.write('netselect(): netselect stderr: %s\n' % err, 2)
+ self.output.write('netselect(): netselect stderr: %s\n' % err, 2)
for line in out.splitlines():
line = line.split()
@@ -158,9 +159,9 @@ class Shallow(object):
top_host_dict[line[0]] = line[1]
if not quiet:
- output.write('Done.\n')
+ self.output.write('Done.\n')
- output.write('\nnetselect(): returning %s and %s\n' % (top_hosts,
+ self.output.write('\nnetselect(): returning %s and %s\n' % (top_hosts,
top_host_dict), 2)
if quiet:
@@ -176,24 +177,24 @@ class Shallow(object):
"""
hosts = [host[0] for host in hosts]
- output.write('netselect_split() got %s hosts.\n' % len(hosts), 2)
+ self.output.write('netselect_split() got %s hosts.\n' % len(hosts), 2)
host_blocks = self.host_blocks(hosts, block_size)
- output.write(' split into %s blocks\n' % len(host_blocks), 2)
+ self.output.write(' split into %s blocks\n' % len(host_blocks), 2)
top_hosts = []
ret_hosts = {}
block_index = 0
for block in host_blocks:
- output.print_info('Using netselect to choose the top '
+ self.output.print_info('Using netselect to choose the top '
'%d hosts, in blocks of %s. %s of %s blocks complete.'
% (number, block_size, block_index, len(host_blocks)))
host_dict = self.netselect(block, len(block), quiet=True)[1]
- output.write('ran netselect(%s, %s), and got %s\n' % (block, len(block),
+ self.output.write('ran netselect(%s, %s), and got %s\n' % (block, len(block),
host_dict), 2)
for key in host_dict.keys():
@@ -210,7 +211,7 @@ class Shallow(object):
for rank in host_ranking_keys[:number]:
top_hosts.append(ret_hosts[rank])
- output.write('netselect_split(): returns %s\n' % top_hosts, 2)
+ self.output.write('netselect_split(): returns %s\n' % top_hosts, 2)
self.urls = top_hosts
@@ -230,7 +231,7 @@ class Shallow(object):
mylist = []
host_array.append(hosts)
- output.write('\n_host_blocks(): returns %s blocks, each about %s in size\n'
+ self.output.write('\n_host_blocks(): returns %s blocks, each about %s in size\n'
% (len(host_array), len(host_array[0])), 2)
return host_array
@@ -239,7 +240,8 @@ class Shallow(object):
class Deep(object):
"""handles deep mode mirror selection."""
- def __init__(self, hosts, options):
+ def __init__(self, hosts, options, output):
+ self.output = output
self.urls = []
self._hosts = hosts
self._number = options.servers
@@ -276,7 +278,7 @@ class Deep(object):
for host in hosts:
prog += 1
- output.print_info('Downloading 100k files from each mirror... [%s of %s]'\
+ self.output.print_info('Downloading 100k files from each mirror... [%s of %s]'\
% (prog, num_hosts) )
mytime, ignore = self.deeptime(host, maxtime)
@@ -287,10 +289,10 @@ class Deep(object):
else:
continue
- output.write('deeptest(): got %s hosts, and returned %s\n' % (num_hosts, \
+ self.output.write('deeptest(): got %s hosts, and returned %s\n' % (num_hosts, \
str(top_hosts.values())), 2)
- output.write('\n') #this just makes output nicer
+ self.output.write('\n') #this just makes output nicer
#can't just return the dict.valuse, because we want the fastest mirror first...
keys = top_hosts.keys()
@@ -309,7 +311,7 @@ class Deep(object):
Can be given an optional timeout, for use with a clever algorithm.
Like mine.
"""
- output.write('\n_deeptime(): maxtime is %s\n' % maxtime, 2)
+ self.output.write('\n_deeptime(): maxtime is %s\n' % maxtime, 2)
if url.endswith('/'): #append the path to the testfile to the URL
url = url + 'distfiles/mirrorselect-test'
@@ -342,14 +344,14 @@ class Deep(object):
finally:
signal.alarm(0)
except socket.error, e:
- output.write('deeptime(): dns error for host %s: %s\n' % \
+ self.output.write('deeptime(): dns error for host %s: %s\n' % \
(url_parts.hostname, e), 2)
except TimeoutException:
- output.write('deeptime(): dns timeout for host %s\n' % \
+ self.output.write('deeptime(): dns timeout for host %s\n' % \
(url_parts.hostname,), 2)
if not ips:
- output.write('deeptime(): unable to resolve ip for host %s\n' % \
+ self.output.write('deeptime(): unable to resolve ip for host %s\n' % \
(url_parts.hostname,), 2)
return (None, True)
@@ -365,16 +367,16 @@ class Deep(object):
finally:
signal.alarm(0)
except EnvironmentError, e:
- output.write(('deeptime(): connection to host %s ' + \
+ self.output.write(('deeptime(): connection to host %s ' + \
'failed for ip %s: %s\n') % \
(url_parts.hostname, ip, e), 2)
except TimeoutException:
- output.write(('deeptime(): connection to host %s ' + \
+ self.output.write(('deeptime(): connection to host %s ' + \
'timed out for ip %s\n') % \
(url_parts.hostname, ip), 2)
if f is None:
- output.write('deeptime(): unable to ' + \
+ self.output.write('deeptime(): unable to ' + \
'connect to host %s\n' % \
(url_parts.hostname,), 2)
return (None, True)
@@ -387,11 +389,11 @@ class Deep(object):
finally:
signal.alarm(0)
except EnvironmentError, e:
- output.write(('deeptime(): close connection to host %s ' + \
+ self.output.write(('deeptime(): close connection to host %s ' + \
'failed for ip %s: %s\n') % \
(url_parts.hostname, ip, e), 2)
except TimeoutException:
- output.write(('deeptime(): close connection to host %s ' + \
+ self.output.write(('deeptime(): close connection to host %s ' + \
'timed out for ip %s\n') % \
(url_parts.hostname, ip), 2)
@@ -413,20 +415,20 @@ class Deep(object):
signal.alarm(0)
except EnvironmentError, e:
- output.write(('deeptime(): download from host %s ' + \
+ self.output.write(('deeptime(): download from host %s ' + \
'failed for ip %s: %s\n') % \
(url_parts.hostname, ip, e), 2)
return (None, True)
except TimeoutException:
- output.write(('deeptime(): download from host %s ' + \
+ self.output.write(('deeptime(): download from host %s ' + \
'timed out for ip %s\n') % \
(url_parts.hostname, ip), 2)
return (None, True)
signal.signal(signal.SIGALRM, signal.SIG_DFL)
- output.write('deeptime(): download completed.\n', 2)
- output.write('deeptime(): %s seconds for host %s\n' % (delta, url), 2)
+ self.output.write('deeptime(): download completed.\n', 2)
+ self.output.write('deeptime(): %s seconds for host %s\n' % (delta, url), 2)
return (delta, False)
def _list_add(self, time_host, maxtime, host_dict, maxlen):
@@ -438,7 +440,7 @@ class Deep(object):
"""
if len(host_dict) < maxlen: #still have room, and host is fast. add it.
- output.write('_list_add(): added host %s. with a time of %s\n' %
+ self.output.write('_list_add(): added host %s. with a time of %s\n' %
(time_host[1], time_host[0]), 2)
host_dict.update(dict([time_host]))
@@ -446,11 +448,11 @@ class Deep(object):
times.sort()
else: #We need to make room in the dict before we add. Kill the slowest.
- output.write('_list_add(): Adding host %s with a time of %s\n' %
+ self.output.write('_list_add(): Adding host %s with a time of %s\n' %
(time_host[1], time_host[0]), 2)
times = host_dict.keys()
times.sort()
- output.write('_list_add(): removing %s\n' % host_dict[times[-1]],
+ self.output.write('_list_add(): removing %s\n' % host_dict[times[-1]],
2)
del host_dict[times[-1]]
host_dict.update(dict([time_host]))
@@ -459,18 +461,18 @@ class Deep(object):
times.sort()
if len(host_dict) < maxlen: #check again to choose new timeout
- output.write('_list_add(): host_dict is not full yet.'
+ self.output.write('_list_add(): host_dict is not full yet.'
' reusing timeout of %s sec.\n' % maxtime, 2)
retval = maxtime
else:
- output.write('_list_add(): host_dict is full. Selecting the best'
+ self.output.write('_list_add(): host_dict is full. Selecting the best'
' timeout\n', 2)
if times[-1] < maxtime:
retval = times[-1]
else:
retval = maxtime
- output.write('_list_add(): new max time is %s seconds,'
+ self.output.write('_list_add(): new max time is %s seconds,'
' and now len(host_dict)= %s\n' % (retval, len(host_dict)), 2)
return retval, host_dict
@@ -479,11 +481,12 @@ class Deep(object):
class Interactive(object):
"""Handles interactive host selection."""
- def __init__(self, hosts, options):
+ def __init__(self, hosts, options, output):
+ self.output = output
self.urls = []
self.interactive(hosts, options)
- output.write('Interactive.interactive(): self.urls = %s\n' % self.urls, 2)
+ self.output.write('Interactive.interactive(): self.urls = %s\n' % self.urls, 2)
if len(self.urls[0]) == 0:
sys.exit(1)