From ca00d7eea61103bf6a3706e997d75a66b85e33ab Mon Sep 17 00:00:00 2001
From: Roland Ernst <rcrernst@gmail.com>
Date: Thu, 5 Mar 2020 21:29:00 +0100
Subject: [PATCH] BackendServerAddr and MasterServerName replaced
MasterServerIP
in V30, according ticket #13024.
Replace any occurences of the deprecated settings and allow
'BackendServerAddr(MasterServerName)' to be an alias for the
host-ip as well.
Fixes #13593
---
mythtv/bindings/python/MythTV/database.py | 12 +---
mythtv/bindings/python/MythTV/methodheap.py | 42 ++++++++------
mythtv/bindings/python/MythTV/mythproto.py | 55 ++++++++++---------
.../python/MythTV/utility/__init__.py | 3 +-
.../bindings/python/MythTV/utility/other.py | 9 +++
5 files changed, 66 insertions(+), 55 deletions(-)
diff --git a/mythtv/bindings/python/MythTV/database.py b/mythtv/bindings/python/MythTV/database.py
index 7e3c4fe42b..e8b8bf5d52 100644
a
|
b
|
class DBCache( MythSchema ): |
1338 | 1338 | |
1339 | 1339 | def _gethostfromaddr(self, addr, value=None): |
1340 | 1340 | if value is None: |
1341 | | for value in ['BackendServerAddr']: |
1342 | | try: |
1343 | | return self._gethostfromaddr(addr, value) |
1344 | | except MythDBError: |
1345 | | pass |
1346 | | else: |
1347 | | raise MythDBError(MythError.DB_SETTING, |
1348 | | 'BackendServerAddr', addr) |
1349 | | |
| 1341 | value = 'BackendServerAddr' |
1350 | 1342 | with self as cursor: |
1351 | 1343 | if cursor.execute("""SELECT hostname FROM settings |
1352 | 1344 | WHERE value=? AND data=?""", [value, addr]) == 0: |
… |
… |
class DBCache( MythSchema ): |
1360 | 1352 | return self.dbconfig.profile |
1361 | 1353 | |
1362 | 1354 | def getMasterBackend(self): |
1363 | | return self._gethostfromaddr(self.settings.NULL.MasterServerIP) |
| 1355 | return self.settings.NULL.MasterServerName |
1364 | 1356 | |
1365 | 1357 | def getStorageGroup(self, groupname=None, hostname=None): |
1366 | 1358 | """ |
diff --git a/mythtv/bindings/python/MythTV/methodheap.py b/mythtv/bindings/python/MythTV/methodheap.py
index 04c7e98bb4..3e9b181b28 100644
a
|
b
|
from MythTV.static import * |
8 | 8 | from MythTV.exceptions import * |
9 | 9 | from MythTV.logging import MythLog |
10 | 10 | from MythTV.connections import FEConnection, XMLConnection, BEEventConnection |
11 | | from MythTV.utility import databaseSearch, datetime, check_ipv6, _donothing |
| 11 | from MythTV.utility import databaseSearch, datetime, check_ipv6, _donothing, resolve_ip |
12 | 12 | from MythTV.database import DBCache, DBData |
13 | 13 | from MythTV.system import SystemEvent |
14 | 14 | from MythTV.mythproto import BECache, FileOps, Program, FreeSpace, EventLock |
… |
… |
class MythVideo( MythDB ): |
1131 | 1131 | class MythXML( XMLConnection ): |
1132 | 1132 | """ |
1133 | 1133 | Provides convenient methods to access the backend XML server. |
| 1134 | Parameter 'backend' is either a hostname from 'settings', |
| 1135 | an ip address or a hostname in ip-notation. |
1134 | 1136 | """ |
1135 | 1137 | def __init__(self, backend=None, port=None, db=None): |
1136 | 1138 | if backend and port: |
… |
… |
class MythXML( XMLConnection ): |
1142 | 1144 | self.log = MythLog('Python XML Connection') |
1143 | 1145 | if backend is None: |
1144 | 1146 | # use master backend |
1145 | | backend = self.db.settings.NULL.MasterServerIP |
1146 | | if re.match(r'(?:\d{1,3}\.){3}\d{1,3}',backend) or \ |
1147 | | check_ipv6(backend): |
1148 | | # process ip address |
1149 | | host = self.db._gethostfromaddr(backend) |
1150 | | self.host = backend |
1151 | | self.port = int(self.db.settings[host].BackendStatusPort) |
| 1147 | backend = self.db.getMasterBackend() |
| 1148 | |
| 1149 | # assume hostname from settings |
| 1150 | host = self.db._getpreferredaddr(backend) |
| 1151 | if host: |
| 1152 | port = int(self.db.settings[backend].BackendStatusPort) |
1152 | 1153 | else: |
1153 | | # assume given a hostname |
1154 | | self.host = backend |
1155 | | self.port = int(self.db.settings[self.host].BackendStatusPort) |
1156 | | if not self.port: |
1157 | | # try a truncated hostname |
1158 | | self.host = backend.split('.')[0] |
1159 | | self.port = int(self.db.setting[self.host].BackendStatusPort) |
1160 | | if not self.port: |
1161 | | raise MythDBError(MythError.DB_SETTING, |
1162 | | backend+': BackendStatusPort') |
| 1154 | # assume ip address |
| 1155 | hostname = self.db._gethostfromaddr(backend) |
| 1156 | host = backend |
| 1157 | port = int(self.db.settings[hostname].BackendStatusPort) |
| 1158 | |
| 1159 | # resolve ip address from name |
| 1160 | reshost, resport = resolve_ip(host,port) |
| 1161 | if not reshost: |
| 1162 | raise MythDBError(MythError.DB_SETTING, |
| 1163 | backend+': BackendServerAddr') |
| 1164 | if not resport: |
| 1165 | raise MythDBError(MythError.DB_SETTING, |
| 1166 | backend+': BackendStatusPort') |
| 1167 | self.host = host |
| 1168 | self.port = port |
1163 | 1169 | |
1164 | 1170 | def getHosts(self): |
1165 | 1171 | """Returns a list of unique hostnames found in the settings table.""" |
diff --git a/mythtv/bindings/python/MythTV/mythproto.py b/mythtv/bindings/python/MythTV/mythproto.py
index b388e9619f..6b00ba222c 100644
a
|
b
|
from MythTV.altdict import DictData |
12 | 12 | from MythTV.connections import BEConnection, BEEventConnection |
13 | 13 | from MythTV.database import DBCache |
14 | 14 | from MythTV.utility import CMPRecord, datetime, ParseEnum, \ |
15 | | CopyData, CopyData2, check_ipv6, py23_repr |
| 15 | CopyData, CopyData2, check_ipv6, py23_repr, resolve_ip |
16 | 16 | |
17 | 17 | from datetime import date |
18 | 18 | from time import sleep |
… |
… |
class BECache( object ): |
75 | 75 | self.receiveevents = events |
76 | 76 | |
77 | 77 | if backend is None: |
78 | | # no backend given, use master |
79 | | self.host = self.db.settings.NULL.MasterServerIP |
80 | | self.hostname = self.db._gethostfromaddr(self.host) |
81 | | |
| 78 | # use master backend |
| 79 | backend = self.db.getMasterBackend() |
82 | 80 | else: |
83 | 81 | backend = backend.strip('[]') |
84 | | if self._reip.match(backend): |
85 | | # given backend is IP address |
86 | | self.host = backend |
87 | | self.hostname = self.db._gethostfromaddr( |
88 | | backend, 'BackendServerAddr') |
89 | | elif check_ipv6(backend): |
90 | | # given backend is IPv6 address |
91 | | self.host = backend |
92 | | self.hostname = self.db._gethostfromaddr( |
93 | | backend, 'BackendServerAddr') |
94 | | else: |
95 | | # given backend is hostname, pull address from database |
96 | | self.hostname = backend |
97 | | self.host = self.db._getpreferredaddr(backend) |
98 | 82 | |
99 | | # lookup port from database |
100 | | self.port = int(self.db.settings[self.hostname].BackendServerPort) |
101 | | if not self.port: |
102 | | raise MythDBError(MythError.DB_SETTING, 'BackendServerPort', |
103 | | self.port) |
| 83 | # assume backend is hostname from settings |
| 84 | host = self.db._getpreferredaddr(backend) |
| 85 | if host: |
| 86 | port = int(self.db.settings[backend].BackendServerPort) |
| 87 | self.hostname = backend |
| 88 | else: |
| 89 | # assume ip address |
| 90 | self.hostname = self.db._gethostfromaddr(backend) |
| 91 | host = backend |
| 92 | port = int(self.db.settings[self.hostname].BackendServerPort) |
| 93 | |
| 94 | # resolve ip address from name |
| 95 | reshost, resport = resolve_ip(host,port) |
| 96 | if not reshost: |
| 97 | raise MythDBError(MythError.DB_SETTING, |
| 98 | backend+': BackendServerAddr') |
| 99 | if not resport: |
| 100 | raise MythDBError(MythError.DB_SETTING, |
| 101 | backend+': BackendServerPort') |
| 102 | |
| 103 | self.host = host |
| 104 | self.port = port |
104 | 105 | |
105 | 106 | self._ident = '%s:%d' % (self.host, self.port) |
106 | 107 | if self._ident in self._shared: |
… |
… |
def ftopen(file, mode, forceremote=False, nooverwrite=False, db=None, \ |
241 | 242 | else: |
242 | 243 | raise MythError('Invalid FileTransfer input string: '+file) |
243 | 244 | |
244 | | # get full system name |
| 245 | # prefer hostname from settings over IP address |
245 | 246 | host = host.strip('[]') |
246 | | if reip.match(host) or check_ipv6(host): |
| 247 | if ( not db._getpreferredaddr(host) and \ |
| 248 | resolve_ip(host, None)[0] ): |
| 249 | # host is either IPv4, IPv6 or an (aliased) name |
247 | 250 | host = db._gethostfromaddr(host) |
248 | 251 | |
249 | 252 | # select the correct transfer function: |
diff --git a/mythtv/bindings/python/MythTV/utility/__init__.py b/mythtv/bindings/python/MythTV/utility/__init__.py
index 4f8d060a23..1ca7087d7b 100644
a
|
b
|
from .altdict import OrdDict, DictInvert, DictInvertCI |
7 | 7 | |
8 | 8 | from .other import _donothing, SchemaUpdate, databaseSearch, deadlinesocket, \ |
9 | 9 | MARKUPLIST, levenshtein, ParseEnum, ParseSet, CopyData, \ |
10 | | CopyData2, check_ipv6, QuickProperty, py23_str, py23_repr |
| 10 | CopyData2, check_ipv6, QuickProperty, py23_str, py23_repr, \ |
| 11 | resolve_ip |
11 | 12 | |
diff --git a/mythtv/bindings/python/MythTV/utility/other.py b/mythtv/bindings/python/MythTV/utility/other.py
index bb8f29630d..7f5b0c759c 100644
a
|
b
|
def check_ipv6(n): |
576 | 576 | except socket.error: |
577 | 577 | return False |
578 | 578 | |
| 579 | def resolve_ip(host, port): |
| 580 | try: |
| 581 | res = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM)[0] |
| 582 | # (family, socktype, proto, canonname, sockaddr) |
| 583 | af, socktype, proto, canonname, sa = res |
| 584 | return(sa[0], sa[1]) |
| 585 | except: |
| 586 | return (None, None) |
| 587 | |
579 | 588 | def py23_str(value, ignore_errors=False): |
580 | 589 | error_methods = ('strict', 'ignore') |
581 | 590 | error_method = error_methods[ignore_errors] |