From f00e9de4926c9c408a5ff8b6597db6a5d849a270 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 24 Dec 2017 04:12:02 +0100 Subject: [PATCH 1/2] refactor/move hostname/fqdn related funcs, see #3471 - move stuff to platform.base (should be platform independent according to the docs). - bump platform API version - parseformat: import fqdn from platform instead of recomputing it This is not yet fixing #3471, just a preparation for it. (cherry picked from commit 5e4df7782bc7b5b789431c10c1390b6233951113) --- src/borg/helpers.py | 4 ++-- src/borg/platform/__init__.py | 4 ++-- src/borg/platform/base.py | 21 +++++++++++++++++---- src/borg/platform/darwin.pyx | 2 +- src/borg/platform/freebsd.pyx | 2 +- src/borg/platform/linux.pyx | 2 +- src/borg/platform/posix.pyx | 23 ++--------------------- 7 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/borg/helpers.py b/src/borg/helpers.py index f880e4ce7..f758ffb89 100644 --- a/src/borg/helpers.py +++ b/src/borg/helpers.py @@ -139,7 +139,7 @@ def check_extension_modules(): raise ExtensionModuleError if borg.crypto.low_level.API_VERSION != '1.1_02': raise ExtensionModuleError - if platform.API_VERSION != platform.OS_API_VERSION != '1.1_02': + if platform.API_VERSION != platform.OS_API_VERSION != '1.1_03': raise ExtensionModuleError if item.API_VERSION != '1.1_02': raise ExtensionModuleError @@ -664,8 +664,8 @@ def format_line(format, data): def replace_placeholders(text): """Replace placeholders in text with their values.""" + from .platform import fqdn current_time = datetime.now() - fqdn = socket.getfqdn() data = { 'pid': os.getpid(), 'fqdn': fqdn, diff --git a/src/borg/platform/__init__.py b/src/borg/platform/__init__.py index 171590b74..9bf79672c 100644 --- a/src/borg/platform/__init__.py +++ b/src/borg/platform/__init__.py @@ -10,12 +10,12 @@ from .base import acl_get, acl_set from .base import set_flags, get_flags from .base import SaveFile, SyncFile, sync_dir, fdatasync, safe_fadvise from .base import swidth, API_VERSION -from .base import process_alive, get_process_id, local_pid_alive +from .base import process_alive, get_process_id, local_pid_alive, fqdn, hostname, hostid OS_API_VERSION = API_VERSION if not sys.platform.startswith(('win32', )): - from .posix import process_alive, get_process_id, local_pid_alive + from .posix import process_alive, local_pid_alive if sys.platform.startswith('linux'): # pragma: linux only from .linux import API_VERSION as OS_API_VERSION diff --git a/src/borg/platform/base.py b/src/borg/platform/base.py index f56c03be4..638572b29 100644 --- a/src/borg/platform/base.py +++ b/src/borg/platform/base.py @@ -1,5 +1,7 @@ import errno import os +import socket +import uuid from borg.helpers import truncate_and_unlink @@ -15,7 +17,7 @@ platform API: that way platform APIs provided by the platform-specific support m are correctly composed into the base functionality. """ -API_VERSION = '1.1_02' +API_VERSION = '1.1_03' fdatasync = getattr(os, 'fdatasync', os.fsync) @@ -183,12 +185,23 @@ def swidth(s): return len(s) +# for performance reasons, only determine hostname / fqdn / hostid once. +# XXX this sometimes requires live internet access for issuing a DNS query in the background. +hostname = socket.gethostname() +fqdn = socket.getfqdn() +hostid = '%s@%s' % (fqdn, uuid.getnode()) + + def get_process_id(): """ - Return identification tuple (hostname, pid, thread_id) for 'us'. If this is a FUSE process, then the PID will be - that of the parent, not the forked FUSE child. + Return identification tuple (hostname, pid, thread_id) for 'us'. + This always returns the current pid, which might be different from before, e.g. if daemonize() was used. + + Note: Currently thread_id is *always* zero. """ - raise NotImplementedError + thread_id = 0 + pid = os.getpid() + return hostid, pid, thread_id def process_alive(host, pid, thread): diff --git a/src/borg/platform/darwin.pyx b/src/borg/platform/darwin.pyx index b7e439ab6..eac6ddc9f 100644 --- a/src/borg/platform/darwin.pyx +++ b/src/borg/platform/darwin.pyx @@ -4,7 +4,7 @@ from ..helpers import user2uid, group2gid from ..helpers import safe_decode, safe_encode from .posix import swidth -API_VERSION = '1.1_02' +API_VERSION = '1.1_03' cdef extern from "sys/acl.h": ctypedef struct _acl_t: diff --git a/src/borg/platform/freebsd.pyx b/src/borg/platform/freebsd.pyx index 3344de165..33bcccdb9 100644 --- a/src/borg/platform/freebsd.pyx +++ b/src/borg/platform/freebsd.pyx @@ -4,7 +4,7 @@ from ..helpers import posix_acl_use_stored_uid_gid from ..helpers import safe_encode, safe_decode from .posix import swidth -API_VERSION = '1.1_02' +API_VERSION = '1.1_03' cdef extern from "errno.h": int errno diff --git a/src/borg/platform/linux.pyx b/src/borg/platform/linux.pyx index 25f71fa18..000fa8fdd 100644 --- a/src/borg/platform/linux.pyx +++ b/src/borg/platform/linux.pyx @@ -13,7 +13,7 @@ from .posix import swidth from libc cimport errno from libc.stdint cimport int64_t -API_VERSION = '1.1_02' +API_VERSION = '1.1_03' cdef extern from "sys/types.h": int ACL_TYPE_ACCESS diff --git a/src/borg/platform/posix.pyx b/src/borg/platform/posix.pyx index 0144e1aa3..fe2039f83 100644 --- a/src/borg/platform/posix.pyx +++ b/src/borg/platform/posix.pyx @@ -1,8 +1,5 @@ import errno import os -import uuid -import socket -import subprocess cdef extern from "wchar.h": @@ -18,23 +15,6 @@ def swidth(s): return str_len -# for performance reasons, only determine the hostname once. -# XXX this sometimes requires live internet access for issuing a DNS query in the background. -_hostname = '%s@%s' % (socket.getfqdn(), uuid.getnode()) - - -def get_process_id(): - """ - Return identification tuple (hostname, pid, thread_id) for 'us'. - This always returns the current pid, which might be different from before, e.g. if daemonize() was used. - - Note: Currently thread_id is *always* zero. - """ - thread_id = 0 - pid = os.getpid() - return _hostname, pid, thread_id - - def process_alive(host, pid, thread): """ Check if the (host, pid, thread_id) combination corresponds to a potentially alive process. @@ -43,8 +23,9 @@ def process_alive(host, pid, thread): returns always True, since there is no real way to check. """ from . import local_pid_alive + from . import hostid - if host != _hostname: + if host != hostid: return True if thread != 0: From d11c9e9b157f55c8ff9a6647c35e07014d2cd523 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 24 Dec 2017 04:46:20 +0100 Subject: [PATCH 2/2] use patched version of socket.getfqdn(), fixes #3471 (cherry picked from commit 9b0d0f3127289fc3bbe620e8adce8038ed594e9f) --- src/borg/platform/base.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/borg/platform/base.py b/src/borg/platform/base.py index 638572b29..3e6e60d3e 100644 --- a/src/borg/platform/base.py +++ b/src/borg/platform/base.py @@ -185,10 +185,31 @@ def swidth(s): return len(s) +# patched socket.getfqdn() - see https://bugs.python.org/issue5004 +def getfqdn(name=''): + """Get fully qualified domain name from name. + + An empty argument is interpreted as meaning the local host. + """ + name = name.strip() + if not name or name == '0.0.0.0': + name = socket.gethostname() + try: + addrs = socket.getaddrinfo(name, None, 0, socket.SOCK_DGRAM, 0, socket.AI_CANONNAME) + except socket.error: + pass + else: + for addr in addrs: + if addr[3]: + name = addr[3] + break + return name + + # for performance reasons, only determine hostname / fqdn / hostid once. # XXX this sometimes requires live internet access for issuing a DNS query in the background. hostname = socket.gethostname() -fqdn = socket.getfqdn() +fqdn = getfqdn(hostname) hostid = '%s@%s' % (fqdn, uuid.getnode())