 d54083771f
			
		
	
	d54083771f
	
	
	
		
			
			Change-Id: I9a1ebec645ced755aece8e28452f51488c2b776c Related-Change: I09143ae20bd6249083c0b80cdaa9d561e6abb301
		
			
				
	
	
		
			2410 lines
		
	
	
		
			99 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			2410 lines
		
	
	
		
			99 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright (c) 2010-2012 OpenStack Foundation
 | |
| #
 | |
| # Licensed under the Apache License, Version 2.0 (the "License");
 | |
| # you may not use this file except in compliance with the License.
 | |
| # You may obtain a copy of the License at
 | |
| #
 | |
| #    http://www.apache.org/licenses/LICENSE-2.0
 | |
| #
 | |
| # Unless required by applicable law or agreed to in writing, software
 | |
| # distributed under the License is distributed on an "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | |
| # implied.
 | |
| # See the License for the specific language governing permissions and
 | |
| # limitations under the License.
 | |
| from __future__ import print_function
 | |
| 
 | |
| import unittest
 | |
| from test.unit import temptree
 | |
| 
 | |
| import mock
 | |
| import os
 | |
| import sys
 | |
| import resource
 | |
| import signal
 | |
| import errno
 | |
| from collections import defaultdict
 | |
| from time import sleep, time
 | |
| import tempfile
 | |
| 
 | |
| from six.moves import reload_module
 | |
| 
 | |
| from swift.common import manager
 | |
| from swift.common.exceptions import InvalidPidFileException
 | |
| 
 | |
| import eventlet
 | |
| threading = eventlet.patcher.original('threading')
 | |
| 
 | |
| DUMMY_SIG = 1
 | |
| 
 | |
| 
 | |
| class MockOs(object):
 | |
|     RAISE_EPERM_SIG = 99
 | |
| 
 | |
|     def __init__(self, pids):
 | |
|         self.running_pids = pids
 | |
|         self.pid_sigs = defaultdict(list)
 | |
|         self.closed_fds = []
 | |
|         self.child_pid = 9999  # fork defaults to test parent process path
 | |
|         self.execlp_called = False
 | |
| 
 | |
|     def kill(self, pid, sig):
 | |
|         if sig == self.RAISE_EPERM_SIG:
 | |
|             raise OSError(errno.EPERM, 'Operation not permitted')
 | |
|         if pid not in self.running_pids:
 | |
|             raise OSError(3, 'No such process')
 | |
|         self.pid_sigs[pid].append(sig)
 | |
| 
 | |
|     def __getattr__(self, name):
 | |
|         # I only over-ride portions of the os module
 | |
|         try:
 | |
|             return object.__getattr__(self, name)
 | |
|         except AttributeError:
 | |
|             return getattr(os, name)
 | |
| 
 | |
| 
 | |
| def pop_stream(f):
 | |
|     """read everything out of file from the top and clear it out
 | |
|     """
 | |
|     f.flush()
 | |
|     f.seek(0)
 | |
|     output = f.read()
 | |
|     f.seek(0)
 | |
|     f.truncate()
 | |
|     return output
 | |
| 
 | |
| 
 | |
| class TestManagerModule(unittest.TestCase):
 | |
| 
 | |
|     def test_servers(self):
 | |
|         main_plus_rest = set(manager.MAIN_SERVERS + manager.REST_SERVERS)
 | |
|         self.assertEqual(set(manager.ALL_SERVERS), main_plus_rest)
 | |
|         # make sure there's no server listed in both
 | |
|         self.assertEqual(len(main_plus_rest), len(manager.MAIN_SERVERS) +
 | |
|                          len(manager.REST_SERVERS))
 | |
| 
 | |
|     def test_setup_env(self):
 | |
|         class MockResource(object):
 | |
|             def __init__(self, error=None):
 | |
|                 self.error = error
 | |
|                 self.called_with_args = []
 | |
| 
 | |
|             def setrlimit(self, resource, limits):
 | |
|                 if self.error:
 | |
|                     raise self.error
 | |
|                 self.called_with_args.append((resource, limits))
 | |
| 
 | |
|             def __getattr__(self, name):
 | |
|                 # I only over-ride portions of the resource module
 | |
|                 try:
 | |
|                     return object.__getattr__(self, name)
 | |
|                 except AttributeError:
 | |
|                     return getattr(resource, name)
 | |
| 
 | |
|         _orig_resource = manager.resource
 | |
|         _orig_environ = os.environ
 | |
|         try:
 | |
|             manager.resource = MockResource()
 | |
|             manager.os.environ = {}
 | |
|             manager.setup_env()
 | |
|             expected = [
 | |
|                 (resource.RLIMIT_NOFILE, (manager.MAX_DESCRIPTORS,
 | |
|                                           manager.MAX_DESCRIPTORS)),
 | |
|                 (resource.RLIMIT_DATA, (manager.MAX_MEMORY,
 | |
|                                         manager.MAX_MEMORY)),
 | |
|                 (resource.RLIMIT_NPROC, (manager.MAX_PROCS,
 | |
|                                          manager.MAX_PROCS)),
 | |
|             ]
 | |
|             self.assertEqual(manager.resource.called_with_args, expected)
 | |
|             self.assertTrue(
 | |
|                 manager.os.environ['PYTHON_EGG_CACHE'].startswith(
 | |
|                     tempfile.gettempdir()))
 | |
| 
 | |
|             # test error condition
 | |
|             manager.resource = MockResource(error=ValueError())
 | |
|             manager.os.environ = {}
 | |
|             manager.setup_env()
 | |
|             self.assertEqual(manager.resource.called_with_args, [])
 | |
|             self.assertTrue(
 | |
|                 manager.os.environ['PYTHON_EGG_CACHE'].startswith(
 | |
|                     tempfile.gettempdir()))
 | |
| 
 | |
|             manager.resource = MockResource(error=OSError())
 | |
|             manager.os.environ = {}
 | |
|             self.assertRaises(OSError, manager.setup_env)
 | |
|             self.assertIsNone(manager.os.environ.get('PYTHON_EGG_CACHE'))
 | |
|         finally:
 | |
|             manager.resource = _orig_resource
 | |
|             os.environ = _orig_environ
 | |
| 
 | |
|     def test_command_wrapper(self):
 | |
| 
 | |
|         class MockManager(object):
 | |
|             def __init__(self, servers_):
 | |
|                 self.servers = [manager.Server(server) for server in servers_]
 | |
| 
 | |
|             @manager.command
 | |
|             def myfunc(self, arg1):
 | |
|                 """test doc
 | |
|                 """
 | |
|                 return arg1
 | |
| 
 | |
|         m = MockManager(['test'])
 | |
|         self.assertEqual(m.myfunc.__doc__.strip(), 'test doc')
 | |
|         self.assertEqual(m.myfunc(1), 1)
 | |
|         self.assertEqual(m.myfunc(0), 0)
 | |
|         self.assertEqual(m.myfunc(True), 1)
 | |
|         self.assertEqual(m.myfunc(False), 0)
 | |
|         self.assertTrue(hasattr(m.myfunc, 'publicly_accessible'))
 | |
|         self.assertTrue(m.myfunc.publicly_accessible)
 | |
| 
 | |
|     def test_watch_server_pids(self):
 | |
|         class MockOs(object):
 | |
|             WNOHANG = os.WNOHANG
 | |
| 
 | |
|             def __init__(self, pid_map=None):
 | |
|                 if pid_map is None:
 | |
|                     pid_map = {}
 | |
|                 self.pid_map = {}
 | |
|                 for pid, v in pid_map.items():
 | |
|                     self.pid_map[pid] = (x for x in v)
 | |
| 
 | |
|             def waitpid(self, pid, options):
 | |
|                 try:
 | |
|                     rv = next(self.pid_map[pid])
 | |
|                 except StopIteration:
 | |
|                     raise OSError(errno.ECHILD, os.strerror(errno.ECHILD))
 | |
|                 except KeyError:
 | |
|                     raise OSError(errno.ESRCH, os.strerror(errno.ESRCH))
 | |
|                 if isinstance(rv, Exception):
 | |
|                     raise rv
 | |
|                 else:
 | |
|                     return rv
 | |
| 
 | |
|         class MockTime(object):
 | |
|             def __init__(self, ticks=None):
 | |
|                 self.tock = time()
 | |
|                 if not ticks:
 | |
|                     ticks = []
 | |
| 
 | |
|                 self.ticks = (t for t in ticks)
 | |
| 
 | |
|             def time(self):
 | |
|                 try:
 | |
|                     self.tock += next(self.ticks)
 | |
|                 except StopIteration:
 | |
|                     self.tock += 1
 | |
|                 return self.tock
 | |
| 
 | |
|             def sleep(*args):
 | |
|                 return
 | |
| 
 | |
|         class MockServer(object):
 | |
| 
 | |
|             def __init__(self, pids, run_dir=manager.RUN_DIR, zombie=0):
 | |
|                 self.heartbeat = (pids for _ in range(zombie))
 | |
| 
 | |
|             def get_running_pids(self):
 | |
|                 try:
 | |
|                     rv = next(self.heartbeat)
 | |
|                     return rv
 | |
|                 except StopIteration:
 | |
|                     return {}
 | |
| 
 | |
|         _orig_os = manager.os
 | |
|         _orig_time = manager.time
 | |
|         _orig_server = manager.Server
 | |
|         try:
 | |
|             manager.time = MockTime()
 | |
|             manager.os = MockOs()
 | |
|             # this server always says it's dead when you ask for running pids
 | |
|             server = MockServer([1])
 | |
|             # list of pids keyed on servers to watch
 | |
|             server_pids = {
 | |
|                 server: [1],
 | |
|             }
 | |
|             # basic test, server dies
 | |
|             gen = manager.watch_server_pids(server_pids)
 | |
|             expected = [(server, 1)]
 | |
|             self.assertEqual([x for x in gen], expected)
 | |
|             # start long running server and short interval
 | |
|             server = MockServer([1], zombie=15)
 | |
|             server_pids = {
 | |
|                 server: [1],
 | |
|             }
 | |
|             gen = manager.watch_server_pids(server_pids)
 | |
|             self.assertEqual([x for x in gen], [])
 | |
|             # wait a little longer
 | |
|             gen = manager.watch_server_pids(server_pids, interval=15)
 | |
|             self.assertEqual([x for x in gen], [(server, 1)])
 | |
|             # zombie process
 | |
|             server = MockServer([1], zombie=200)
 | |
|             server_pids = {
 | |
|                 server: [1],
 | |
|             }
 | |
|             # test weird os error
 | |
|             manager.os = MockOs({1: [OSError()]})
 | |
|             gen = manager.watch_server_pids(server_pids)
 | |
|             self.assertRaises(OSError, lambda: [x for x in gen])
 | |
|             # test multi-server
 | |
|             server1 = MockServer([1, 10], zombie=200)
 | |
|             server2 = MockServer([2, 20], zombie=8)
 | |
|             server_pids = {
 | |
|                 server1: [1, 10],
 | |
|                 server2: [2, 20],
 | |
|             }
 | |
|             pid_map = {
 | |
|                 1: [None for _ in range(10)],
 | |
|                 2: [None for _ in range(8)],
 | |
|                 20: [None for _ in range(4)],
 | |
|             }
 | |
|             manager.os = MockOs(pid_map)
 | |
|             gen = manager.watch_server_pids(server_pids,
 | |
|                                             interval=manager.KILL_WAIT)
 | |
|             expected = [
 | |
|                 (server2, 2),
 | |
|                 (server2, 20),
 | |
|             ]
 | |
|             self.assertEqual([x for x in gen], expected)
 | |
| 
 | |
|         finally:
 | |
|             manager.os = _orig_os
 | |
|             manager.time = _orig_time
 | |
|             manager.Server = _orig_server
 | |
| 
 | |
|     def test_safe_kill(self):
 | |
|         manager.os = MockOs([1, 2, 3, 4])
 | |
| 
 | |
|         proc_files = (
 | |
|             ('1/cmdline', 'same-procname'),
 | |
|             ('2/cmdline', 'another-procname'),
 | |
|             ('4/cmdline', 'another-procname'),
 | |
|         )
 | |
|         files, contents = zip(*proc_files)
 | |
|         with temptree(files, contents) as t:
 | |
|             manager.PROC_DIR = t
 | |
|             manager.safe_kill(1, signal.SIG_DFL, 'same-procname')
 | |
|             self.assertRaises(InvalidPidFileException, manager.safe_kill,
 | |
|                               2, signal.SIG_DFL, 'same-procname')
 | |
|             manager.safe_kill(3, signal.SIG_DFL, 'same-procname')
 | |
|             manager.safe_kill(4, signal.SIGHUP, 'same-procname')
 | |
| 
 | |
|     def test_exc(self):
 | |
|         self.assertTrue(issubclass(manager.UnknownCommandError, Exception))
 | |
| 
 | |
|     def test_format_server_name(self):
 | |
|         self.assertEqual(
 | |
|             manager.format_server_name('proxy'),
 | |
|             ("proxy-server", "swift-proxy-server"))
 | |
|         self.assertEqual(
 | |
|             manager.format_server_name('Proxy'),
 | |
|             ("Proxy-server", "swift-Proxy-server"))
 | |
|         self.assertEqual(
 | |
|             manager.format_server_name(''),
 | |
|             ("-server", "swift--server"))
 | |
| 
 | |
|     def test_verify_server(self):
 | |
|         def mock_find_exe(f):
 | |
|             # pretend that swift-object-server is the only file on path
 | |
|             return f if f == 'swift-object-server' else None
 | |
| 
 | |
|         with mock.patch('swift.common.manager.find_executable',
 | |
|                         side_effect=mock_find_exe):
 | |
|             # test valid servers
 | |
|             self.assertTrue(manager.verify_server('object'))
 | |
|             self.assertTrue(manager.verify_server('object-server'))
 | |
|             self.assertTrue(manager.verify_server('object.replication'))
 | |
|             self.assertTrue(manager.verify_server('object-server.1'))
 | |
