~ubuntu-cloud-archive/ubuntu/precise/glance/folsom

« back to all changes in this revision

Viewing changes to glance/tests/functional/test_bin_glance_control.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Chuck Short, Soren Hansen
  • Date: 2012-09-07 12:17:46 UTC
  • mfrom: (1.1.42)
  • Revision ID: package-import@ubuntu.com-20120907121746-a4i0aewhlzb7vw31
Tags: 2012.2~rc1~20120907.129.f0bd856-0ubuntu1
[ Chuck Short ]
* New upstream version.
* drop debian/patches/fix-docs-build.patch. 
* debian/rules: Re-activate tests.
* debain/control: Add depends on python-swiftclient.
* debian/*.usptart: make glance start from runlevel 1 to runlevel
  2. (LP: #820688)

[ Soren Hansen ]
* Update debian/watch to account for symbolically named tarballs and
  use newer URL.
* New snapshot.
* Refresh disable-network-for-docs.patch
* Fix Launchpad URLs in debian/watch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2012 Red Hat, Inc
 
4
#
 
5
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
6
#    not use this file except in compliance with the License. You may obtain
 
7
#    a copy of the License at
 
8
#
 
9
#         http://www.apache.org/licenses/LICENSE-2.0
 
10
#
 
11
#    Unless required by applicable law or agreed to in writing, software
 
12
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
13
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
14
#    License for the specific language governing permissions and limitations
 
15
#    under the License.
 
16
 
 
17
"""Functional test case for the glance-control --respawn option """
 
18
 
 
19
import httplib2
 
20
import os
 
21
import signal
 
22
import socket
 
23
import sys
 
24
import time
 
25
 
 
26
from glance.tests import functional
 
27
from glance.tests.utils import skip_if_disabled
 
28
 
 
29
 
 
30
class TestGlanceControl(functional.FunctionalTest):
 
31
 
 
32
    """Functional test for glance-control"""
 
33
 
 
34
    def get_versions(self):
 
35
        path = "http://%s:%d" % ("127.0.0.1", self.api_port)
 
36
        http = httplib2.Http()
 
37
        response, content = http.request(path, 'GET')
 
38
        self.assertEqual(response.status, 300)
 
39
 
 
40
    def get_pid(self):
 
41
        return int(open(self.api_server.pid_file).read().strip())
 
42
 
 
43
    def kill_server(self):
 
44
        pid = self.get_pid()
 
45
        os.killpg(pid, signal.SIGKILL)
 
46
        return pid
 
47
 
 
48
    def wait_for(self, predicate):
 
49
        count = 0
 
50
        while count < 50:
 
51
            if predicate():
 
52
                break
 
53
            else:
 
54
                time.sleep(0.1)
 
55
                count += 1
 
56
        self.assertTrue(predicate())
 
57
 
 
58
    def connection_unavailable(self, type):
 
59
        try:
 
60
            self.get_versions()
 
61
            self.fail('%s server should not be respawned' % type)
 
62
        except socket.error:
 
63
            exc_value = sys.exc_info()[1]
 
64
            self.assertTrue('Connection refused' in exc_value or
 
65
                            'ECONNREFUSED' in exc_value)
 
66
 
 
67
    @skip_if_disabled
 
68
    def test_respawn(self):
 
69
        """
 
70
        We test that the '--respawn' option causes the API server
 
71
        to be respawned after death but not after a deliberate stop
 
72
        """
 
73
        self.cleanup()
 
74
        self.api_server.server_control_options += ' --respawn'
 
75
 
 
76
        # start API server, allowing glance-control to continue running
 
77
        self.start_with_retry(self.api_server,
 
78
                              'api_port',
 
79
                              3,
 
80
                              expect_launch=True,
 
81
                              expect_exit=False,
 
82
                              expect_confirmation=False,
 
83
                              **self.__dict__.copy())
 
84
 
 
85
        # ensure the service pid has been cached
 
86
        pid_cached = lambda: os.path.exists(self.api_server.pid_file)
 
87
        self.wait_for(pid_cached)
 
88
 
 
89
        # ensure glance-control has had a chance to waitpid on child
 
90
        time.sleep(1)
 
91
 
 
92
        # verify server health with version negotiation
 
93
        self.get_versions()
 
94
 
 
95
        # server is killed ungracefully
 
96
        old_pid = self.kill_server()
 
97
 
 
98
        # ... but should be respawned
 
99
 
 
100
        # wait for pid to cycle
 
101
        pid_changed = lambda: old_pid != self.get_pid()
 
102
        self.wait_for(pid_changed)
 
103
 
 
104
        # ensure API service port is re-activated
 
105
        launch_msg = self.wait_for_servers([self.api_server])
 
106
        self.assertTrue(launch_msg is None, launch_msg)
 
107
 
 
108
        # verify server health with version negotiation
 
109
        self.get_versions()
 
110
 
 
111
        # deliberately stop server, it should not be respawned
 
112
        proc_file = '/proc/%d' % self.get_pid()
 
113
        self.stop_server(self.api_server, 'API server')
 
114
 
 
115
        # ensure last server process has gone away
 
116
        process_died = lambda: not os.path.exists(proc_file)
 
117
        self.wait_for(process_died)
 
118
 
 
119
        # deliberately stopped server should not be respawned
 
120
        launch_msg = self.wait_for_servers([self.api_server], False)
 
121
        self.assertTrue(launch_msg is None, launch_msg)
 
122
 
 
123
        # ensure the server has not been respawned
 
124
        self.connection_unavailable('deliberately stopped')
 
125
 
 
126
    @skip_if_disabled
 
127
    def test_bouncing(self):
 
128
        """
 
129
        We test that the '--respawn' option doesn't cause bouncing
 
130
        API server to be respawned
 
131
        """
 
132
        self.cleanup()
 
133
        self.api_server.server_control_options += ' --respawn'
 
134
        self.api_server.default_store = 'shouldnotexist'
 
135
 
 
136
        exitcode, out, err = self.api_server.start(**self.__dict__.copy())
 
137
 
 
138
        # ensure the service pid has been cached
 
139
        pid_cached = lambda: os.path.exists(self.api_server.pid_file)
 
140
        self.wait_for(pid_cached)
 
141
 
 
142
        # ensure glance-control has had a chance to waitpid on child
 
143
        time.sleep(1)
 
144
 
 
145
        # bouncing server should not be respawned
 
146
        launch_msg = self.wait_for_servers([self.api_server], False)
 
147
        self.assertTrue(launch_msg is None, launch_msg)
 
148
 
 
149
        # ensure server process has gone away
 
150
        process_died = lambda: not os.path.exists('/proc/%d' % self.get_pid())
 
151
        self.wait_for(process_died)
 
152
 
 
153
        # ensure the server has not been respawned
 
154
        self.connection_unavailable('bouncing')
 
155
 
 
156
    @skip_if_disabled
 
157
    def test_reload(self):
 
158
        """Exercise `glance-control api reload`"""
 
159
        self.cleanup()
 
160
 
 
161
        # start API server, allowing glance-control to continue running
 
162
        self.start_with_retry(self.api_server,
 
163
                              'api_port',
 
164
                              3,
 
165
                              expect_launch=True,
 
166
                              expect_exit=False,
 
167
                              expect_confirmation=False,
 
168
                              **self.__dict__.copy())
 
169
 
 
170
        # ensure the service pid has been cached
 
171
        pid_cached = lambda: os.path.exists(self.api_server.pid_file)
 
172
        self.wait_for(pid_cached)
 
173
 
 
174
        # ensure glance-control has had a chance to waitpid on child
 
175
        time.sleep(1)
 
176
 
 
177
        # verify server health with version negotiation
 
178
        self.get_versions()
 
179
 
 
180
        self.reload_server(self.api_server, True)
 
181
 
 
182
        # ensure API service port is re-activated
 
183
        launch_msg = self.wait_for_servers([self.api_server])
 
184
        self.assertTrue(launch_msg is None, launch_msg)
 
185
 
 
186
        # verify server health with version negotiation
 
187
        self.get_versions()
 
188
 
 
189
        # deliberately stop server
 
190
        proc_file = '/proc/%d' % self.get_pid()
 
191
        self.stop_server(self.api_server, 'API server')
 
192
 
 
193
        # ensure last server process has gone away
 
194
        process_died = lambda: not os.path.exists(proc_file)
 
195
        self.wait_for(process_died)
 
196
 
 
197
        # deliberately stopped server should not be respawned
 
198
        launch_msg = self.wait_for_servers([self.api_server], False)
 
199
        self.assertTrue(launch_msg is None, launch_msg)
 
200
 
 
201
        # ensure the server has not been respawned
 
202
        self.connection_unavailable('deliberately stopped')