Browse Source

remove test_multiprocess_api

This test suite should be removed for the following reasons.

1) it's not a unit test

2) it's failing randomly, a lot, and depends on timing of the host for
process start and signal handling which are provably not predicable on
slower machines

3) it's triggering testr bugs in the ways that it fails which means we
don't actually get any subunit in the fail scenario, which makes it
actually impossible to move forward on fixes.

Conflicts:
	nova/tests/integrated/test_multiprocess_api.py

Change-Id: Ieb7c02115c12cd9f6c9fa67691a643aed7632784
Closes-Bug: #1357578
(cherry picked from commit f3c99ba1ef)
tags/2014.1.3
Sean Dague 5 years ago
parent
commit
4e6371b82a
1 changed files with 0 additions and 213 deletions
  1. 0
    213
      nova/tests/integrated/test_multiprocess_api.py

+ 0
- 213
nova/tests/integrated/test_multiprocess_api.py View File

@@ -1,213 +0,0 @@
1
-# Copyright (c) 2012 Intel, LLC
2
-# Copyright (c) 2012 OpenStack Foundation
3
-#
4
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
5
-#    not use this file except in compliance with the License. You may obtain
6
-#    a copy of the License at
7
-#
8
-#         http://www.apache.org/licenses/LICENSE-2.0
9
-#
10
-#    Unless required by applicable law or agreed to in writing, software
11
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
-#    License for the specific language governing permissions and limitations
14
-#    under the License.
15
-
16
-"""
17
-Test multiprocess enabled API service.
18
-"""
19
-import errno
20
-import fixtures
21
-import os
22
-import signal
23
-import time
24
-import traceback
25
-
26
-from nova.openstack.common import log as logging
27
-from nova import service
28
-from nova.tests.integrated.api import client
29
-from nova.tests.integrated import integrated_helpers
30
-
31
-LOG = logging.getLogger(__name__)
32
-
33
-
34
-class MultiprocessWSGITest(integrated_helpers._IntegratedTestBase):
35
-    _api_version = 'v2'
36
-
37
-    def _start_api_service(self):
38
-        # Process will be started in _spawn()
39
-        self.osapi = service.WSGIService("osapi_compute")
40
-        self.auth_url = 'http://%(host)s:%(port)s/%(api_version)s' % ({
41
-            'host': self.osapi.host, 'port': self.osapi.port,
42
-            'api_version': self._api_version})
43
-        LOG.info('auth_url = %s' % self.auth_url)
44
-
45
-    def _get_flags(self):
46
-        self.workers = 2
47
-        f = super(MultiprocessWSGITest, self)._get_flags()
48
-        f['osapi_compute_workers'] = self.workers
49
-        return f
50
-
51
-    def _spawn(self):
52
-        pid = os.fork()
53
-        if pid == 0:
54
-            # NOTE(johannes): We can't let the child processes exit back
55
-            # into the unit test framework since then we'll have multiple
56
-            # processes running the same tests (and possibly forking more
57
-            # processes that end up in the same situation). So we need
58
-            # to catch all exceptions and make sure nothing leaks out, in
59
-            # particlar SystemExit, which is raised by sys.exit(). We use
60
-            # os._exit() which doesn't have this problem.
61
-            status = 0
62
-            try:
63
-                launcher = service.process_launcher()
64
-                launcher.launch_service(self.osapi, workers=self.osapi.workers)
65
-                launcher.wait()
66
-            except SystemExit as exc:
67
-                status = exc.code
68
-            except BaseException:
69
-                # We need to be defensive here too
70
-                try:
71
-                    traceback.print_exc()
72
-                except BaseException:
73
-                    LOG.error("Couldn't print traceback")
74
-                status = 2
75
-
76
-            # Really exit
77
-            os._exit(status)
78
-
79
-        self.pid = pid
80
-
81
-        # Wait at most 10 seconds to spawn workers
82
-        cond = lambda: self.workers == len(self._get_workers())
83
-        timeout = 10
84
-        self._wait(cond, timeout)
85
-
86
-        workers = self._get_workers()
87
-        self.assertEqual(len(workers), self.workers)
88
-        return workers
89
-
90
-    def _wait(self, cond, timeout):
91
-        start = time.time()
92
-        while True:
93
-            if cond():
94
-                break
95
-            if time.time() - start > timeout:
96
-                break
97
-            time.sleep(.1)
98
-
99
-    def tearDown(self):
100
-        if self.pid:
101
-            # Make sure all processes are stopped
102
-            os.kill(self.pid, signal.SIGTERM)
103
-
104
-            try:
105
-                # Make sure we reap our test process
106
-                self._reap_test()
107
-            except fixtures.TimeoutException:
108
-                # If the child gets stuck or is too slow in existing
109
-                # after receiving the SIGTERM, gracefully handle the
110
-                # timeout exception and try harder to kill it. We need
111
-                # to do this otherwise the child process can hold up
112
-                # the test run
113
-                os.kill(self.pid, signal.SIGKILL)
114
-
115
-        super(MultiprocessWSGITest, self).tearDown()
116
-
117
-    def _reap_test(self):
118
-        pid, status = os.waitpid(self.pid, 0)
119
-        self.pid = None
120
-        return status
121
-
122
-    def _get_workers(self):
123
-        # NOTE(hartsocks): use of ps checks the process table for child pid
124
-        # entries these processes may be ended but not reaped so ps may
125
-        # show processes that are still being cleaned out of the table.
126
-        f = os.popen('ps ax -o pid,ppid,command')
127
-        # Skip ps header
128
-        f.readline()
129
-
130
-        processes = [tuple(int(p) for p in l.strip().split()[:2])
131
-                     for l in f.readlines()]
132
-        return [p for p, pp in processes if pp == self.pid]
133
-
134
-    def wait_on_process_until_end(self, worker_pid):
135
-        # NOTE: the testing framework itself has a
136
-        # built in test timeout function so a test
137
-        # stuck in an infinite loop will eventually
138
-        # be killed by the test framework.
139
-        LOG.info('waiting on process %r to exit' % worker_pid)
140
-
141
-        while True:
142
-            # poll the process until it isn't there to poll
143
-            try:
144
-                os.kill(worker_pid, 0)
145
-                time.sleep(0.1)
146
-            except OSError as err:
147
-                # by watching specifically for errno.ESRCH
148
-                # we guarantee this loop continues until
149
-                # the process table has cleared the pid.
150
-                # Child process table entries hang around
151
-                # for several cycles in case a parent process
152
-                # needs to check their exit state.
153
-                if err.errno == errno.ESRCH:
154
-                    break
155
-        LOG.info('process %r has exited' % worker_pid)
156
-
157
-    def test_killed_worker_recover(self):
158
-        start_workers = self._spawn()
159
-
160
-        worker_pid = start_workers[0]
161
-        # kill one worker and check if new worker can come up
162
-        LOG.info('pid of first child is %s' % worker_pid)
163
-
164
-        # signal child
165
-        os.kill(worker_pid, signal.SIGTERM)
166
-
167
-        self.wait_on_process_until_end(worker_pid)
168
-
169
-        # Make sure worker pids don't match
170
-        end_workers = self._get_workers()
171
-        LOG.info('workers: %r' % end_workers)
172
-        self.assertNotEqual(start_workers, end_workers)
173
-
174
-        # check if api service still works
175
-        flavors = self.api.get_flavors()
176
-        self.assertTrue(len(flavors) > 0, 'Num of flavors > 0.')
177
-
178
-    def _terminate_with_signal(self, sig):
179
-        self._spawn()
180
-
181
-        # check if api service is working
182
-        flavors = self.api.get_flavors()
183
-        self.assertTrue(len(flavors) > 0, 'Num of flavors > 0.')
184
-
185
-        worker_pids = self._get_workers()
186
-
187
-        LOG.info("sent launcher_process pid: %r signal: %r" % (self.pid, sig))
188
-        os.kill(self.pid, sig)
189
-
190
-        # did you know the test framework has a timeout of its own?
191
-        # if a test takes too long, the test will be killed.
192
-        for pid in worker_pids:
193
-            self.wait_on_process_until_end(pid)
194
-
195
-        workers = self._get_workers()
196
-        self.assertFalse(workers, 'OS processes left %r' % workers)
197
-
198
-    def test_terminate_sigkill(self):
199
-        self._terminate_with_signal(signal.SIGKILL)
200
-        status = self._reap_test()
201
-        self.assertTrue(os.WIFSIGNALED(status))
202
-        self.assertEqual(os.WTERMSIG(status), signal.SIGKILL)
203
-
204
-    def test_terminate_sigterm(self):
205
-        self._terminate_with_signal(signal.SIGTERM)
206
-        status = self._reap_test()
207
-        self.assertTrue(os.WIFEXITED(status))
208
-        self.assertEqual(os.WEXITSTATUS(status), 0)
209
-
210
-
211
-class MultiprocessWSGITestV3(client.TestOpenStackClientV3Mixin,
212
-                             MultiprocessWSGITest):
213
-    _api_version = 'v3'

Loading…
Cancel
Save