|             # test invalid servers
 | |
|             self.assertFalse(manager.verify_server('test'))
 | |
|             self.assertFalse(manager.verify_server('test-server'))
 | |
|             self.assertFalse(manager.verify_server('ls'))
 | |
|             self.assertFalse(manager.verify_server(''))
 | |
|             self.assertFalse(manager.verify_server('Object'))
 | |
|             self.assertFalse(manager.verify_server('object1'))
 | |
|             self.assertFalse(manager.verify_server(None))
 | |
| 
 | |
| 
 | |
| class TestServer(unittest.TestCase):
 | |
| 
 | |
|     def tearDown(self):
 | |
|         reload_module(manager)
 | |
| 
 | |
|     def join_swift_dir(self, path):
 | |
|         return os.path.join(manager.SWIFT_DIR, path)
 | |
| 
 | |
|     def join_run_dir(self, path):
 | |
|         return os.path.join(manager.RUN_DIR, path)
 | |
| 
 | |
|     def test_create_server(self):
 | |
|         server = manager.Server('proxy')
 | |
|         self.assertEqual(server.server, 'proxy-server')
 | |
|         self.assertEqual(server.type, 'proxy')
 | |
|         self.assertEqual(server.cmd, 'swift-proxy-server')
 | |
|         server = manager.Server('object-replicator')
 | |
|         self.assertEqual(server.server, 'object-replicator')
 | |
|         self.assertEqual(server.type, 'object')
 | |
|         self.assertEqual(server.cmd, 'swift-object-replicator')
 | |
| 
 | |
|     def test_server_to_string(self):
 | |
|         server = manager.Server('Proxy')
 | |
|         self.assertEqual(str(server), 'proxy-server')
 | |
|         server = manager.Server('object-replicator')
 | |
|         self.assertEqual(str(server), 'object-replicator')
 | |
| 
 | |
|     def test_server_repr(self):
 | |
|         server = manager.Server('proxy')
 | |
|         self.assertTrue(server.__class__.__name__ in repr(server))
 | |
|         self.assertTrue(str(server) in repr(server))
 | |
| 
 | |
|     def test_server_equality(self):
 | |
|         server1 = manager.Server('Proxy')
 | |
|         server2 = manager.Server('proxy-server')
 | |
|         self.assertEqual(server1, server2)
 | |
|         # it is NOT a string
 | |
|         self.assertNotEqual(server1, 'proxy-server')
 | |
| 
 | |
|     def test_get_pid_file_name(self):
 | |
|         server = manager.Server('proxy')
 | |
|         conf_file = self.join_swift_dir('proxy-server.conf')
 | |
|         pid_file = self.join_run_dir('proxy-server.pid')
 | |
|         self.assertEqual(pid_file, server.get_pid_file_name(conf_file))
 | |
|         server = manager.Server('object-replicator')
 | |
|         conf_file = self.join_swift_dir('object-server/1.conf')
 | |
|         pid_file = self.join_run_dir('object-replicator/1.pid')
 | |
|         self.assertEqual(pid_file, server.get_pid_file_name(conf_file))
 | |
|         server = manager.Server('container-auditor')
 | |
|         conf_file = self.join_swift_dir(
 | |
|             'container-server/1/container-auditor.conf')
 | |
|         pid_file = self.join_run_dir(
 | |
|             'container-auditor/1/container-auditor.pid')
 | |
|         self.assertEqual(pid_file, server.get_pid_file_name(conf_file))
 | |
| 
 | |
|     def test_get_custom_pid_file_name(self):
 | |
|         random_run_dir = "/random/dir"
 | |
|         get_random_run_dir = lambda x: os.path.join(random_run_dir, x)
 | |
|         server = manager.Server('proxy', run_dir=random_run_dir)
 | |
|         conf_file = self.join_swift_dir('proxy-server.conf')
 | |
|         pid_file = get_random_run_dir('proxy-server.pid')
 | |
|         self.assertEqual(pid_file, server.get_pid_file_name(conf_file))
 | |
|         server = manager.Server('object-replicator', run_dir=random_run_dir)
 | |
|         conf_file = self.join_swift_dir('object-server/1.conf')
 | |
|         pid_file = get_random_run_dir('object-replicator/1.pid')
 | |
|         self.assertEqual(pid_file, server.get_pid_file_name(conf_file))
 | |
|         server = manager.Server('container-auditor', run_dir=random_run_dir)
 | |
|         conf_file = self.join_swift_dir(
 | |
|             'container-server/1/container-auditor.conf')
 | |
|         pid_file = get_random_run_dir(
 | |
|             'container-auditor/1/container-auditor.pid')
 | |
|         self.assertEqual(pid_file, server.get_pid_file_name(conf_file))
 | |
| 
 | |
|     def test_get_conf_file_name(self):
 | |
|         server = manager.Server('proxy')
 | |
|         conf_file = self.join_swift_dir('proxy-server.conf')
 | |
|         pid_file = self.join_run_dir('proxy-server.pid')
 | |
|         self.assertEqual(conf_file, server.get_conf_file_name(pid_file))
 | |
|         server = manager.Server('object-replicator')
 | |
|         conf_file = self.join_swift_dir('object-server/1.conf')
 | |
|         pid_file = self.join_run_dir('object-replicator/1.pid')
 | |
|         self.assertEqual(conf_file, server.get_conf_file_name(pid_file))
 | |
|         server = manager.Server('container-auditor')
 | |
|         conf_file = self.join_swift_dir(
 | |
|             'container-server/1/container-auditor.conf')
 | |
|         pid_file = self.join_run_dir(
 | |
|             'container-auditor/1/container-auditor.pid')
 | |
|         self.assertEqual(conf_file, server.get_conf_file_name(pid_file))
 | |
|         server_name = manager.STANDALONE_SERVERS[0]
 | |
|         server = manager.Server(server_name)
 | |
|         conf_file = self.join_swift_dir(server_name + '.conf')
 | |
|         pid_file = self.join_run_dir(server_name + '.pid')
 | |
|         self.assertEqual(conf_file, server.get_conf_file_name(pid_file))
 | |
| 
 | |
|     def test_conf_files(self):
 | |
|         # test get single conf file
 | |
|         conf_files = (
 | |
|             'proxy-server.conf',
 | |
|             'proxy-server.ini',
 | |
|             'auth-server.conf',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             server = manager.Server('proxy')
 | |
|             conf_files = server.conf_files()
 | |
|             self.assertEqual(len(conf_files), 1)
 | |
|             conf_file = conf_files[0]
 | |
|             proxy_conf = self.join_swift_dir('proxy-server.conf')
 | |
|             self.assertEqual(conf_file, proxy_conf)
 | |
| 
 | |
|         # test multi server conf files & grouping of server-type config
 | |
|         conf_files = (
 | |
|             'object-server1.conf',
 | |
|             'object-server/2.conf',
 | |
|             'object-server/object3.conf',
 | |
|             'object-server/conf/server4.conf',
 | |
|             'object-server.txt',
 | |
|             'proxy-server.conf',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             server = manager.Server('object-replicator')
 | |
|             conf_files = server.conf_files()
 | |
|             self.assertEqual(len(conf_files), 4)
 | |
|             c1 = self.join_swift_dir('object-server1.conf')
 | |
|             c2 = self.join_swift_dir('object-server/2.conf')
 | |
|             c3 = self.join_swift_dir('object-server/object3.conf')
 | |
|             c4 = self.join_swift_dir('object-server/conf/server4.conf')
 | |
|             for c in [c1, c2, c3, c4]:
 | |
|                 self.assertTrue(c in conf_files)
 | |
|             # test configs returned sorted
 | |
|             sorted_confs = sorted([c1, c2, c3, c4])
 | |
|             self.assertEqual(conf_files, sorted_confs)
 | |
| 
 | |
|         # test get single numbered conf
 | |
|         conf_files = (
 | |
|             'account-server/1.conf',
 | |
|             'account-server/2.conf',
 | |
|             'account-server/3.conf',
 | |
|             'account-server/4.conf',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             server = manager.Server('account')
 | |
|             conf_files = server.conf_files(number=2)
 | |
|             self.assertEqual(len(conf_files), 1)
 | |
|             conf_file = conf_files[0]
 | |
|             self.assertEqual(conf_file,
 | |
|                              self.join_swift_dir('account-server/2.conf'))
 | |
|             # test missing config number
 | |
|             conf_files = server.conf_files(number=5)
 | |
|             self.assertFalse(conf_files)
 | |
| 
 | |
|         # test getting specific conf
 | |
|         conf_files = (
 | |
|             'account-server/1.conf',
 | |
|             'account-server/2.conf',
 | |
|             'account-server/3.conf',
 | |
|             'account-server/4.conf',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             server = manager.Server('account.2')
 | |
|             conf_files = server.conf_files()
 | |
|             self.assertEqual(len(conf_files), 1)
 | |
|             conf_file = conf_files[0]
 | |
|             self.assertEqual(conf_file,
 | |
|                              self.join_swift_dir('account-server/2.conf'))
 | |
| 
 | |
|         # test verbose & quiet
 | |
|         conf_files = (
 | |
|             'auth-server.ini',
 | |
|             'container-server/1.conf',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             old_stdout = sys.stdout
 | |
|             try:
 | |
|                 with open(os.path.join(t, 'output'), 'w+') as f:
 | |
|                     sys.stdout = f
 | |
|                     server = manager.Server('auth')
 | |
|                     # check warn "unable to locate"
 | |
|                     conf_files = server.conf_files()
 | |
|                     self.assertFalse(conf_files)
 | |
|                     self.assertTrue('unable to locate config for auth'
 | |
|                                     in pop_stream(f).lower())
 | |
|                     # check quiet will silence warning
 | |
|                     conf_files = server.conf_files(verbose=True, quiet=True)
 | |
|                     self.assertEqual(pop_stream(f), '')
 | |
|                     # check found config no warning
 | |
|                     server = manager.Server('container-auditor')
 | |
|                     conf_files = server.conf_files()
 | |
|                     self.assertEqual(pop_stream(f), '')
 | |
|                     # check missing config number warn "unable to locate"
 | |
|                     conf_files = server.conf_files(number=2)
 | |
|                     self.assertTrue(
 | |
|                         'unable to locate config number 2 for ' +
 | |
|                         'container-auditor' in pop_stream(f).lower())
 | |
|                     # check verbose lists configs
 | |
|                     conf_files = server.conf_files(number=2, verbose=True)
 | |
|                     c1 = self.join_swift_dir('container-server/1.conf')
 | |
|                     self.assertIn(c1, pop_stream(f))
 | |
|             finally:
 | |
|                 sys.stdout = old_stdout
 | |
| 
 | |
|         # test standalone conf file
 | |
|         server_name = manager.STANDALONE_SERVERS[0]
 | |
|         conf_files = (server_name + '.conf',)
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             server = manager.Server(server_name)
 | |
|             conf_files = server.conf_files()
 | |
|             self.assertEqual(len(conf_files), 1)
 | |
|             conf_file = conf_files[0]
 | |
|             conf = self.join_swift_dir(server_name + '.conf')
 | |
|             self.assertEqual(conf_file, conf)
 | |
| 
 | |
|     def _test_expirer_conf_files(self, files_and_contents, expected_files):
 | |
|         files, contents = zip(*files_and_contents)
 | |
|         with temptree(files, contents) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             expected_files = [self.join_swift_dir(f) for f in expected_files]
 | |
| 
 | |
|             def assert_results(quiet, verbose):
 | |
|                 original_stdout = sys.stdout
 | |
|                 try:
 | |
|                     with open(os.path.join(t, 'output'), 'w+') as stdout:
 | |
|                         sys.stdout = stdout
 | |
|                         server = manager.Server('object-expirer')
 | |
|                         conf_files = server.conf_files(verbose=verbose,
 | |
|                                                        quiet=quiet)
 | |
|                         messages = pop_stream(stdout)
 | |
|                 finally:
 | |
|                     sys.stdout = original_stdout
 | |
| 
 | |
|                 self.assertEqual(conf_files, expected_files)
 | |
| 
 | |
|                 if any(["expirer" in f for f in expected_files]) and not quiet:
 | |
|                     self.assertIn(
 | |
|                         "object-expirer.conf is deprecated.", messages)
 | |
|                     if verbose:
 | |
|                         for f in expected_files:
 | |
|                             self.assertIn(f, messages)
 | |
|                 elif not expected_files and not quiet:
 | |
|                     self.assertIn("Unable to locate config", messages)
 | |
|                 else:
 | |
|                     self.assertEqual(messages, "")
 | |
| 
 | |
|             assert_results(quiet=True, verbose=False)
 | |
|             assert_results(quiet=False, verbose=False)
 | |
|             assert_results(quiet=False, verbose=True)
 | |
| 
 | |
|     def test_expirer_conf_files(self):
 | |
|         self._test_expirer_conf_files(
 | |
|             [('object-expirer.conf', '')], ['object-expirer.conf'])
 | |
| 
 | |
|         self._test_expirer_conf_files(
 | |
|             [('object-server.conf', '')], [])
 | |
|         self._test_expirer_conf_files(
 | |
|             [('object-server.conf', '[object-expirer]')],
 | |
|             ['object-server.conf'])
 | |
| 
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server/1.conf', ''),
 | |
|             ('object-server/2.conf', ''),
 | |
|             ('object-server/3.conf', ''),
 | |
|             ('object-server/4.conf', ''),
 | |
|         ], [])
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server/1.conf', '[object-expirer]'),
 | |
|             ('object-server/2.conf', ''),
 | |
|             ('object-server/3.conf', ''),
 | |
|             ('object-server/4.conf', ''),
 | |
|         ], ['object-server/1.conf'])
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server/1.conf', '[object-expirer]'),
 | |
|             ('object-server/2.conf', '[object-expirer]'),
 | |
|             ('object-server/3.conf', '[object-expirer]'),
 | |
|             ('object-server/4.conf', '[object-expirer]'),
 | |
|         ], [
 | |
|             'object-server/1.conf',
 | |
|             'object-server/2.conf',
 | |
|             'object-server/3.conf',
 | |
|             'object-server/4.conf',
 | |
|         ])
 | |
