Bug #339642 - Use AF_UNSPEC for --sync addresses.
authorZac Medico <zmedico@gentoo.org>
Mon, 4 Oct 2010 19:29:09 +0000 (12:29 -0700)
committerZac Medico <zmedico@gentoo.org>
Wed, 6 Oct 2010 22:57:32 +0000 (15:57 -0700)
pym/_emerge/actions.py

index 4f167d573222e6f90e6151175205988e35489984..18a3a9298e1a248fdb5a8f35ecc8deb7d2670b1b 100644 (file)
@@ -11,6 +11,7 @@ import errno
 import logging
 import platform
 import pwd
+import random
 import re
 import shutil
 import signal
@@ -2077,45 +2078,49 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                extra_rsync_opts = portage.util.shlex_split(
                        settings.get("PORTAGE_RSYNC_EXTRA_OPTS",""))
                all_rsync_opts.update(extra_rsync_opts)
-               family = socket.AF_INET
-               if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
-                       family = socket.AF_INET
-               elif socket.has_ipv6 and \
-                       ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
-                       family = socket.AF_INET6
-               ips=[]
+
+               ips_v4 = []
+               ips_v6 = []
+
+               try:
+                       addrinfos = socket.getaddrinfo(hostname, None,
+                               socket.AF_UNSPEC, socket.SOCK_STREAM)
+               except socket.error as e:
+                       writemsg("!!! getaddrinfo failed: %s\n" % (e,), noiselevel=-1)
+                       return 1
+
+               for addrinfo in addrinfos:
+                       if socket.has_ipv6 and addrinfo[0] == socket.AF_INET6:
+                               # IPv6 addresses need to be enclosed in square brackets
+                               ips_v6.append("[%s]" % addrinfo[4][0])
+                       else:
+                               ips_v4.append(addrinfo[4][0])
+
+               random.shuffle(ips_v4)
+               random.shuffle(ips_v6)
+
+               # Give priority to the address family that
+               # getaddrinfo() returned first.
+               if socket.has_ipv6 and addrinfos and \
+                       addrinfos[0][0] == socket.AF_INET6:
+                       ips = ips_v6 + ips_v4
+               else:
+                       ips = ips_v4 + ips_v6
+
+               # reverse, for use with pop()
+               ips.reverse()
+
                SERVER_OUT_OF_DATE = -1
                EXCEEDED_MAX_RETRIES = -2
                while (1):
                        if ips:
-                               del ips[0]
-                       if ips==[]:
-                               try:
-                                       for addrinfo in socket.getaddrinfo(
-                                               hostname, None, family, socket.SOCK_STREAM):
-                                               if socket.has_ipv6 and addrinfo[0] == socket.AF_INET6:
-                                                       # IPv6 addresses need to be enclosed in square brackets
-                                                       ips.append("[%s]" % addrinfo[4][0])
-                                               else:
-                                                       ips.append(addrinfo[4][0])
-                                       from random import shuffle
-                                       shuffle(ips)
-                               except SystemExit as e:
-                                       raise # Needed else can't exit
-                               except Exception as e:
-                                       print("Notice:",str(e))
-                                       dosyncuri=syncuri
-
-                       if ips:
-                               try:
-                                       dosyncuri = syncuri.replace(
-                                               "//" + user_name + hostname + port + "/",
-                                               "//" + user_name + ips[0] + port + "/", 1)
-                               except SystemExit as e:
-                                       raise # Needed else can't exit
-                               except Exception as e:
-                                       print("Notice:",str(e))
-                                       dosyncuri=syncuri
+                               dosyncuri = syncuri.replace(
+                                       "//" + user_name + hostname + port + "/",
+                                       "//" + user_name + ips.pop() + port + "/", 1)
+                       else:
+                               writemsg("!!! Exhausted addresses for %s\n" % \
+                                       hostname, noiselevel=-1)
+                               return 1
 
                        if (retries==0):
                                if "--ask" in myopts: