py3: Make seamless reloads work
Starting with Python 3.4, newly-created file descriptors are non-inheritable [0], which causes trouble when we try to use a pipe for IPC. Fortunately, the same PEP that implemented this change *also* provided a new API to mark file descriptors as being inheritable -- so just do that. While we're at it, * Fix up the probe tests to work on py3 * Fix up the probe tests to work when policy-0 is erasure-coded * Decode the bytes read so py3 doesn't log a b'pid' * Log a warning if the read() is empty; something surely went wrong in the re-exec [0] https://www.python.org/dev/peps/pep-0446/ Change-Id: I2a8a9f3dc78abb99bf9cbcf6b44c32ca644bb07b Related-Change: I3e5229d2fb04be67e53533ff65b0870038accbb7
This commit is contained in:
parent
5fa8ef2c56
commit
8c0fd3f138
@ -1288,6 +1288,9 @@ def run_wsgi(conf_path, app_section, *args, **kwargs):
|
||||
myself = os.path.realpath(sys.argv[0])
|
||||
logger.info("Old server PID=%d re'execing as: %r",
|
||||
orig_server_pid, [myself] + list(sys.argv))
|
||||
if hasattr(os, 'set_inheritable'):
|
||||
# See https://www.python.org/dev/peps/pep-0446/
|
||||
os.set_inheritable(write_fd, True)
|
||||
os.execv(myself, sys.argv)
|
||||
logger.error('Somehow lived past os.execv()?!')
|
||||
exit('Somehow lived past os.execv()?!')
|
||||
@ -1299,12 +1302,19 @@ def run_wsgi(conf_path, app_section, *args, **kwargs):
|
||||
os.getpid(), orig_server_pid)
|
||||
try:
|
||||
got_pid = os.read(read_fd, 30)
|
||||
logger.info('Old server temporary child PID=%d notified '
|
||||
'to shutdown old listen sockets by PID=%s',
|
||||
os.getpid(), got_pid)
|
||||
except Exception as e:
|
||||
logger.warning('Unexpected exception while reading from '
|
||||
'pipe:', exc_info=True)
|
||||
else:
|
||||
got_pid = got_pid.decode('ascii')
|
||||
if got_pid:
|
||||
logger.info('Old server temporary child PID=%d notified '
|
||||
'to shutdown old listen sockets by PID=%s',
|
||||
os.getpid(), got_pid)
|
||||
else:
|
||||
logger.warning('Old server temporary child PID=%d *NOT* '
|
||||
'notified to shutdown old listen sockets; '
|
||||
'the pipe just *died*.', os.getpid())
|
||||
try:
|
||||
os.close(read_fd)
|
||||
except Exception:
|
||||
|
@ -27,7 +27,6 @@ from uuid import uuid4
|
||||
|
||||
from six.moves import http_client as httplib
|
||||
|
||||
from swift.common.storage_policy import POLICIES
|
||||
from swift.common.ring import Ring
|
||||
from swift.common.manager import Manager
|
||||
|
||||
@ -230,9 +229,9 @@ class TestObjectServerReloadBase(TestWSGIServerProcessHandling):
|
||||
PID_TIMEOUT = 35
|
||||
|
||||
def get_ip_port(self):
|
||||
policy = random.choice(list(POLICIES))
|
||||
policy.load_ring('/etc/swift')
|
||||
self.ring_node = random.choice(policy.object_ring.get_part_nodes(1))
|
||||
self.policy.load_ring('/etc/swift')
|
||||
self.ring_node = random.choice(
|
||||
self.policy.object_ring.get_part_nodes(1))
|
||||
return self.ring_node['ip'], self.ring_node['port']
|
||||
|
||||
def start_write_req(self, conn, suffix):
|
||||
@ -240,7 +239,8 @@ class TestObjectServerReloadBase(TestWSGIServerProcessHandling):
|
||||
self.ring_node['device'], self.account, self.container, suffix),
|
||||
headers={'X-Timestamp': str(time.time()),
|
||||
'Content-Type': 'application/octet-string',
|
||||
'Content-Length': len(self.BODY)})
|
||||
'Content-Length': len(self.BODY),
|
||||
'X-Backend-Storage-Policy-Index': str(self.policy.idx)})
|
||||
|
||||
def finish_write_req(self, conn):
|
||||
conn.send(self.BODY)
|
||||
@ -250,12 +250,12 @@ class TestObjectServerReloadBase(TestWSGIServerProcessHandling):
|
||||
got_body = resp.read()
|
||||
self.assertEqual(resp.status // 100, 2, 'Got status %d; %r' %
|
||||
(resp.status, got_body))
|
||||
self.assertEqual('', got_body)
|
||||
self.assertEqual(b'', got_body)
|
||||
return resp
|
||||
|
||||
|
||||
class TestObjectServerReload(OldReloadMixin, TestObjectServerReloadBase):
|
||||
BODY = 'test-object' * 10
|
||||
BODY = b'test-object' * 10
|
||||
|
||||
def test_object_reload(self):
|
||||
self._check_reload()
|
||||
@ -263,7 +263,7 @@ class TestObjectServerReload(OldReloadMixin, TestObjectServerReloadBase):
|
||||
|
||||
class TestObjectServerReloadSeamless(SeamlessReloadMixin,
|
||||
TestObjectServerReloadBase):
|
||||
BODY = 'test-object' * 10
|
||||
BODY = b'test-object' * 10
|
||||
|
||||
def test_object_reload_seamless(self):
|
||||
self._check_reload()
|
||||
@ -331,12 +331,12 @@ class TestProxyServerReloadBase(TestWSGIServerProcessHandling):
|
||||
got_body = resp.read()
|
||||
self.assertEqual(resp.status // 100, 2, 'Got status %d; %r' %
|
||||
(resp.status, got_body))
|
||||
self.assertEqual('', got_body)
|
||||
self.assertEqual(b'', got_body)
|
||||
return resp
|
||||
|
||||
|
||||
class TestProxyServerReload(OldReloadMixin, TestProxyServerReloadBase):
|
||||
BODY = 'proxy' * 10
|
||||
BODY = b'proxy' * 10
|
||||
|
||||
def test_proxy_reload(self):
|
||||
self._check_reload()
|
||||
@ -344,7 +344,7 @@ class TestProxyServerReload(OldReloadMixin, TestProxyServerReloadBase):
|
||||
|
||||
class TestProxyServerReloadSeamless(SeamlessReloadMixin,
|
||||
TestProxyServerReloadBase):
|
||||
BODY = 'proxy-seamless' * 10
|
||||
BODY = b'proxy-seamless' * 10
|
||||
|
||||
def test_proxy_reload_seamless(self):
|
||||
self._check_reload()
|
||||
|
Loading…
x
Reference in New Issue
Block a user