| 
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server.conf', ''),
 | |
|             ('object-expirer.conf', ''),
 | |
|         ], ['object-expirer.conf'])
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server.conf', '[object-expirer]'),
 | |
|             ('object-expirer.conf', ''),
 | |
|         ], ['object-server.conf'])
 | |
| 
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server/1.conf', ''),
 | |
|             ('object-server/2.conf', ''),
 | |
|             ('object-server/3.conf', ''),
 | |
|             ('object-server/4.conf', ''),
 | |
|             ('object-expirer.conf', ''),
 | |
|         ], ['object-expirer.conf'])
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server/1.conf', '[object-expirer]'),
 | |
|             ('object-server/2.conf', ''),
 | |
|             ('object-server/3.conf', ''),
 | |
|             ('object-server/4.conf', ''),
 | |
|             ('object-expirer.conf', ''),
 | |
|         ], ['object-server/1.conf'])
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server/1.conf', '[object-expirer]'),
 | |
|             ('object-server/2.conf', '[object-expirer]'),
 | |
|             ('object-server/3.conf', '[object-expirer]'),
 | |
|             ('object-server/4.conf', '[object-expirer]'),
 | |
|             ('object-expirer.conf', ''),
 | |
|         ], [
 | |
|             'object-server/1.conf',
 | |
|             'object-server/2.conf',
 | |
|             'object-server/3.conf',
 | |
|             'object-server/4.conf',
 | |
|         ])
 | |
| 
 | |
|         self._test_expirer_conf_files([
 | |
|             ('object-server/1.conf.d/20_setting.conf', '[object-expirer]'),
 | |
|             ('object-server/2.conf.d/20_setting.conf', '[object-expirer]'),
 | |
|             ('object-server/3.conf.d/20_setting.conf', '[object-expirer]'),
 | |
|             ('object-server/4.conf.d/20_setting.conf', '[object-expirer]'),
 | |
|         ], [
 | |
|             'object-server/1.conf.d',
 | |
|             'object-server/2.conf.d',
 | |
|             'object-server/3.conf.d',
 | |
|             'object-server/4.conf.d',
 | |
|         ])
 | |
| 
 | |
|     def test_proxy_conf_dir(self):
 | |
