def test_start(self, mock_frompidfile, mock_frompid, mock_popen): mock_frompidfile.return_value._is_postmaster_process.return_value = False mock_frompid.return_value = "proc 123" mock_popen.return_value.pid = 123 self.assertEqual(PostmasterProcess.start('true', '/tmp', '/tmp/test.conf', []), "proc 123") mock_frompid.assert_called_with(123) mock_frompidfile.side_effect = psutil.NoSuchProcess(123) self.assertEqual(PostmasterProcess.start('true', '/tmp', '/tmp/test.conf', []), "proc 123") mock_popen.side_effect = Exception self.assertIsNone(PostmasterProcess.start('true', '/tmp', '/tmp/test.conf', []))
def test_from_pidfile(self, mock_read, mock_init, mock_create_time): mock_init.side_effect = psutil.NoSuchProcess(123) mock_read.return_value = {} self.assertIsNone(PostmasterProcess.from_pidfile('')) mock_read.return_value = {"pid": "foo"} self.assertIsNone(PostmasterProcess.from_pidfile('')) mock_read.return_value = {"pid": "123"} self.assertIsNone(PostmasterProcess.from_pidfile('')) mock_init.side_effect = None with patch.object(psutil.Process, 'pid', 123), \ patch.object(psutil.Process, 'ppid', return_value=124), \ patch('os.getpid', return_value=125) as mock_ospid, \ patch('os.getppid', return_value=126): self.assertIsNotNone(PostmasterProcess.from_pidfile('')) mock_create_time.return_value = 100000 mock_read.return_value = {"pid": "123", "start_time": "200000"} self.assertIsNone(PostmasterProcess.from_pidfile('')) mock_read.return_value = {"pid": "123", "start_time": "foobar"} self.assertIsNotNone(PostmasterProcess.from_pidfile('')) mock_ospid.return_value = 123 mock_read.return_value = {"pid": "123", "start_time": "100000"} self.assertIsNone(PostmasterProcess.from_pidfile(''))
def test_signal_kill(self, mock_kill, mock_children, mock_suspend): proc = PostmasterProcess(123) # all processes successfully stopped mock_children.return_value = [Mock()] mock_children.return_value[0].kill.side_effect = psutil.NoSuchProcess( 123) self.assertTrue(proc.signal_kill()) # postmaster has gone before suspend mock_suspend.side_effect = psutil.NoSuchProcess(123) self.assertTrue(proc.signal_kill()) # postmaster has gone before we got a list of children mock_suspend.side_effect = psutil.AccessDenied() mock_children.side_effect = psutil.NoSuchProcess(123) self.assertTrue(proc.signal_kill()) # postmaster has gone after we got a list of children mock_children.side_effect = psutil.AccessDenied() mock_kill.side_effect = psutil.NoSuchProcess(123) self.assertTrue(proc.signal_kill()) # failed to kill postmaster mock_kill.side_effect = psutil.AccessDenied() self.assertFalse(proc.signal_kill())
def test_signal_stop(self, mock_send_signal): proc = PostmasterProcess(-123) self.assertEqual(proc.signal_stop('immediate'), False) mock_send_signal.side_effect = [None, psutil.NoSuchProcess(123), psutil.AccessDenied()] proc = PostmasterProcess(123) self.assertEqual(proc.signal_stop('immediate'), None) self.assertEqual(proc.signal_stop('immediate'), True) self.assertEqual(proc.signal_stop('immediate'), False)
def test_signal_stop_nt(self, mock_os): mock_os.configure_mock(name="nt") proc = PostmasterProcess(-123) self.assertEqual(proc.signal_stop('immediate'), False) proc = PostmasterProcess(123) self.assertEqual(proc.signal_stop('immediate'), None) self.assertEqual(proc.signal_stop('immediate'), False) self.assertEqual(proc.signal_stop('immediate'), True)
def is_running(self): """Returns PostmasterProcess if one is running on the data directory or None. If most recently seen process is running updates the cached process based on pid file.""" if self._postmaster_proc: if self._postmaster_proc.is_running(): return self._postmaster_proc self._postmaster_proc = None # we noticed that postgres was restarted, force syncing of replication self.slots_handler.schedule() self._postmaster_proc = PostmasterProcess.from_pidfile(self._data_dir) return self._postmaster_proc
def test_wait_for_user_backends_to_close(self, mock_wait): c1 = Mock() c1.cmdline = Mock(return_value=["postgres: startup process "]) c2 = Mock() c2.cmdline = Mock(return_value=["postgres: postgres postgres [local] idle"]) c3 = Mock() c3.cmdline = Mock(side_effect=psutil.NoSuchProcess(123)) with patch('psutil.Process.children', Mock(return_value=[c1, c2, c3])): proc = PostmasterProcess(123) self.assertIsNone(proc.wait_for_user_backends_to_close()) mock_wait.assert_called_with([c2]) with patch('psutil.Process.children', Mock(side_effect=psutil.NoSuchProcess(123))): proc = PostmasterProcess(123) self.assertIsNone(proc.wait_for_user_backends_to_close())
def start(self, timeout=None, task=None, block_callbacks=False, role=None): """Start PostgreSQL Waits for postmaster to open ports or terminate so pg_isready can be used to check startup completion or failure. :returns: True if start was initiated and postmaster ports are open, False if start failed""" # make sure we close all connections established against # the former node, otherwise, we might get a stalled one # after kill -9, which would report incorrect data to # patroni. self._connection.close() if self.is_running(): logger.error( 'Cannot start PostgreSQL because one is already running.') self.set_state('starting') return True if not block_callbacks: self.__cb_pending = ACTION_ON_START self.set_role(role or self.get_postgres_role_from_data_directory()) self.set_state('starting') self._pending_restart = False configuration = self.config.effective_configuration self.config.write_postgresql_conf(configuration) self.config.resolve_connection_addresses() self.config.replace_pg_hba() self.config.replace_pg_ident() options = [ '--{0}={1}'.format(p, configuration[p]) for p in self.config.CMDLINE_OPTIONS if p in configuration and p != 'wal_keep_segments' ] if self.cancellable.is_cancelled: return False with task or null_context(): if task and task.is_cancelled: logger.info("PostgreSQL start cancelled.") return False self._postmaster_proc = PostmasterProcess.start( self.pgcommand('postgres'), self._data_dir, self.config.postgresql_conf, options) if task: task.complete(self._postmaster_proc) start_timeout = timeout if not start_timeout: try: start_timeout = float(self.config.get('pg_ctl_timeout', 60)) except ValueError: start_timeout = 60 # We want postmaster to open ports before we continue if not self._postmaster_proc or not self.wait_for_port_open( self._postmaster_proc, start_timeout): return False ret = self.wait_for_startup(start_timeout) if ret is not None: return ret elif timeout is not None: return False else: return None
def test_from_pid(self, mock_init): mock_init.side_effect = psutil.NoSuchProcess(123) self.assertEqual(PostmasterProcess.from_pid(123), None) mock_init.side_effect = None self.assertNotEqual(PostmasterProcess.from_pid(123), None)
def test_init(self): proc = PostmasterProcess(-123) self.assertTrue(proc.is_single_user)
def test_read_postmaster_pidfile(self): with patch.object(builtins, 'open', Mock(side_effect=IOError)): self.assertIsNone(PostmasterProcess.from_pidfile('')) with patch.object(builtins, 'open', mock_open(read_data='123\n')): self.assertIsNone(PostmasterProcess.from_pidfile(''))