~ubuntu-branches/ubuntu/trusty/ceilometer/trusty-proposed

« back to all changes in this revision

Viewing changes to ceilometer/tests/test_service.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, James Page, Chuck Short
  • Date: 2014-01-23 15:08:11 UTC
  • mfrom: (1.1.11)
  • Revision ID: package-import@ubuntu.com-20140123150811-1zaismsuyh1hcl8y
Tags: 2014.1~b2-0ubuntu1
[ James Page ]
* d/control: Add python-jsonpath-rw to BD's.
* d/p/fix-setup-requirements.patch: Bump WebOb to support < 1.4.
 (LP: #1261101)

[ Chuck Short ]
* New upstream version.
* debian/control, debian/ceilometer-common.install: Split out
  ceilometer-alarm-evaluator and ceilometer-alarm-notifier into their
  own packages. (LP: #1250002)
* debian/ceilometer-agent-central.logrotate,
  debian/ceilometer-agent-compute.logrotate,
  debian/ceilometer-api.logrotate,
  debian/ceilometer-collector.logrotate: Add logrotate files, 
  thanks to Ahmed Rahal. (LP: #1224223)
* Fix typos in upstart files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# -*- encoding: utf-8 -*-
3
 
#
4
 
# Copyright © 2012 eNovance <licensing@enovance.com>
5
 
#
6
 
# Author: Julien Danjou <julien@danjou.info>
7
 
#
8
 
# Licensed under the Apache License, Version 2.0 (the "License"); you may
9
 
# not use this file except in compliance with the License. You may obtain
10
 
# a copy of the License at
11
 
#
12
 
#      http://www.apache.org/licenses/LICENSE-2.0
13
 
#
14
 
# Unless required by applicable law or agreed to in writing, software
15
 
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16
 
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17
 
# License for the specific language governing permissions and limitations
18
 
# under the License.
19
 
 
20
 
import os
21
 
import shutil
22
 
import signal
23
 
import subprocess
24
 
import threading
25
 
import time
26
 
 
27
 
import yaml
28
 
 
29
 
from ceilometer.openstack.common import fileutils
30
 
from ceilometer.openstack.common import test
31
 
from ceilometer import service
32
 
from ceilometer.tests import base
33
 
 
34
 
 
35
 
class ServiceTestCase(test.BaseTestCase):
36
 
    def test_prepare_service(self):
37
 
        service.prepare_service([])
38
 
 
39
 
 
40
 
#NOTE(Fengqian): I have to set up a thread to parse the ouput of
41
 
#subprocess.Popen. Because readline() may block the process in
42
 
#some conditions.
43
 
class ParseOutput(threading.Thread):
44
 
    def __init__(self, input_stream, str_flag):
45
 
        super(ParseOutput, self).__init__()
46
 
        self.input_stream = input_stream
47
 
        self.str_flag = str_flag
48
 
        self.ret_stream = None
49
 
        self.ret = False
50
 
        self.thread_stop = False
51
 
 
52
 
    def run(self):
53
 
        while not self.thread_stop:
54
 
            next_line = self.input_stream.readline()
55
 
            if next_line == '':
56
 
                break
57
 
            if self.str_flag in next_line:
58
 
                self.ret = True
59
 
                self.ret_stream = next_line[(next_line.find(self.str_flag) +
60
 
                                            len(self.str_flag)):]
61
 
                self.stop()
62
 
 
63
 
    def stop(self):
64
 
        self.thread_stop = True
65
 
 
66
 
 
67
 
class ServiceRestartTest(base.BaseTestCase):
68
 
 
69
 
    def setUp(self):
70
 
        super(ServiceRestartTest, self).setUp()
71
 
        self.pipeline_cfg_file = fileutils.write_to_tempfile(content='',
72
 
                                                             prefix='pipeline',
73
 
                                                             suffix='.yaml')
74
 
        shutil.copy(self.path_get('etc/ceilometer/pipeline.yaml'),
75
 
                    self.pipeline_cfg_file)
76
 
        self.pipelinecfg_read_from_file()
77
 
        policy_file = self.path_get('etc/ceilometer/policy.json')
78
 
        content = "[DEFAULT]\n"\
79
 
                  "rpc_backend=ceilometer.openstack.common.rpc.impl_fake\n"\
80
 
                  "auth_strategy=noauth\n"\
81
 
                  "debug=true\n"\
82
 
                  "pipeline_cfg_file={0}\n"\
83
 
                  "policy_file={1}\n"\
84
 
                  "[database]\n"\
85
 
                  "connection=log://localhost\n".format(self.pipeline_cfg_file,
86
 
                                                        policy_file)
87
 
 
88
 
        self.tempfile = fileutils.write_to_tempfile(content=content,
89
 
                                                    prefix='ceilometer',
90
 
                                                    suffix='.conf')
91
 
 
92
 
    def _modify_pipeline_file(self):
93
 
        with open(self.pipeline_cfg_file, 'w') as pipe_fd:
94
 
            pipe_fd.truncate()
95
 
            pipe_fd.write(yaml.safe_dump(self.pipeline_cfg[1]))
96
 
 
97
 
    def pipelinecfg_read_from_file(self):
98
 
        with open(self.pipeline_cfg_file) as fd:
99
 
            data = fd.read()
100
 
        self.pipeline_cfg = yaml.safe_load(data)
101
 
 
102
 
    def tearDown(self):
103
 
        super(ServiceRestartTest, self).tearDown()
104
 
        self.sub.kill()
105
 
        self.sub.wait()
106
 
        os.remove(self.pipeline_cfg_file)
107
 
        os.remove(self.tempfile)
108
 
 
109
 
    @staticmethod
110
 
    def _check_process_alive(pid):
111
 
        try:
112
 
            with open("/proc/%d/status" % pid) as fd_proc:
113
 
                for line in fd_proc.readlines():
114
 
                    if line.startswith("State:"):
115
 
                        state = line.split(":", 1)[1].strip().split(' ')[0]
116
 
                        return state not in ['Z', 'T', 'Z+']
117
 
        except IOError:
118
 
            return False
119
 
 
120
 
    def check_process_alive(self):
121
 
        cond = lambda: self._check_process_alive(self.sub.pid)
122
 
        return self._wait(cond, 60)
123
 
 
124
 
    def parse_output(self, str_flag, timeout=3):
125
 
        parse = ParseOutput(self.sub.stderr, str_flag)
126
 
        parse.start()
127
 
        parse.join(timeout)
128
 
        parse.stop()
129
 
        return parse
130
 
 
131
 
    @staticmethod
132
 
    def _wait(cond, timeout):
133
 
        start = time.time()
134
 
        while not cond():
135
 
            if time.time() - start > timeout:
136
 
                break
137
 
            time.sleep(.1)
138
 
        return cond()
139
 
 
140
 
    def _spawn_service(self, cmd, conf_file=None):
141
 
        if conf_file is None:
142
 
            conf_file = self.tempfile
143
 
        self.sub = subprocess.Popen([cmd, '--config-file=%s' % conf_file],
144
 
                                    stdout=subprocess.PIPE,
145
 
                                    stderr=subprocess.PIPE)
146
 
        #NOTE(Fengqian): Parse the output to see if the service started
147
 
        self.assertTrue(self.parse_output("Starting").ret)
148
 
        self.check_process_alive()
149
 
 
150
 
    def _service_restart(self, cmd):
151
 
        self._spawn_service(cmd)
152
 
 
153
 
        self.assertTrue(self.sub.pid)
154
 
        #NOTE(Fengqian): Modify the pipleline configure file to see
155
 
        #if the file is reloaded correctly.
156
 
        self._modify_pipeline_file()
157
 
        self.pipelinecfg_read_from_file()
158
 
        os.kill(self.sub.pid, signal.SIGHUP)
159
 
 
160
 
        self.assertTrue(self.check_process_alive())
161
 
        self.assertTrue(self.parse_output("Caught SIGHUP").ret)
162
 
        self.assertEqual(self.pipeline_cfg,
163
 
                         yaml.safe_load(
164
 
                         self.parse_output("Pipeline config: ").ret_stream))
165
 
 
166
 
    def test_compute_service_restart(self):
167
 
        self._service_restart('ceilometer-agent-compute')
168
 
 
169
 
    def test_central_service_restart(self):
170
 
        self._service_restart('ceilometer-agent-central')