|         conf_files = (
 | |
|             'proxy-server.conf.d/00.conf',
 | |
|             'proxy-server.conf.d/01.conf',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             server = manager.Server('proxy')
 | |
|             conf_dirs = server.conf_files()
 | |
|             self.assertEqual(len(conf_dirs), 1)
 | |
|             conf_dir = conf_dirs[0]
 | |
|             proxy_conf_dir = self.join_swift_dir('proxy-server.conf.d')
 | |
|             self.assertEqual(proxy_conf_dir, conf_dir)
 | |
| 
 | |
|     def test_named_conf_dir(self):
 | |
|         conf_files = (
 | |
|             'object-server/base.conf-template',
 | |
|             'object-server/object-server.conf.d/00_base.conf',
 | |
|             'object-server/object-server.conf.d/10_server.conf',
 | |
|             'object-server/object-replication.conf.d/00_base.conf',
 | |
|             'object-server/object-replication.conf.d/10_server.conf',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             server = manager.Server('object.replication')
 | |
|             conf_dirs = server.conf_files()
 | |
|             self.assertEqual(len(conf_dirs), 1)
 | |
|             conf_dir = conf_dirs[0]
 | |
|             replication_server_conf_dir = self.join_swift_dir(
 | |
|                 'object-server/object-replication.conf.d')
 | |
|             self.assertEqual(replication_server_conf_dir, conf_dir)
 | |
|             # and again with no named filter
 | |
|             server = manager.Server('object')
 | |
|             conf_dirs = server.conf_files()
 | |
|             self.assertEqual(len(conf_dirs), 2)
 | |
|             for named_conf in ('server', 'replication'):
 | |
|                 conf_dir = self.join_swift_dir(
 | |
|                     'object-server/object-%s.conf.d' % named_conf)
 | |
|                 self.assertTrue(conf_dir in conf_dirs)
 | |
| 
 | |
|     def test_conf_dir(self):
 | |
|         conf_files = (
 | |
|             'object-server/object-server.conf-base',
 | |
|             'object-server/1.conf.d/base.conf',
 | |
|             'object-server/1.conf.d/1.conf',
 | |
|             'object-server/2.conf.d/base.conf',
 | |
|             'object-server/2.conf.d/2.conf',
 | |
|             'object-server/3.conf.d/base.conf',
 | |
|             'object-server/3.conf.d/3.conf',
 | |
|             'object-server/4.conf.d/base.conf',
 | |
|             'object-server/4.conf.d/4.conf',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.SWIFT_DIR = t
 | |
|             server = manager.Server('object-replicator')
 | |
|             conf_dirs = server.conf_files()
 | |
|             self.assertEqual(len(conf_dirs), 4)
 | |
|             c1 = self.join_swift_dir('object-server/1.conf.d')
 | |
|             c2 = self.join_swift_dir('object-server/2.conf.d')
 | |
|             c3 = self.join_swift_dir('object-server/3.conf.d')
 | |
|             c4 = self.join_swift_dir('object-server/4.conf.d')
 | |
|             for c in [c1, c2, c3, c4]:
 | |
|                 self.assertTrue(c in conf_dirs)
 | |
|             # test configs returned sorted
 | |
|             sorted_confs = sorted([c1, c2, c3, c4])
 | |
|             self.assertEqual(conf_dirs, sorted_confs)
 | |
| 
 | |
|     def test_named_conf_dir_pid_files(self):
 | |
|         conf_files = (
 | |
|             'object-server/object-server.pid.d',
 | |
|             'object-server/object-replication.pid.d',
 | |
|         )
 | |
|         with temptree(conf_files) as t:
 | |
|             manager.RUN_DIR = t
 | |
|             server = manager.Server('object.replication', run_dir=t)
 | |
|             pid_files = server.pid_files()
 | |
|             self.assertEqual(len(pid_files), 1)
 | |
|             pid_file = pid_files[0]
 | |
|             replication_server_pid = self.join_run_dir(
 | |
|                 'object-server/object-replication.pid.d')
 | |
|             self.assertEqual(replication_server_pid, pid_file)
 | |
|             # and again with no named filter
 | |
|             server = manager.Server('object', run_dir=t)
 | |
|             pid_files = server.pid_files()
 | |
|             self.assertEqual(len(pid_files), 2)
 | |
|             for named_pid in ('server', 'replication'):
 | |
|                 pid_file = self.join_run_dir(
 | |
|                     'object-server/object-%s.pid.d' % named_pid)
 | |
|                 self.assertTrue(pid_file in pid_files)
 | |
| 
 | |
|     def test_iter_pid_files(self):
 | |
|         """
 | |
|         Server.iter_pid_files is kinda boring, test the
 | |
|         Server.pid_files stuff here as well
 | |
|         """
 | |
|         pid_files = (
 | |
|             ('proxy-server.pid', 1),
 | |
|             ('auth-server.pid', 'blah'),
 | |
|             ('object-replicator/1.pid', 11),
 | |
|             ('object-replicator/2.pid', 12),
 | |
|         )
 | |
|         files, contents = zip(*pid_files)
 | |
|         with temptree(files, contents) as t:
 | |
|             manager.RUN_DIR = t
 | |
|             server = manager.Server('proxy', run_dir=t)
 | |
|             # test get one file
 | |
|             iterator = server.iter_pid_files()
 | |
|             pid_file, pid = next(iterator)
 | |
|             self.assertEqual(pid_file, self.join_run_dir('proxy-server.pid'))
 | |
|             self.assertEqual(pid, 1)
 | |
|             # ... and only one file
 | |
|             self.assertRaises(StopIteration, next, iterator)
 | |
|             # test invalid value in pid file
 | |
|             server = manager.Server('auth', run_dir=t)
 | |
|             pid_file, pid = next(server.iter_pid_files())
 | |
|             self.assertIsNone(pid)
 | |
|             # test object-server doesn't steal pids from object-replicator
 | |
|             server = manager.Server('object', run_dir=t)
 | |
|             self.assertRaises(StopIteration, next, server.iter_pid_files())
 | |
|             # test multi-pid iter
 | |
|             server = manager.Server('object-replicator', run_dir=t)
 | |
|             real_map = {
 | |
|                 11: self.join_run_dir('object-replicator/1.pid'),
 | |
|                 12: self.join_run_dir('object-replicator/2.pid'),
 | |
|             }
 | |
|             pid_map = {}
 | |
|             for pid_file, pid in server.iter_pid_files():
 | |
|                 pid_map[pid] = pid_file
 | |
|             self.assertEqual(pid_map, real_map)
 | |
| 
 | |
|         # test get pid_files by number
 | |
|         conf_files = (
 | |
|             'object-server/1.conf',
 | |
|             'object-server/2.conf',
 | |
|             'object-server/3.conf',
 | |
|             'object-server/4.conf',
 | |
|         )
 | |
| 
 | |
|         pid_files = (
 | |
|             ('object-server/1.pid', 1),
 | |
|             ('object-server/2.pid', 2),
 | |
|             ('object-server/5.pid', 5),
 | |
|         )
 | |
| 
 | |
|         with temptree(conf_files) as swift_dir:
 | |
|             manager.SWIFT_DIR = swift_dir
 | |
|             files, pids = zip(*pid_files)
 | |
|             with temptree(files, pids) as t:
 | |
|                 manager.RUN_DIR = t
 | |
|                 server = manager.Server('object', run_dir=t)
 | |
|                 # test get all pid files
 | |
|                 real_map = {
 | |
|                     1: self.join_run_dir('object-server/1.pid'),
 | |
|                     2: self.join_run_dir('object-server/2.pid'),
 | |
|                     5: self.join_run_dir('object-server/5.pid'),
 | |
|                 }
 | |
|                 pid_map = {}
 | |
|                 for pid_file, pid in server.iter_pid_files():
 | |
|                     pid_map[pid] = pid_file
 | |
|                 self.assertEqual(pid_map, real_map)
 | |
|                 # test get pid with matching conf
 | |
|                 pids = list(server.iter_pid_files(number=2))
 | |
|                 self.assertEqual(len(pids), 1)
 | |
|                 pid_file, pid = pids[0]
 | |
|                 self.assertEqual(pid, 2)
 | |
|                 pid_two = self.join_run_dir('object-server/2.pid')
 | |
|                 self.assertEqual(pid_file, pid_two)
 | |
|                 # try to iter on a pid number with a matching conf but no pid
 | |
|                 pids = list(server.iter_pid_files(number=3))
 | |
|                 self.assertFalse(pids)
 | |
|                 # test get pids w/o matching conf
 | |
|                 pids = list(server.iter_pid_files(number=5))
 | |
|                 self.assertFalse(pids)
 | |
| 
 | |
|         # test get pid_files by conf name
 | |
|         conf_files = (
 | |
|             'object-server/1.conf',
 | |
|             'object-server/2.conf',
 | |
|             'object-server/3.conf',
 | |
|             'object-server/4.conf',
 | |
|         )
 | |
| 
 | |
|         pid_files = (
 | |
|             ('object-server/1.pid', 1),
 | |
|             ('object-server/2.pid', 2),
 | |
|             ('object-server/5.pid', 5),
 | |
|         )
 | |
| 
 | |
|         with temptree(conf_files) as swift_dir:
 | |
|             manager.SWIFT_DIR = swift_dir
 | |
|             files, pids = zip(*pid_files)
 | |
|             with temptree(files, pids) as t:
 | |
|                 manager.RUN_DIR = t
 | |
|                 server = manager.Server('object.2', run_dir=t)
 | |
|                 # test get pid with matching conf
 | |
|                 pids = list(server.iter_pid_files())
 | |
|                 self.assertEqual(len(pids), 1)
 | |
|                 pid_file, pid = pids[0]
 | |
|                 self.assertEqual(pid, 2)
 | |
|                 pid_two = self.join_run_dir('object-server/2.pid')
 | |
|                 self.assertEqual(pid_file, pid_two)
 | |
| 
 | |
|     def test_signal_pids(self):
 | |
|         temp_files = (
 | |
|             ('var/run/zero-server.pid', 0),
 | |
|             ('var/run/proxy-server.pid', 1),
 | |
|             ('var/run/auth-server.pid', 2),
 | |
|             ('var/run/one-server.pid', 3),
 | |
|             ('var/run/object-server.pid', 4),
 | |
|             ('var/run/invalid-server.pid', 'Forty-Two'),
 | |
|             ('proc/3/cmdline', 'swift-another-server')
 | |
|         )
 | |
|         with temptree(*zip(*temp_files)) as t:
 | |
|             manager.RUN_DIR = os.path.join(t, 'var/run')
 | |
|             manager.PROC_DIR = os.path.join(t, 'proc')
 | |
|             # mock os with so both the first and second are running
 | |
|             manager.os = MockOs([1, 2])
 | |
|             server = manager.Server('proxy', run_dir=manager.RUN_DIR)
 | |
|             pids = server.signal_pids(DUMMY_SIG)
 | |
|             self.assertEqual(len(pids), 1)
 | |
|             self.assertIn(1, pids)
 | |
|             self.assertEqual(manager.os.pid_sigs[1], [DUMMY_SIG])
 | |
|             # make sure other process not signaled
 | |
|             self.assertNotIn(2, pids)
 | |
|             self.assertNotIn(2, manager.os.pid_sigs)
 | |
|             # capture stdio
 | |
|             old_stdout = sys.stdout
 | |
|             try:
 | |
|                 with open(os.path.join(t, 'output'), 'w+') as f:
 | |
|                     sys.stdout = f
 | |
|                     # test print details
 | |
|                     pids = server.signal_pids(DUMMY_SIG)
 | |
|                     output = pop_stream(f)
 | |
|                     self.assertIn('pid: %s' % 1, output)
 | |
|                     self.assertIn('signal: %s' % DUMMY_SIG, output)
 | |
|                     # test no details on signal.SIG_DFL
 | |
|                     pids = server.signal_pids(signal.SIG_DFL)
 | |
|                     self.assertEqual(pop_stream(f), '')
 | |
|                     # reset mock os so only the second server is running
 | |
|                     manager.os = MockOs([2])
 | |
|                     # test pid not running
 | |
|                     pids = server.signal_pids(signal.SIG_DFL)
 | |
|                     self.assertNotIn(1, pids)
 | |
|                     self.assertNotIn(1, manager.os.pid_sigs)
 | |
|                     # test remove stale pid file
 | |
|                     self.assertFalse(os.path.exists(
 | |
|                         self.join_run_dir('proxy-server.pid')))
 | |
|                     # reset mock os with no running pids
 | |
|                     manager.os = MockOs([])
 | |
|                     server = manager.Server('auth', run_dir=manager.RUN_DIR)
 | |
|                     # test verbose warns on removing stale pid file
 | |
|                     pids = server.signal_pids(signal.SIG_DFL, verbose=True)
 | |
|                     output = pop_stream(f)
 | |
|                     self.assertTrue('stale pid' in output.lower())
 | |
|                     auth_pid = self.join_run_dir('auth-server.pid')
 | |
|                     self.assertTrue(auth_pid in output)
 | |
|                     # reset mock os so only the third server is running
 | |
|                     manager.os = MockOs([3])
 | |
|                     server = manager.Server('one', run_dir=manager.RUN_DIR)
 | |
|                     # test verbose warns on removing invalid pid file
 | |
|                     pids = server.signal_pids(signal.SIG_DFL, verbose=True)
 | |
|                     output = pop_stream(f)
 | |
|                     old_stdout.write('output %s' % output)
 | |
|                     self.assertTrue('removing pid file' in output.lower())
 | |
|                     one_pid = self.join_run_dir('one-server.pid')
 | |
|                     self.assertTrue(one_pid in output)
 | |
| 
 | |
|                     server = manager.Server('zero', run_dir=manager.RUN_DIR)
 | |
|                     self.assertTrue(os.path.exists(
 | |
|                         self.join_run_dir('zero-server.pid')))  # sanity
 | |
|                     # test verbose warns on removing pid file with invalid pid
 | |
|                     pids = server.signal_pids(signal.SIG_DFL, verbose=True)
 | |
|                     output = pop_stream(f)
 | |
|                     old_stdout.write('output %s' % output)
 | |
|                     self.assertTrue('with invalid pid' in output.lower())
 | |
|                     self.assertFalse(os.path.exists(
 | |
|                         self.join_run_dir('zero-server.pid')))
 | |
|                     server = manager.Server('invalid-server',
 | |
|                                             run_dir=manager.RUN_DIR)
 | |
|                     self.assertTrue(os.path.exists(
 | |
|                         self.join_run_dir('invalid-server.pid')))  # sanity
 | |
|                     # test verbose warns on removing pid file with invalid pid
 | |
|                     pids = server.signal_pids(signal.SIG_DFL, verbose=True)
 | |
|                     output = pop_stream(f)
 | |
|                     old_stdout.write('output %s' % output)
 | |
|                     self.assertTrue('with invalid pid' in output.lower())
 | |
|                     self.assertFalse(os.path.exists(
 | |
|                         self.join_run_dir('invalid-server.pid')))
 | |
| 
 | |
|                     # reset mock os with no running pids
 | |
|                     manager.os = MockOs([])
 | |
|                     # test warning with insufficient permissions
 | |
|                     server = manager.Server('object', run_dir=manager.RUN_DIR)
 | |
|                     pids = server.signal_pids(manager.os.RAISE_EPERM_SIG)
 | |
|                     output = pop_stream(f)
 | |
|                     self.assertTrue('no permission to signal pid 4' in
 | |
|                                     output.lower(), output)
 | |
|             finally:
 | |
|                 sys.stdout = old_stdout
 | |
| 
 | |
|     def test_get_running_pids(self):
 | |
|         # test only gets running pids
 | |
|         temp_files = (
 | |
|             ('var/run/test-server1.pid', 1),
 | |
|             ('var/run/test-server2.pid', 2),
 | |
|             ('var/run/test-server3.pid', 3),
 | |
|             ('proc/1/cmdline', 'swift-test-server'),
 | |
|             ('proc/3/cmdline', 'swift-another-server')
 | |
|         )
 | |
|         with temptree(*zip(*temp_files)) as t:
 | |
|             manager.RUN_DIR = os.path.join(t, 'var/run')
 | |
|             manager.PROC_DIR = os.path.join(t, 'proc')
 | |
|             server = manager.Server(
 | |
|                 'test-server', run_dir=manager.RUN_DIR)
 | |
|             # mock os, only pid '1' is running
 | |
|             manager.os = MockOs([1, 3])
 | |
|             running_pids = server.get_running_pids()
 | |
|             self.assertEqual(len(running_pids), 1)
 | |
|             self.assertIn(1, running_pids)
 | |
|             self.assertNotIn(2, running_pids)
 | |
|             self.assertNotIn(3, running_pids)
 | |
|             # test persistent running pid files
 | |
|             self.assertTrue(os.path.exists(
 | |
|                 os.path.join(manager.RUN_DIR, 'test-server1.pid')))
 | |
|             # test clean up stale pids
 | |
|             pid_two = self.join_swift_dir('test-server2.pid')
 | |
|             self.assertFalse(os.path.exists(pid_two))
 | |
|             pid_three = self.join_swift_dir('test-server3.pid')
 | |
|             self.assertFalse(os.path.exists(pid_three))
 | |
|             # reset mock os, no pids running
 | |
|             manager.os = MockOs([])
 | |
|             running_pids = server.get_running_pids()
 | |
|             self.assertFalse(running_pids)
 | |
|             # and now all pid files are cleaned out
 | |
|             pid_one = self.join_run_dir('test-server1.pid')
 | |
|             self.assertFalse(os.path.exists(pid_one))
 | |
|             all_pids = os.listdir(manager.RUN_DIR)
 | |
|             self.assertEqual(len(all_pids), 0)
 | |
| 
 | |
|         # test only get pids for right server
 | |
|         pid_files = (
 | |
|             ('thing-doer.pid', 1),
 | |
|             ('thing-sayer.pid', 2),
 | |
|             ('other-doer.pid', 3),
 | |
|             ('other-sayer.pid', 4),
 | |
|         )
 | |
|         files, pids = zip(*pid_files)
 | |
|         with temptree(files, pids) as t:
 | |
|             manager.RUN_DIR = t
 | |
|             # all pids are running
 | |
|             manager.os = MockOs(pids)
 | |
|             server = manager.Server('thing-doer', run_dir=t)
 | |
|             running_pids = server.get_running_pids()
 | |
|             # only thing-doer.pid, 1
 | |
|             self.assertEqual(len(running_pids), 1)
 | |
|             self.assertIn(1, running_pids)
 | |
|             # no other pids returned
 | |
|             for n in (2, 3, 4):
 | |
|                 self.assertNotIn(n, running_pids)
 | |
|             # assert stale pids for other servers ignored
 | |
|             manager.os = MockOs([1])  # only thing-doer is running
 | |
|             running_pids = server.get_running_pids()
 | |
|             for f in ('thing-sayer.pid', 'other-doer.pid', 'other-sayer.pid'):
 | |
|                 # other server pid files persist
 | |
|                 self.assertTrue(os.path.exists, os.path.join(t, f))
 | |
|             # verify that servers are in fact not running
 | |
|             for server_name in ('thing-sayer', 'other-doer', 'other-sayer'):
 | |
|                 server = manager.Server(server_name, run_dir=t)
 | |
|                 running_pids = server.get_running_pids()
 | |
|                 self.assertFalse(running_pids)
 | |
|             # and now all OTHER pid files are cleaned out
 | |
|             all_pids = os.listdir(t)
 | |
|             self.assertEqual(len(all_pids), 1)
 | |
|             self.assertTrue(os.path.exists(os.path.join(t, 'thing-doer.pid')))
 | |
| 
 | |
|     def test_kill_running_pids(self):
 | |
|         pid_files = (
 | |
|             ('object-server.pid', 1),
 | |
|             ('object-replicator1.pid', 11),
 | |
|             ('object-replicator2.pid', 12),
 | |
|         )
 | |
|         files, running_pids = zip(*pid_files)
 | |
|         with temptree(files, running_pids) as t:
 | |
|             manager.RUN_DIR = t
 | |
|             server = manager.Server('object', run_dir=t)
 | |
|             # test no servers running
 | |
|             manager.os = MockOs([])
 | |
|             pids = server.kill_running_pids()
 | |
|             self.assertFalse(pids, pids)
 | |
|         files, running_pids = zip(*pid_files)
 | |
|         with temptree(files, running_pids) as t:
 | |
|             manager.RUN_DIR = t
 | |
|             server.run_dir = t
 | |
|             # start up pid
 | |
|             manager.os = MockOs([1])
 | |
|             server = manager.Server('object', run_dir=t)
 | |
|             # test kill one pid
 | |
|             pids = server.kill_running_pids()
 | |
|             self.assertEqual(len(pids), 1)
 | |
|             self.assertIn(1, pids)
 | |
|             self.assertEqual(manager.os.pid_sigs[1], [signal.SIGTERM])
 | |
|             # reset os mock
 | |
|             manager.os = MockOs([1])
 | |
|             # test shutdown
 | |
|             self.assertTrue('object-server' in
 | |
|                             manager.GRACEFUL_SHUTDOWN_SERVERS)
 | |
|             pids = server.kill_running_pids(graceful=True)
 | |
|             self.assertEqual(len(pids), 1)
 | |
|             self.assertIn(1, pids)
 | |
|             self.assertEqual(manager.os.pid_sigs[1], [signal.SIGHUP])
 | |
|             # start up other servers
 | |
|             manager.os = MockOs([11, 12])
 | |
|             # test multi server kill & ignore graceful on unsupported server
 | |
|             self.assertFalse('object-replicator' in
 | |
|                              manager.GRACEFUL_SHUTDOWN_SERVERS)
 | |
|             server = manager.Server('object-replicator', run_dir=t)
 | |
|             pids = server.kill_running_pids(graceful=True)
 | |
|             self.assertEqual(len(pids), 2)
 | |
|             for pid in (11, 12):
 | |
|                 self.assertTrue(pid in pids)
 | |
|                 self.assertEqual(manager.os.pid_sigs[pid],
 | |
|                                  [signal.SIGTERM])
 | |
|             # and the other pid is of course not signaled
 | |
|             self.assertNotIn(1, manager.os.pid_sigs)
 | |
| 
 | |
|     def test_status(self):
 | |
|         conf_files = (
 | |
|             'test-server/1.conf',
 | |
|             'test-server/2.conf',
 | |
|             'test-server/3.conf',
 | |
|             'test-server/4.conf',
 | |
|         )
 | |
| 
 | |
|         pid_files = (
 | |
|             ('test-server/1.pid', 1),
 | |
|             ('test-server/2.pid', 2),
 | |
|             ('test-server/3.pid', 3),
 | |
|             ('test-server/4.pid', 4),
 | |
|         )
 | |
| 
 | |
|         with temptree(conf_files) as swift_dir:
 | |
|             manager.SWIFT_DIR = swift_dir
 | |
|             files, pids = zip(*pid_files)
 | |
|             with temptree(files, pids) as t:
 | |
|                 manager.RUN_DIR = t
 | |
|                 # setup running servers
 | |
|                 server = manager.Server('test', run_dir=t)
 | |
|                 # capture stdio
 | |
|                 old_stdout = sys.stdout
 | |
|                 try:
 | |
|                     with open(os.path.join(t, 'output'), 'w+') as f:
 | |
|                         sys.stdout = f
 | |
|                         # test status for all running
 | |
|                         manager.os = MockOs(pids)
 | |
|                         proc_files = (
 | |
|                             ('1/cmdline', 'swift-test-server'),
 | |
|                             ('2/cmdline', 'swift-test-server'),
 | |
|                             ('3/cmdline', 'swift-test-server'),
 | |
|                             ('4/cmdline', 'swift-test-server'),
 | |
|                         )
 | |
|                         files, contents = zip(*proc_files)
 | |
|                         with temptree(files, contents) as t:
 | |
|                             manager.PROC_DIR = t
 | |
|                             self.assertEqual(server.status(), 0)
 | |
|                             output = pop_stream(f).strip().splitlines()
 | |
|                             self.assertEqual(len(output), 4)
 | |
|                             for line in output:
 | |
|                                 self.assertTrue('test-server running' in line)
 | |
|                         # test get single server by number
 | |
|                         with temptree([], []) as t:
 | |
|                             manager.PROC_DIR = t
 | |
|                             self.assertEqual(server.status(number=4), 0)
 | |
|                             output = pop_stream(f).strip().splitlines()
 | |
|                             self.assertEqual(len(output), 1)
 | |
|                             line = output[0]
 | |
|                             self.assertTrue('test-server running' in line)
 | |
|                             conf_four = self.join_swift_dir(conf_files[3])
 | |
|                             self.assertTrue('4 - %s' % conf_four in line)
 | |
|                         # test some servers not running
 | |
|                         manager.os = MockOs([1, 2, 3])
 | |
|                         proc_files = (
 | |
|                             ('1/cmdline', 'swift-test-server'),
 | |
|                             ('2/cmdline', 'swift-test-server'),
 | |
|                             ('3/cmdline', 'swift-test-server'),
 | |
|                         )
 | |
|                         files, contents = zip(*proc_files)
 | |
|                         with temptree(files, contents) as t:
 | |
|                             manager.PROC_DIR = t
 | |
|                             self.assertEqual(server.status(), 0)
 | |
|                             output = pop_stream(f).strip().splitlines()
 | |
|                             self.assertEqual(len(output), 3)
 | |
|                             for line in output:
 | |
|                                 self.assertTrue('test-server running' in line)
 | |
|                         # test single server not running
 | |
|                         manager.os = MockOs([1, 2])
 | |
|                         proc_files = (
 | |
|                             ('1/cmdline', 'swift-test-server'),
 | |
|                             ('2/cmdline', 'swift-test-server'),
 | |
|                         )
 | |
|                         files, contents = zip(*proc_files)
 | |
|                         with temptree(files, contents) as t:
 | |
|                             manager.PROC_DIR = t
 | |
|                             self.assertEqual(server.status(number=3), 1)
 | |
|                             output = pop_stream(f).strip().splitlines()
 | |
|                             self.assertEqual(len(output), 1)
 | |
|                             line = output[0]
 | |
|                             self.assertTrue('not running' in line)
 | |
|                             conf_three = self.join_swift_dir(conf_files[2])
 | |
|                             self.assertTrue(conf_three in line)
 | |
|                         # test no running pids
 | |
|                         manager.os = MockOs([])
 | |
|                         with temptree([], []) as t:
 | |
|                             manager.PROC_DIR = t
 | |
|                             self.assertEqual(server.status(), 1)
 | |
|                             output = pop_stream(f).lower()
 | |
|                             self.assertTrue('no test-server running' in output)
 | |
|                         # test use provided pids
 | |
|                         pids = {
 | |
|                             1: '1.pid',
 | |
|                             2: '2.pid',
 | |
|                         }
 | |
|                         # shouldn't call get_running_pids
 | |
|                         called = []
 | |
| 
 | |
|                         def mock(*args, **kwargs):
 | |
|                             called.append(True)
 | |
|                         server.get_running_pids = mock
 | |
|                         status = server.status(pids=pids)
 | |
|                         self.assertEqual(status, 0)
 | |
|                         self.assertFalse(called)
 | |
|                         output = pop_stream(f).strip().splitlines()
 | |
|                         self.assertEqual(len(output), 2)
 | |
|                         for line in output:
 | |
|                             self.assertTrue('test-server running' in line)
 | |
|                 finally:
 | |
|                     sys.stdout = old_stdout
 | |
| 
 | |
|     def test_spawn(self):
 | |
| 
 | |
|         # mocks
 | |
|         class MockProcess(object):
 | |
| 
 | |
|             NOTHING = 'default besides None'
 | |
|             STDOUT = 'stdout'
 | |
|             PIPE = 'pipe'
 | |
| 
 | |
|             def __init__(self, pids=None):
 | |
|                 if pids is None:
 | |
|                     pids = []
 | |
|                 self.pids = (p for p in pids)
 | |
| 
 | |
|             def Popen(self, args, **kwargs):
 | |
|                 return MockProc(next(self.pids), args, **kwargs)
 | |
| 
 | |
|         class MockProc(object):
 | |
| 
 | |
|             def __init__(self, pid, args, stdout=MockProcess.NOTHING,
 | |
|                          stderr=MockProcess.NOTHING):
 | |
|                 self.pid = pid
 | |
|                 self.args = args
 | |
|                 self.stdout = stdout
 | |
|                 if stderr == MockProcess.STDOUT:
 | |
|                     self.stderr = self.stdout
 | |
|                 else:
 | |
|                     self.stderr = stderr
 | |
| 
 | |
|         # setup running servers
 | |
|         server = manager.Server('test')
 | |
| 
 | |
|         with temptree(['test-server.conf']) as swift_dir:
 | |
|             manager.SWIFT_DIR = swift_dir
 | |
|             with temptree([]) as t:
 | |
|                 manager.RUN_DIR = t
 | |
|                 server.run_dir = t
 | |
|                 old_subprocess = manager.subprocess
 | |
|                 try:
 | |
|                     # test single server process calls spawn once
 | |
|                     manager.subprocess = MockProcess([1])
 | |
|                     conf_file = self.join_swift_dir('test-server.conf')
 | |
|                     # spawn server no kwargs
 | |
|                     server.spawn(conf_file)
 | |
|                     # test pid file
 | |
|                     pid_file = self.join_run_dir('test-server.pid')
 | |
|                     self.assertTrue(os.path.exists(pid_file))
 | |
|                     pid_on_disk = int(open(pid_file).read().strip())
 | |
|                     self.assertEqual(pid_on_disk, 1)
 | |
|                     # assert procs args
 | |
|                     self.assertTrue(server.procs)
 | |
|                     self.assertEqual(len(server.procs), 1)
 | |
|                     proc = server.procs[0]
 | |
|                     expected_args = [
 | |
|                         'swift-test-server',
 | |
|                         conf_file,
 | |
|                     ]
 | |
|                     self.assertEqual(proc.args, expected_args)
 | |
|                     # assert stdout is piped
 | |
|                     self.assertEqual(proc.stdout, MockProcess.PIPE)
 | |
|                     self.assertEqual(proc.stderr, proc.stdout)
 | |
|                     # test multi server process calls spawn multiple times
 | |
|                     manager.subprocess = MockProcess([11, 12, 13, 14])
 | |
|                     conf1 = self.join_swift_dir('test-server/1.conf')
 | |
|                     conf2 = self.join_swift_dir('test-server/2.conf')
 | |
|                     conf3 = self.join_swift_dir('test-server/3.conf')
 | |
|                     conf4 = self.join_swift_dir('test-server/4.conf')
 | |
|                     server = manager.Server('test', run_dir=t)
 | |
|                     # test server run once
 | |
|                     server.spawn(conf1, once=True)
 | |
|                     self.assertTrue(server.procs)
 | |
|                     self.assertEqual(len(server.procs), 1)
 | |
|                     proc = server.procs[0]
 | |
|                     expected_args = ['swift-test-server', conf1, 'once']
 | |
|                     # assert stdout is piped
 | |
|                     self.assertEqual(proc.stdout, MockProcess.PIPE)
 | |
|                     self.assertEqual(proc.stderr, proc.stdout)
 | |
|                     # test server not daemon
 | |
|                     server.spawn(conf2, daemon=False)
 | |
|                     self.assertTrue(server.procs)
 | |
|                     self.assertEqual(len(server.procs), 2)
 | |
|                     proc = server.procs[1]
 | |
|                     expected_args = ['swift-test-server', conf2, 'verbose']
 | |
|                     self.assertEqual(proc.args, expected_args)
 | |
|                     # assert stdout is not changed
 | |
|                     self.assertIsNone(proc.stdout)
 | |
|                     self.assertIsNone(proc.stderr)
 | |
|                     # test server wait
 | |
|                     server.spawn(conf3, wait=False)
 | |
|                     self.assertTrue(server.procs)
 | |
|                     self.assertEqual(len(server.procs), 3)
 | |
|                     proc = server.procs[2]
 | |
|                     # assert stdout is /dev/null
 | |
|                     with open('/dev/null', 'wb+') as fp:
 | |
|                         self.assertTrue(isinstance(proc.stdout, type(fp)))
 | |
|                     self.assertEqual(proc.stdout.name, os.devnull)
 | |
|                     self.assertIn('b', proc.stdout.mode)
 | |
|                     self.assertTrue(any(x in proc.stdout.mode for x in 'aw+'),
 | |
|                                     'mode must be writable, not %r' %
 | |
|                                     proc.stdout.mode)
 | |
|                     self.assertEqual(proc.stderr, proc.stdout)
 | |
|                     # test not daemon over-rides wait
 | |
|                     server.spawn(conf4, wait=False, daemon=False, once=True)
 | |
|                     self.assertTrue(server.procs)
 | |
|                     self.assertEqual(len(server.procs), 4)
 | |
|                     proc = server.procs[3]
 | |
|                     expected_args = ['swift-test-server', conf4, 'once',
 | |
|                                      'verbose']
 | |
|                     self.assertEqual(proc.args, expected_args)
 | |
|                     # daemon behavior should trump wait, once shouldn't matter
 | |
|                     self.assertIsNone(proc.stdout)
 | |
|                     self.assertIsNone(proc.stderr)
 | |
|                     # assert pids
 | |
|                     for i, proc in enumerate(server.procs):
 | |
|                         pid_file = self.join_run_dir('test-server/%d.pid' %
 | |
|                                                      (i + 1))
 | |
|                         pid_on_disk = int(open(pid_file).read().strip())
 | |
|                         self.assertEqual(pid_on_disk, proc.pid)
 | |
|                 finally:
 | |
|                     manager.subprocess = old_subprocess
 | |
| 
 | |
|     def test_wait(self):
 | |
|         server = manager.Server('test')
 | |
|         self.assertEqual(server.wait(), 0)
 | |
| 
 | |
|         class MockProcess(threading.Thread):
 | |
|             def __init__(self, delay=0.1, fail_to_start=False):
 | |
|                 threading.Thread.__init__(self)
 | |
|                 # setup pipe
 | |
|                 rfd, wfd = os.pipe()
 | |
|                 # subprocess connection to read stdout
 | |
|                 self.stdout = os.fdopen(rfd, 'rb')
 | |
|                 # real process connection to write stdout
 | |
|                 self._stdout = os.fdopen(wfd, 'wb')
 | |
|                 self.delay = delay
 | |
|                 self.finished = False
 | |
|                 self.returncode = None
 | |
|                 if fail_to_start:
 | |
|                     self._returncode = 1
 | |
|                     self.run = self.fail
 | |
|                 else:
 | |
|                     self._returncode = 0
 | |
| 
 | |
|             def __enter__(self):
 | |
|                 self.start()
 | |
|                 return self
 | |
| 
 | |
|             def __exit__(self, *args):
 | |
|                 if self.is_alive():
 | |
|                     self.join()
 | |
| 
 | |
|             def close_stdout(self):
 | |
|                 self._stdout.flush()
 | |
|                 with open(os.devnull, 'wb') as nullfile:
 | |
|                     try:
 | |
|                         os.dup2(nullfile.fileno(), self._stdout.fileno())
 | |
|                     except OSError:
 | |
|                         pass
 | |
| 
 | |
|             def fail(self):
 | |
|                 self._stdout.write(b'mock process started\n')
 | |
|                 sleep(self.delay)  # perform setup processing
 | |
|                 self._stdout.write(b'mock process failed to start\n')
 | |
|                 self.close_stdout()
 | |
| 
 | |
|             def poll(self):
 | |
|                 self.returncode = self._returncode
 | |
|                 return self.returncode or None
 | |
| 
 | |
|             def run(self):
 | |
|                 self._stdout.write(b'mock process started\n')
 | |
|                 sleep(self.delay)  # perform setup processing
 | |
|                 self._stdout.write(b'setup complete!\n')
 | |
|                 self.close_stdout()
 | |
|                 sleep(self.delay)  # do some more processing
 | |
|                 self._stdout.write(b'mock process finished\n')
 | |
|                 self.finished = True
 | |
| 
 | |
|         class MockTime(object):
 | |
| 
 | |
|             def time(self):
 | |
|                 return time()
 | |
| 
 | |
|             def sleep(self, *args, **kwargs):
 | |
|                 pass
 | |
| 
 | |
|         with temptree([]) as t, open(os.path.join(t, 'output'), 'w+') as f, \
 | |
|                 mock.patch.object(sys, 'stdout', f), \
 | |
|                 mock.patch.object(manager, 'WARNING_WAIT', 0.01), \
 | |
|                 mock.patch.object(manager, 'time', MockTime()):
 | |
|             # Note that we actually capture the read stdout (for prints)
 | |
|             # test closing pipe in subprocess unblocks read
 | |
|             with MockProcess() as proc:
 | |
|                 server.procs = [proc]
 | |
|                 status = server.wait()
 | |
|                 self.assertEqual(status, 0)
 | |
|                 # wait should return before process exits
 | |
|                 self.assertTrue(proc.is_alive())
 | |
|                 self.assertFalse(proc.finished)
 | |
|             self.assertTrue(proc.finished)  # make sure it did finish
 | |
|             # test output kwarg prints subprocess output
 | |
|             with MockProcess() as proc:
 | |
|                 server.procs = [proc]
 | |
|                 status = server.wait(output=True)
 | |
|             output = pop_stream(f)
 | |
|             self.assertIn('mock process started', output)
 | |
|             self.assertIn('setup complete', output)
 | |
|             # make sure we don't get prints after stdout was closed
 | |
|             self.assertNotIn('mock process finished', output)
 | |
|             # test process which fails to start
 | |
|             with MockProcess(fail_to_start=True) as proc:
 | |
|                 server.procs = [proc]
 | |
|                 status = server.wait()
 | |
|                 self.assertEqual(status, 1)
 | |
|             self.assertIn('failed', pop_stream(f))
 | |
|             # test multiple procs
 | |
|             procs = [MockProcess(delay=.5) for i in range(3)]
 | |
|             for proc in procs:
 | |
|                 proc.start()
 | |
|             server.procs = procs
 | |
|             status = server.wait()
 | |
|             self.assertEqual(status, 0)
 | |
|             for proc in procs:
 | |
|                 self.assertTrue(proc.is_alive())
 | |
|             for proc in procs:
 | |
|                 proc.join()
 | |
| 
 | |
|     def test_interact(self):
 | |
|         class MockProcess(object):
 | |
| 
 | |
|             def __init__(self, fail=False):
 | |
|                 self.returncode = None
 | |
|                 if fail:
 | |
|                     self._returncode = 1
 | |
|                 else:
 | |
|                     self._returncode = 0
 | |
| 
 | |
|             def communicate(self):
 | |
|                 self.returncode = self._returncode
 | |
|                 return '', ''
 | |
| 
 | |
|         server = manager.Server('test')
 | |
|         server.procs = [MockProcess()]
 | |
|         self.assertEqual(server.interact(), 0)
 | |
|         server.procs = [MockProcess(fail=True)]
 | |
|         self.assertEqual(server.interact(), 1)
 | |
|         procs = []
 | |
|         for fail in (False, True, True):
 | |
|             procs.append(MockProcess(fail=fail))
 | |
|         server.procs = procs
 | |
|         self.assertTrue(server.interact() > 0)
 | |
| 
 | |
|     def test_launch(self):
 | |
|         # stubs
 | |
|         conf_files = (
 | |
|             'proxy-server.conf',
 | |
|             'auth-server.conf',
 | |
|             'object-server/1.conf',
 | |
|             'object-server/2.conf',
 | |
|             'object-server/3.conf',
 | |
|             'object-server/4.conf',
 | |
|         )
 | |
|         pid_files = (
 | |
|             ('proxy-server.pid', 1),
 | |
|             ('proxy-server/2.pid', 2),
 | |
|         )
 | |
| 
 | |
|         # mocks
 | |
|         class MockSpawn(object):
 | |
| 
 | |
|             def __init__(self, pids=None):
 | |
|                 self.conf_files = []
 | |
|                 self.kwargs = []
 | |
|                 if not pids:
 | |
|                     def one_forever():
 | |
|                         while True:
 | |
|                             yield 1
 | |
|                     self.pids = one_forever()
 | |
|                 else:
 | |
|                     self.pids = (x for x in pids)
 | |
| 
 | |
|             def __call__(self, conf_file, **kwargs):
 | |
|                 self.conf_files.append(conf_file)
 | |
|                 self.kwargs.append(kwargs)
 | |
|                 rv = next(self.pids)
 | |
|                 if isinstance(rv, Exception):
 | |
|                     raise rv
 | |
|                 else:
 | |
|                     return rv
 | |
| 
 | |
|         with temptree(conf_files) as swift_dir:
 | |
|             manager.SWIFT_DIR = swift_dir
 | |
|             files, pids = zip(*pid_files)
 | |
|             with temptree(files, pids) as t:
 | |
|                 manager.RUN_DIR = t
 | |
|                 old_stdout = sys.stdout
 | |
|                 try:
 | |
|                     with open(os.path.join(t, 'output'), 'w+') as f:
 | |
|                         sys.stdout = f
 | |
|                         # can't start server w/o an conf
 | |
|                         server = manager.Server('test', run_dir=t)
 | |
|                         self.assertFalse(server.launch())
 | |
|                         # start mock os running all pids
 | |
|                         manager.os = MockOs(pids)
 | |
|                         proc_files = (
 | |
|                             ('1/cmdline', 'swift-proxy-server'),
 | |
|                             ('2/cmdline', 'swift-proxy-server'),
 | |
|                         )
 | |
|                         files, contents = zip(*proc_files)
 | |
|                         with temptree(files, contents) as proc_dir:
 | |
|                             manager.PROC_DIR = proc_dir
 | |
|                             server = manager.Server('proxy', run_dir=t)
 | |
|                             # can't start server if it's already running
 | |
|                             self.assertFalse(server.launch())
 | |
|                             output = pop_stream(f)
 | |
|                             self.assertTrue('running' in output)
 | |
|                             conf_file = self.join_swift_dir(
 | |
|                                 'proxy-server.conf')
 | |
|                             self.assertTrue(conf_file in output)
 | |
|                             pid_file = self.join_run_dir('proxy-server/2.pid')
 | |
|                             self.assertTrue(pid_file in output)
 | |
|                             self.assertTrue('already started' in output)
 | |
| 
 | |
|                         # no running pids
 | |
|                         manager.os = MockOs([])
 | |
|                         with temptree([], []) as proc_dir:
 | |
|                             manager.PROC_DIR = proc_dir
 | |
|                             # test ignore once for non-start-once server
 | |
|                             mock_spawn = MockSpawn([1])
 | |
|                             server.spawn = mock_spawn
 | |
|                             conf_file = self.join_swift_dir(
 | |
|                                 'proxy-server.conf')
 | |
|                             expected = {
 | |
|                                 1: conf_file,
 | |
|                             }
 | |
|                             self.assertEqual(server.launch(once=True),
 | |
|                                              expected)
 | |
|                             self.assertEqual(mock_spawn.conf_files,
 | |
|                                              [conf_file])
 | |
|                             expected = {
 | |
|                                 'once': False,
 | |
|                             }
 | |
|                             self.assertEqual(mock_spawn.kwargs, [expected])
 | |
|                             output = pop_stream(f)
 | |
|                             self.assertIn('Starting', output)
 | |
|                             self.assertNotIn('once', output)
 | |
|                         # test multi-server kwarg once
 | |
|                         server = manager.Server('object-replicator')
 | |
|                         with temptree([], []) as proc_dir:
 | |
|                             manager.PROC_DIR = proc_dir
 | |
|                             mock_spawn = MockSpawn([1, 2, 3, 4])
 | |
|                             server.spawn = mock_spawn
 | |
|                             conf1 = self.join_swift_dir('object-server/1.conf')
 | |
|                             conf2 = self.join_swift_dir('object-server/2.conf')
 | |
|                             conf3 = self.join_swift_dir('object-server/3.conf')
 | |
|                             conf4 = self.join_swift_dir('object-server/4.conf')
 | |
|                             expected = {
 | |
|                                 1: conf1,
 | |
|                                 2: conf2,
 | |
|                                 3: conf3,
 | |
|                                 4: conf4,
 | |
|                             }
 | |
|                             self.assertEqual(server.launch(once=True),
 | |
|                                              expected)
 | |
|                             self.assertEqual(mock_spawn.conf_files, [
 | |
|                                 conf1, conf2, conf3, conf4])
 | |
|                             expected = {
 | |
|                                 'once': True,
 | |
|                             }
 | |
|                             self.assertEqual(len(mock_spawn.kwargs), 4)
 | |
|                             for kwargs in mock_spawn.kwargs:
 | |
|                                 self.assertEqual(kwargs, expected)
 | |
|                             # test number kwarg
 | |
|                             mock_spawn = MockSpawn([4])
 | |
|                             manager.PROC_DIR = proc_dir
 | |
|                             server.spawn = mock_spawn
 | |
|                             expected = {
 | |
|                                 4: conf4,
 | |
|                             }
 | |
|                             self.assertEqual(server.launch(number=4),
 | |
|                                              expected)
 | |
|                             self.assertEqual(mock_spawn.conf_files, [conf4])
 | |
|                             expected = {
 | |
|                                 'number': 4
 | |
|                             }
 | |
|                             self.assertEqual(mock_spawn.kwargs, [expected])
 | |
|                         # test cmd does not exist
 | |
|                         server = manager.Server('auth')
 | |
|                         with temptree([], []) as proc_dir:
 | |
|                             manager.PROC_DIR = proc_dir
 | |
|                             mock_spawn = MockSpawn([OSError(errno.ENOENT,
 | |
|                                                             'blah')])
 | |
|                             server.spawn = mock_spawn
 | |
|                             self.assertEqual(server.launch(), {})
 | |
|                             self.assertTrue(
 | |
|                                 'swift-auth-server does not exist' in
 | |
|                                 pop_stream(f))
 | |
|                 finally:
 | |
|                     sys.stdout = old_stdout
 | |
| 
 | |
|     def test_stop(self):
 | |
|         conf_files = (
 | |
|             'account-server/1.conf',
 | |
|             'account-server/2.conf',
 | |
|             'account-server/3.conf',
 | |
|             'account-server/4.conf',
 | |
|         )
 | |
|         pid_files = (
 | |
|             ('account-reaper/1.pid', 1),
 | |
|             ('account-reaper/2.pid', 2),
 | |
|             ('account-reaper/3.pid', 3),
 | |
|             ('account-reaper/4.pid', 4),
 | |
|         )
 | |
| 
 | |
|         with temptree(conf_files) as swift_dir:
 | |
|             manager.SWIFT_DIR = swift_dir
 | |
|             files, pids = zip(*pid_files)
 | |
|             with temptree(files, pids) as t:
 | |
|                 manager.RUN_DIR = t
 | |
|                 # start all pids in mock os
 | |
|                 manager.os = MockOs(pids)
 | |
|                 server = manager.Server('account-reaper', run_dir=t)
 | |
|                 # test kill all running pids
 | |
|                 pids = server.stop()
 | |
|                 self.assertEqual(len(pids), 4)
 | |
|                 for pid in (1, 2, 3, 4):
 | |
|                     self.assertTrue(pid in pids)
 | |
|                     self.assertEqual(manager.os.pid_sigs[pid],
 | |
|                                      [signal.SIGTERM])
 | |
|                 conf1 = self.join_swift_dir('account-reaper/1.conf')
 | |
|                 conf2 = self.join_swift_dir('account-reaper/2.conf')
 | |
|                 conf3 = self.join_swift_dir('account-reaper/3.conf')
 | |
|                 conf4 = self.join_swift_dir('account-reaper/4.conf')
 | |
|                 # reset mock os with only 2 running pids
 | |
|                 manager.os = MockOs([3, 4])
 | |
|                 pids = server.stop()
 | |
|                 self.assertEqual(len(pids), 2)
 | |
|                 for pid in (3, 4):
 | |
|                     self.assertTrue(pid in pids)
 | |
|                     self.assertEqual(manager.os.pid_sigs[pid],
 | |
|                                      [signal.SIGTERM])
 | |
|                 self.assertFalse(os.path.exists(conf1))
 | |
|                 self.assertFalse(os.path.exists(conf2))
 | |
|                 # test number kwarg
 | |
|                 manager.os = MockOs([3, 4])
 | |
|                 pids = server.stop(number=3)
 | |
|                 self.assertEqual(len(pids), 1)
 | |
|                 expected = {
 | |
|                     3: conf3,
 | |
|                 }
 | |
|                 self.assertTrue(pids, expected)
 | |
|                 self.assertEqual(manager.os.pid_sigs[3], [signal.SIGTERM])
 | |
|                 self.assertFalse(os.path.exists(conf4))
 | |
|                 self.assertFalse(os.path.exists(conf3))
 | |
| 
 | |
| 
 | |
| class TestManager(unittest.TestCase):
 | |
| 
 | |
|     @mock.patch.object(manager, 'verify_server',
 | |
|                        side_effect=lambda server: 'error' not in server)
 | |
|     def test_create(self, mock_verify):
 | |
|         m = manager.Manager(['test'])
 | |
|         self.assertEqual(len(m.servers), 1)
 | |
|         server = m.servers.pop()
 | |
|         self.assertTrue(isinstance(server, manager.Server))
 | |
|         self.assertEqual(server.server, 'test-server')
 | |
|         # test multi-server and simple dedupe
 | |
|         servers = ['object-replicator', 'object-auditor',
 | |
|                    'object-replicator']
 | |
|         m = manager.Manager(servers)
 | |
|         self.assertEqual(len(m.servers), 2)
 | |
|         for server in m.servers:
 | |
|             self.assertTrue(server.server in servers)
 | |
|         # test all
 | |
|         m = manager.Manager(['all'])
 | |
|         self.assertEqual(len(m.servers), len(manager.ALL_SERVERS))
 | |
|         for server in m.servers:
 | |
|             self.assertTrue(server.server in manager.ALL_SERVERS)
 | |
|         # test main
 | |
|         m = manager.Manager(['main'])
 | |
|         self.assertEqual(len(m.servers), len(manager.MAIN_SERVERS))
 | |
|         for server in m.servers:
 | |
|             self.assertTrue(server.server in manager.MAIN_SERVERS)
 | |
|         # test rest
 | |
|         m = manager.Manager(['rest'])
 | |
|         self.assertEqual(len(m.servers), len(manager.REST_SERVERS))
 | |
|         for server in m.servers:
 | |
|             self.assertTrue(server.server in manager.REST_SERVERS)
 | |
|         # test main + rest == all
 | |
|         m = manager.Manager(['main', 'rest'])
 | |
|         self.assertEqual(len(m.servers), len(manager.ALL_SERVERS))
 | |
|         for server in m.servers:
 | |
|             self.assertTrue(server.server in manager.ALL_SERVERS)
 | |
|         # test dedupe
 | |
|         m = manager.Manager(['main', 'rest', 'proxy', 'object',
 | |
|                              'container', 'account'])
 | |
|         self.assertEqual(len(m.servers), len(manager.ALL_SERVERS))
 | |
|         for server in m.servers:
 | |
|             self.assertTrue(server.server in manager.ALL_SERVERS)
 | |
|         # test glob
 | |
|         m = manager.Manager(['object-*'])
 | |
|         object_servers = [s for s in manager.ALL_SERVERS if
 | |
|                           s.startswith('object')]
 | |
|         self.assertEqual(len(m.servers), len(object_servers))
 | |
|         for s in m.servers:
 | |
|             self.assertTrue(str(s) in object_servers)
 | |
|         m = manager.Manager(['*-replicator'])
 | |
|         replicators = [s for s in manager.ALL_SERVERS if
 | |
|                        s.endswith('replicator')]
 | |
|         for s in m.servers:
 | |
|             self.assertTrue(str(s) in replicators)
 | |
| 
 | |
|         # test invalid server
 | |
|         m = manager.Manager(['error'])
 | |
|         self.assertEqual(len(m.servers), 0)
 | |
|         # test valid + invalid server
 | |
|         servers = ['object-server']
 | |
|         m = manager.Manager(['object', 'error'])
 | |
|         self.assertEqual(len(m.servers), 1)
 | |
|         for server in m.servers:
 | |
|             self.assertTrue(server.server in servers)
 | |
|         # test multi-server and invalid server together
 | |
|         servers = ['object-replicator', 'object-auditor', 'error']
 | |
|         m = manager.Manager(servers)
 | |
|         self.assertEqual(len(m.servers), 2)
 | |
|         for server in m.servers:
 | |
|             self.assertTrue(server.server in servers[:2])
 | |
| 
 | |
|     def test_iter(self):
 | |
|         with mock.patch.object(manager, 'find_executable', lambda x: x):
 | |
|             m = manager.Manager(['all'])
 | |
|             self.assertEqual(len(list(m)), len(manager.ALL_SERVERS))
 | |
|             for server in m:
 | |
|                 self.assertTrue(server.server in manager.ALL_SERVERS)
 | |
| 
 | |
|     def test_default_strict(self):
 | |
|         # test default strict
 | |
|         m = manager.Manager(['proxy'])
 | |
|         self.assertEqual(m._default_strict, True)
 | |
|         # aliases
 | |
|         m = manager.Manager(['main'])
 | |
|         self.assertEqual(m._default_strict, False)
 | |
|         m = manager.Manager(['proxy*'])
 | |
|         self.assertEqual(m._default_strict, False)
 | |
| 
 | |
|     def test_status(self):
 | |
|         class MockServer(object):
 | |
| 
 | |
|             def __init__(self, server, run_dir=manager.RUN_DIR):
 | |
|                 self.server = server
 | |
|                 self.called_kwargs = []
 | |
| 
 | |
|             def status(self, **kwargs):
 | |
|                 self.called_kwargs.append(kwargs)
 | |
|                 if 'error' in self.server:
 | |
|                     return 1
 | |
|                 else:
 | |
|                     return 0
 | |
| 
 | |
|         def mock_verify_server(server):
 | |
|             if 'error' in server:
 | |
|                 return False
 | |
|             return True
 | |
| 
 | |
|         old_verify_server = manager.verify_server
 | |
|         old_server_class = manager.Server
 | |
| 
 | |
|         try:
 | |
|             manager.verify_server = mock_verify_server
 | |
|             manager.Server = MockServer
 | |
|             m = manager.Manager(['test'])
 | |
|             status = m.status()
 | |
|             self.assertEqual(status, 0)
 | |
|             m = manager.Manager(['error'])
 | |
|             status = m.status()
 | |
|             self.assertEqual(status, 1)
 | |
|             # test multi-server
 | |
|             m = manager.Manager(['test', 'error'])
 | |
|             kwargs = {'key': 'value'}
 | |
|             status = m.status(**kwargs)
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called_kwargs, [kwargs])
 | |
|         finally:
 | |
|             manager.verify_server = old_verify_server
 | |
|             manager.Server = old_server_class
 | |
| 
 | |
|     def test_start(self):
 | |
|         def mock_setup_env():
 | |
|             getattr(mock_setup_env, 'called', []).append(True)
 | |
| 
 | |
|         def mock_verify_server(server):
 | |
|             if 'none' in server:
 | |
|                 return False
 | |
|             return True
 | |
| 
 | |
|         class MockServer(object):
 | |
|             def __init__(self, server, run_dir=manager.RUN_DIR):
 | |
|                 self.server = server
 | |
|                 self.called = defaultdict(list)
 | |
| 
 | |
|             def launch(self, **kwargs):
 | |
|                 self.called['launch'].append(kwargs)
 | |
|                 if 'noconfig' in self.server:
 | |
|                     return {}
 | |
|                 elif 'somerunning' in self.server:
 | |
|                     return {}
 | |
|                 else:
 | |
|                     return {1: self.server[0]}
 | |
| 
 | |
|             def wait(self, **kwargs):
 | |
|                 self.called['wait'].append(kwargs)
 | |
|                 return int('error' in self.server)
 | |
| 
 | |
|             def stop(self, **kwargs):
 | |
|                 self.called['stop'].append(kwargs)
 | |
| 
 | |
|             def interact(self, **kwargs):
 | |
|                 self.called['interact'].append(kwargs)
 | |
|                 if 'raise' in self.server:
 | |
|                     raise KeyboardInterrupt
 | |
|                 elif 'error' in self.server:
 | |
|                     return 1
 | |
|                 else:
 | |
|                     return 0
 | |
| 
 | |
|         old_setup_env = manager.setup_env
 | |
|         old_verify_server = manager.verify_server
 | |
|         old_swift_server = manager.Server
 | |
|         try:
 | |
|             manager.setup_env = mock_setup_env
 | |
|             manager.verify_server = mock_verify_server
 | |
|             manager.Server = MockServer
 | |
| 
 | |
|             # test no errors on launch
 | |
|             m = manager.Manager(['proxy'])
 | |
|             status = m.start()
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{}])
 | |
| 
 | |
|             # test error on launch
 | |
|             m = manager.Manager(['proxy', 'error'])
 | |
|             status = m.start()
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{}])
 | |
|                 self.assertEqual(server.called['wait'], [{}])
 | |
| 
 | |
|             # test missing (on launch, as it happens)
 | |
|             # We only throw a bad error code if nothing good was run.
 | |
|             m = manager.Manager(['none'])
 | |
|             status = m.start()
 | |
|             self.assertEqual(status, 1)
 | |
|             m = manager.Manager(['proxy', 'none'])
 | |
|             status = m.start()
 | |
|             self.assertEqual(status, 0)
 | |
| 
 | |
|             # test interact
 | |
|             m = manager.Manager(['proxy', 'error'])
 | |
|             kwargs = {'daemon': False}
 | |
|             status = m.start(**kwargs)
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [kwargs])
 | |
|                 self.assertEqual(server.called['interact'], [kwargs])
 | |
|             m = manager.Manager(['raise'])
 | |
|             kwargs = {'daemon': False}
 | |
|             status = m.start(**kwargs)
 | |
| 
 | |
|             # test no config
 | |
|             m = manager.Manager(['proxy', 'noconfig'])
 | |
|             status = m.start()
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{}])
 | |
|                 self.assertEqual(server.called['wait'], [{}])
 | |
| 
 | |
|             # test no config with --non-strict
 | |
|             m = manager.Manager(['proxy', 'noconfig'])
 | |
|             status = m.start(strict=False)
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{'strict': False}])
 | |
|                 self.assertEqual(server.called['wait'], [{'strict': False}])
 | |
| 
 | |
|             # test no config --strict
 | |
|             m = manager.Manager(['proxy', 'noconfig'])
 | |
|             status = m.start(strict=True)
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{'strict': True}])
 | |
|                 self.assertEqual(server.called['wait'], [{'strict': True}])
 | |
| 
 | |
|             # test no config with alias
 | |
|             m = manager.Manager(['main', 'noconfig'])
 | |
|             status = m.start()
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{}])
 | |
|                 self.assertEqual(server.called['wait'], [{}])
 | |
| 
 | |
|             # test no config with alias and --non-strict
 | |
|             m = manager.Manager(['main', 'noconfig'])
 | |
|             status = m.start(strict=False)
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{'strict': False}])
 | |
|                 self.assertEqual(server.called['wait'], [{'strict': False}])
 | |
| 
 | |
|             # test no config with alias and --strict
 | |
|             m = manager.Manager(['main', 'noconfig'])
 | |
|             status = m.start(strict=True)
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{'strict': True}])
 | |
|                 self.assertEqual(server.called['wait'], [{'strict': True}])
 | |
| 
 | |
|             # test already all running
 | |
|             m = manager.Manager(['proxy', 'somerunning'])
 | |
|             status = m.start()
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{}])
 | |
|                 self.assertEqual(server.called['wait'], [{}])
 | |
| 
 | |
|             # test already all running --non-strict
 | |
|             m = manager.Manager(['proxy', 'somerunning'])
 | |
|             status = m.start(strict=False)
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{'strict': False}])
 | |
|                 self.assertEqual(server.called['wait'], [{'strict': False}])
 | |
| 
 | |
|             # test already all running --strict
 | |
|             m = manager.Manager(['proxy', 'somerunning'])
 | |
|             status = m.start(strict=True)
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{'strict': True}])
 | |
|                 self.assertEqual(server.called['wait'], [{'strict': True}])
 | |
| 
 | |
|             # test already all running with alias
 | |
|             m = manager.Manager(['main', 'somerunning'])
 | |
|             status = m.start()
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{}])
 | |
|                 self.assertEqual(server.called['wait'], [{}])
 | |
| 
 | |
|             # test already all running with alias and --non-strict
 | |
|             m = manager.Manager(['main', 'somerunning'])
 | |
|             status = m.start(strict=False)
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{'strict': False}])
 | |
|                 self.assertEqual(server.called['wait'], [{'strict': False}])
 | |
| 
 | |
|             # test already all running with alias and --strict
 | |
|             m = manager.Manager(['main', 'somerunning'])
 | |
|             status = m.start(strict=True)
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in m.servers:
 | |
|                 self.assertEqual(server.called['launch'], [{'strict': True}])
 | |
|                 self.assertEqual(server.called['wait'], [{'strict': True}])
 | |
| 
 | |
|         finally:
 | |
|             manager.setup_env = old_setup_env
 | |
|             manager.verify_server = old_verify_server
 | |
|             manager.Server = old_swift_server
 | |
| 
 | |
|     def test_no_wait(self):
 | |
|         def mock_verify_server(server):
 | |
|             if 'error' in server:
 | |
|                 return False
 | |
|             return True
 | |
| 
 | |
|         class MockServer(object):
 | |
|             def __init__(self, server, run_dir=manager.RUN_DIR):
 | |
|                 self.server = server
 | |
|                 self.called = defaultdict(list)
 | |
| 
 | |
|             def launch(self, **kwargs):
 | |
|                 self.called['launch'].append(kwargs)
 | |
|                 # must return non-empty dict if launch succeeded
 | |
|                 return {1: self.server[0]}
 | |
| 
 | |
|             def wait(self, **kwargs):
 | |
|                 self.called['wait'].append(kwargs)
 | |
|                 return int('error' in self.server)
 | |
| 
 | |
|         orig_verify_server = manager.verify_server
 | |
|         orig_swift_server = manager.Server
 | |
|         try:
 | |
|             manager.verify_server = mock_verify_server
 | |
|             manager.Server = MockServer
 | |
|             # test success
 | |
|             init = manager.Manager(['proxy'])
 | |
|             status = init.no_wait()
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in init.servers:
 | |
|                 self.assertEqual(len(server.called['launch']), 1)
 | |
|                 called_kwargs = server.called['launch'][0]
 | |
|                 self.assertFalse(called_kwargs['wait'])
 | |
|                 self.assertFalse(server.called['wait'])
 | |
|             # test no errocode status even on invalid
 | |
|             init = manager.Manager(['invalid'])
 | |
|             status = init.no_wait()
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in init.servers:
 | |
|                 self.assertEqual(len(server.called['launch']), 1)
 | |
|                 called_kwargs = server.called['launch'][0]
 | |
|                 self.assertTrue('wait' in called_kwargs)
 | |
|                 self.assertFalse(called_kwargs['wait'])
 | |
|                 self.assertFalse(server.called['wait'])
 | |
|             # test wait with once option
 | |
|             init = manager.Manager(['updater', 'replicator-invalid'])
 | |
|             status = init.no_wait(once=True)
 | |
|             self.assertEqual(status, 0)
 | |
|             for server in init.servers:
 | |
|                 self.assertEqual(len(server.called['launch']), 1)
 | |
|                 called_kwargs = server.called['launch'][0]
 | |
|                 self.assertTrue('wait' in called_kwargs)
 | |
|                 self.assertFalse(called_kwargs['wait'])
 | |
|                 self.assertTrue('once' in called_kwargs)
 | |
|                 self.assertTrue(called_kwargs['once'])
 | |
|                 self.assertFalse(server.called['wait'])
 | |
|         finally:
 | |
|             manager.verify_server = orig_verify_server
 | |
|             manager.Server = orig_swift_server
 | |
| 
 | |
|     def test_no_daemon(self):
 | |
|         def mock_verify_server(server):
 | |
|             return True
 | |
| 
 | |
|         class MockServer(object):
 | |
| 
 | |
|             def __init__(self, server, run_dir=manager.RUN_DIR):
 | |
|                 self.server = server
 | |
|                 self.called = defaultdict(list)
 | |
| 
 | |
|             def launch(self, **kwargs):
 | |
|                 self.called['launch'].append(kwargs)
 | |
|                 # must return non-empty dict if launch succeeded
 | |
|                 return {1: self.server[0]}
 | |
| 
 | |
|             def interact(self, **kwargs):
 | |
|                 self.called['interact'].append(kwargs)
 | |
|                 return int('error' in self.server)
 | |
| 
 | |
|         orig_verify_server = manager.verify_server
 | |
|         orig_swift_server = manager.Server
 | |
|         try:
 | |
|             manager.Server = MockServer
 | |
|             manager.verify_server = mock_verify_server
 | |
|             # test success
 | |
|             init = manager.Manager(['proxy'])
 | |
|             stats = init.no_daemon()
 | |
|             self.assertEqual(stats, 0)
 | |
|             # test error
 | |
|             init = manager.Manager(['proxy', 'object-error'])
 | |
|             stats = init.no_daemon()
 | |
|             self.assertEqual(stats, 1)
 | |
|             # test once
 | |
|             init = manager.Manager(['proxy', 'object-error'])
 | |
|             stats = init.no_daemon()
 | |
|             for server in init.servers:
 | |
|                 self.assertEqual(len(server.called['launch']), 1)
 | |
|                 self.assertEqual(len(server.called['wait']), 0)
 | |
|                 self.assertEqual(len(server.called['interact']), 1)
 | |
|         finally:
 | |
|             manager.verify_server = orig_verify_server
 | |
|             manager.Server = orig_swift_server
 | |
| 
 | |
|     def test_once(self):
 | |
|         def mock_verify_server(server):
 | |
|             if 'error' in server:
 | |
|                 return False
 | |
|             return True
 | |
| 
 | |
|         class MockServer(object):
 | |
| 
 | |
|             def __init__(self, server, run_dir=manager.RUN_DIR):
 | |
|                 self.server = server
 | |
|                 self.called = defaultdict(list)
 | |
| 
 | |
|             def wait(self, **kwargs):
 | |
|                 self.called['wait'].append(kwargs)
 | |
|                 if 'error' in self.server:
 | |
|                     return 1
 | |
|                 else:
 | |
|                     return 0
 | |
| 
 | |
|             def launch(self, **kwargs):
 | |
|                 self.called['launch'].append(kwargs)
 | |
|                 return {1: 'account-reaper'}
 | |
| 
 | |
|         orig_verify_server = manager.verify_server
 | |
|         orig_swift_server = manager.Server
 | |
|         try:
 | |
|             manager.Server = MockServer
 | |
|             manager.verify_server = mock_verify_server
 | |
|             # test no errors
 | |
|             init = manager.Manager(['account-reaper'])
 | |
|             status = init.once()
 | |
|             self.assertEqual(status, 0)
 | |
|             # test error code on error
 | |
|             init = manager.Manager(['error'])
 | |
|             status = init.once()
 | |
|             self.assertEqual(status, 1)
 | |
|             for server in init.servers:
 | |
|                 self.assertEqual(len(server.called['launch']), 1)
 | |
|                 called_kwargs = server.called['launch'][0]
 | |
|                 self.assertEqual(called_kwargs, {'once': True})
 | |
|                 self.assertEqual(len(server.called['wait']), 1)
 | |
|                 self.assertEqual(len(server.called['interact']), 0)
 | |
|         finally:
 | |
|             manager.Server = orig_swift_server
 | |
|             manager.verify_server = orig_verify_server
 | |
| 
 | |
|     def test_stop(self):
 | |
|         def mock_verify_server(server):
 | |
|             if 'error' in server:
 | |
|                 return False
 | |
|             return True
 | |
| 
 | |
|         class MockServerFactory(object):
 | |
|             class MockServer(object):
 | |
|                 def __init__(self, pids, run_dir=manager.RUN_DIR):
 | |
|                     self.pids = pids
 | |
| 
 | |
|                 def stop(self, **kwargs):
 | |
|                     return self.pids
 | |
| 
 | |
|                 def status(self, **kwargs):
 | |
|                     return not self.pids
 | |
| 
 | |
|             def __init__(self, server_pids, run_dir=manager.RUN_DIR):
 | |
|                 self.server_pids = server_pids
 | |
| 
 | |
|             def __call__(self, server, run_dir=manager.RUN_DIR):
 | |
|                 return MockServerFactory.MockServer(self.server_pids[server])
 | |
| 
 | |
|         def mock_watch_server_pids(server_pids, **kwargs):
 | |
|             for server, pids in server_pids.items():
 | |
|                 for pid in pids:
 | |
|                     if pid is None:
 | |
|                         continue
 | |
|                     yield server, pid
 | |
| 
 | |
|         def mock_kill_group(pid, sig):
 | |
|             self.fail('kill_group should not be called')
 | |
| 
 | |
|         _orig_verify_server = manager.verify_server
 | |
|         _orig_server = manager.Server
 | |
|         _orig_watch_server_pids = manager.watch_server_pids
 | |
|         _orig_kill_group = manager.kill_group
 | |
|         try:
 | |
|             manager.watch_server_pids = mock_watch_server_pids
 | |
|             manager.kill_group = mock_kill_group
 | |
|             manager.verify_server = mock_verify_server
 | |
|             # test stop one server
 | |
|             server_pids = {
 | |
|                 'test': {1: "dummy.pid"}
 | |
|             }
 | |
|             manager.Server = MockServerFactory(server_pids)
 | |
|             m = manager.Manager(['test'])
 | |
|             status = m.stop()
 | |
|             self.assertEqual(status, 0)
 | |
|             # test not running
 | |
|             server_pids = {
 | |
|                 'test': {}
 | |
|             }
 | |
|             manager.Server = MockServerFactory(server_pids)
 | |
|             m = manager.Manager(['test'])
 | |
|             status = m.stop()
 | |
|             self.assertEqual(status, 1)
 | |
|             # test kill not running
 | |
|             server_pids = {
 | |
|                 'test': {}
 | |
|             }
 | |
|             manager.Server = MockServerFactory(server_pids)
 | |
|             m = manager.Manager(['test'])
 | |
|             status = m.kill()
 | |
|             self.assertEqual(status, 0)
 | |
|             # test won't die
 | |
|             server_pids = {
 | |
|                 'test': {None: None}
 | |
|             }
 | |
|             manager.Server = MockServerFactory(server_pids)
 | |
|             m = manager.Manager(['test'])
 | |
|             status = m.stop()
 | |
|             self.assertEqual(status, 1)
 | |
| 
 | |
|         finally:
 | |
|             manager.verify_server = _orig_verify_server
 | |
|             manager.Server = _orig_server
 | |
|             manager.watch_server_pids = _orig_watch_server_pids
 | |
|             manager.kill_group = _orig_kill_group
 | |
| 
 | |
|     def test_stop_kill_after_timeout(self):
 | |
|         class MockServerFactory(object):
 | |
|             class MockServer(object):
 | |
|                 def __init__(self, pids, run_dir=manager.RUN_DIR):
 | |
|                     self.pids = pids
 | |
| 
 | |
|                 def stop(self, **kwargs):
 | |
|                     return self.pids
 | |
| 
 | |
|                 def status(self, **kwargs):
 | |
|                     return not self.pids
 | |
| 
 | |
|             def __init__(self, server_pids, run_dir=manager.RUN_DIR):
 | |
|                 self.server_pids = server_pids
 | |
| 
 | |
|             def __call__(self, server, run_dir=manager.RUN_DIR):
 | |
|                 return MockServerFactory.MockServer(self.server_pids[server])
 | |
| 
 | |
|         def mock_watch_server_pids(server_pids, **kwargs):
 | |
|             for server, pids in server_pids.items():
 | |
|                 for pid in pids:
 | |
|                     if pid is None:
 | |
|                         continue
 | |
|                     yield server, pid
 | |
| 
 | |
|         mock_kill_group_called = []
 | |
| 
 | |
|         def mock_kill_group(*args):
 | |
|             mock_kill_group_called.append(args)
 | |
| 
 | |
|         def mock_kill_group_oserr(*args):
 | |
|             raise OSError()
 | |
| 
 | |
|         def mock_kill_group_oserr_ESRCH(*args):
 | |
|             raise OSError(errno.ESRCH, 'No such process')
 | |
| 
 | |
|         def mock_verify_server(server):
 | |
|             if 'error' in server:
 | |
|                 return False
 | |
|             return True
 | |
| 
 | |
|         _orig_server = manager.Server
 | |
|         _orig_watch_server_pids = manager.watch_server_pids
 | |
|         _orig_kill_group = manager.kill_group
 | |
|         _orig_verify_server = manager.verify_server
 | |
|         try:
 | |
|             manager.watch_server_pids = mock_watch_server_pids
 | |
|             manager.kill_group = mock_kill_group
 | |
|             manager.verify_server = mock_verify_server
 | |
|             # test stop one server
 | |
|             server_pids = {
 | |
|                 'test': {None: None}
 | |
|             }
 | |
|             manager.Server = MockServerFactory(server_pids)
 | |
|             m = manager.Manager(['test'])
 | |
|             status = m.stop(kill_after_timeout=True)
 | |
|             self.assertEqual(status, 1)
 | |
|             self.assertEqual(mock_kill_group_called, [(None, 9)])
 | |
| 
 | |
|             manager.kill_group = mock_kill_group_oserr
 | |
|             # test stop one server - OSError
 | |
|             server_pids = {
 | |
|                 'test': {None: None}
 | |
|             }
 | |
|             manager.Server = MockServerFactory(server_pids)
 | |
|             m = manager.Manager(['test'])
 | |
|             with self.assertRaises(OSError):
 | |
|                 status = m.stop(kill_after_timeout=True)
 | |
| 
 | |
|             manager.kill_group = mock_kill_group_oserr_ESRCH
 | |
|             # test stop one server - OSError: No such process
 | |
|             server_pids = {
 | |
|                 'test': {None: None}
 | |
|             }
 | |
|             manager.Server = MockServerFactory(server_pids)
 | |
|             m = manager.Manager(['test'])
 | |
|             status = m.stop(kill_after_timeout=True)
 | |
|             self.assertEqual(status, 1)
 | |
|         finally:
 | |
|             manager.Server = _orig_server
 | |
|             manager.watch_server_pids = _orig_watch_server_pids
 | |
|             manager.kill_group = _orig_kill_group
 | |
|             manager.verify_server = _orig_verify_server
 | |
| 
 | |
|     @mock.patch.object(manager, 'verify_server',
 | |
|                        side_effect=lambda server: 'error' not in server)
 | |
|     def test_shutdown(self, mock_verify):
 | |
|         m = manager.Manager(['test'])
 | |
|         m.stop_was_called = False
 | |
| 
 | |
|         def mock_stop(*args, **kwargs):
 | |
|             m.stop_was_called = True
 | |
|             expected = {'graceful': True}
 | |
|             self.assertEqual(kwargs, expected)
 | |
|             return 0
 | |
|         m.stop = mock_stop
 | |
|         status = m.shutdown()
 | |
|         self.assertEqual(status, 0)
 | |
|         self.assertEqual(m.stop_was_called, True)
 | |
| 
 | |
|     @mock.patch.object(manager, 'verify_server',
 | |
|                        side_effect=lambda server: 'error' not in server)
 | |
|     def test_restart(self, mock_verify):
 | |
|         m = manager.Manager(['test'])
 | |
|         m.stop_was_called = False
 | |
| 
 | |
|         def mock_stop(*args, **kwargs):
 | |
|             m.stop_was_called = True
 | |
|             return 0
 | |
|         m.start_was_called = False
 | |
| 
 | |
|         def mock_start(*args, **kwargs):
 | |
|             m.start_was_called = True
 | |
|             return 0
 | |
|         m.stop = mock_stop
 | |
|         m.start = mock_start
 | |
|         status = m.restart()
 | |
|         self.assertEqual(status, 0)
 | |
|         self.assertEqual(m.stop_was_called, True)
 | |
|         self.assertEqual(m.start_was_called, True)
 | |
| 
 | |
|     def test_reload(self):
 | |
|         def do_test(graceful):
 | |
|             called = defaultdict(list)
 | |
| 
 | |
|             def stop(self, **kwargs):
 | |
|                 called[self].append(('stop', kwargs))
 | |
|                 return 0
 | |
| 
 | |
|             def start(self, **kwargs):
 | |
|                 called[self].append(('start', kwargs))
 | |
|                 return 0
 | |
| 
 | |
|             m = manager.Manager(['*-server'])
 | |
|             expected_servers = set([server.server for server in m.servers])
 | |
|             self.assertEqual(len(expected_servers), 4)
 | |
|             for server in expected_servers:
 | |
|                 self.assertIn(server, manager.GRACEFUL_SHUTDOWN_SERVERS)
 | |
| 
 | |
|             with mock.patch('swift.common.manager.Manager.start', start):
 | |
|                 with mock.patch('swift.common.manager.Manager.stop', stop):
 | |
|                     status = m.reload(graceful=graceful)
 | |
| 
 | |
|             self.assertEqual(status, 0)
 | |
|             self.assertEqual(4, len(called))
 | |
|             actual_servers = set()
 | |
|             for m, calls in called.items():
 | |
|                 self.assertEqual(calls, [('stop', {'graceful': True}),
 | |
|                                          ('start', {'graceful': True})])
 | |
|                 actual_servers.update([server.server for server in m.servers])
 | |
|             self.assertEqual(expected_servers, actual_servers)
 | |
| 
 | |
|         with mock.patch.object(manager, 'find_executable', lambda x: x):
 | |
|             do_test(graceful=True)
 | |
|             do_test(graceful=False)  # graceful is forced regardless
 | |
| 
 | |
|     @mock.patch.object(manager, 'verify_server',
 | |
|                        side_effect=lambda server: 'error' not in server)
 | |
|     def test_force_reload(self, mock_verify):
 | |
|         m = manager.Manager(['test'])
 | |
|         m.reload_was_called = False
 | |
| 
 | |
|         def mock_reload(*args, **kwargs):
 | |
|             m.reload_was_called = True
 | |
|             return 0
 | |
|         m.reload = mock_reload
 | |
|         status = m.force_reload()
 | |
|         self.assertEqual(status, 0)
 | |
|         self.assertEqual(m.reload_was_called, True)
 | |
| 
 | |
|     @mock.patch.object(manager, 'verify_server',
 | |
|                        side_effect=lambda server: 'error' not in server)
 | |
|     def test_get_command(self, mock_verify):
 | |
|         m = manager.Manager(['test'])
 | |
|         self.assertEqual(m.start, m.get_command('start'))
 | |
|         self.assertEqual(m.force_reload, m.get_command('force-reload'))
 | |
|         self.assertEqual(m.get_command('force-reload'),
 | |
|                          m.get_command('force_reload'))
 | |
|         self.assertRaises(manager.UnknownCommandError, m.get_command,
 | |
|                           'no_command')
 | |
|         self.assertRaises(manager.UnknownCommandError, m.get_command,
 | |
|                           '__init__')
 | |
| 
 | |
|     def test_list_commands(self):
 | |
|         for cmd, help in manager.Manager.list_commands():
 | |
|             method = getattr(manager.Manager, cmd.replace('-', '_'), None)
 | |
|             self.assertTrue(method, '%s is not a command' % cmd)
 | |
|             self.assertTrue(getattr(method, 'publicly_accessible', False))
 | |
|             self.assertEqual(method.__doc__.strip(), help)
 | |
| 
 | |
|     @mock.patch.object(manager, 'verify_server',
 | |
|                        side_effect=lambda server: 'error' not in server)
 | |
|     def test_run_command(self, mock_verify):
 | |
|         m = manager.Manager(['test'])
 | |
|         m.cmd_was_called = False
 | |
| 
 | |
|         def mock_cmd(*args, **kwargs):
 | |
|             m.cmd_was_called = True
 | |
|             expected = {'kw1': True, 'kw2': False}
 | |
|             self.assertEqual(kwargs, expected)
 | |
|             return 0
 | |
|         mock_cmd.publicly_accessible = True
 | |
|         m.mock_cmd = mock_cmd
 | |
|         kwargs = {'kw1': True, 'kw2': False}
 | |
|         status = m.run_command('mock_cmd', **kwargs)
 | |
|         self.assertEqual(status, 0)
 | |
|         self.assertEqual(m.cmd_was_called, True)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     unittest.main()
 |