blob: a46d0fbbdaa1b2faeee446459435f8d9102c6ed0 [file] [log] [blame]
Matthew Treinishd15705b2012-10-16 14:04:48 -04001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Copyright 2012 IBM
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
17import json
18import os
19import re
20import shutil
21import sys
22
Matthew Treinish90aedd12013-02-25 17:56:49 -050023from oslo.config import cfg
24
Matthew Treinishd15705b2012-10-16 14:04:48 -040025from tempest.common.rest_client import RestClient
26from tempest import config
Matthew Treinishd15705b2012-10-16 14:04:48 -040027from tempest.tests.compute import base
28
29CONF = config.TempestConfig()
30
31
32class CoverageClientJSON(RestClient):
33
34 def __init__(self, config, username, password, auth_url, tenant_name=None):
35 super(CoverageClientJSON, self).__init__(config, username, password,
36 auth_url, tenant_name)
37 self.service = self.config.compute.catalog_type
38
39 def start_coverage(self):
40 post_body = {
41 'start': {},
42 }
43 post_body = json.dumps(post_body)
44 return self.post('os-coverage/action', post_body, self.headers)
45
46 def start_coverage_combine(self):
47 post_body = {
48 'start': {
49 'combine': True,
50 },
51 }
52 post_body = json.dumps(post_body)
53 return self.post('os-coverage/action', post_body, self.headers)
54
55 def stop_coverage(self):
56 post_body = {
57 'stop': {},
58 }
59 post_body = json.dumps(post_body)
60 resp, body = self.post('os-coverage/action', post_body, self.headers)
61 body = json.loads(body)
62 return resp, body
63
64 def report_coverage_xml(self, file=None):
65 post_body = {
66 'report': {
67 'file': 'coverage.report',
68 'xml': True,
69 },
70 }
71 if file:
72 post_body['report']['file'] = file
73 post_body = json.dumps(post_body)
74 resp, body = self.post('os-coverage/action', post_body, self.headers)
75 body = json.loads(body)
76 return resp, body
77
78 def report_coverage(self, file=None):
79 post_body = {
80 'report': {
81 'file': 'coverage.report',
82 },
83 }
84 if file:
85 post_body['report']['file'] = file
86 post_body = json.dumps(post_body)
87 resp, body = self.post('os-coverage/action', post_body, self.headers)
88 body = json.loads(body)
89 return resp, body
90
91 def report_coverage_html(self, file=None):
92 post_body = {
93 'report': {
94 'file': 'coverage.report',
95 'html': True,
96 },
97 }
98 if file:
99 post_body['report']['file'] = file
100 post_body = json.dumps(post_body)
101 resp, body = self.post('os-coverage/action', post_body, self.headers)
102 body = json.loads(body)
103 return resp, body
104
105
106def parse_opts(argv):
107 cli_opts = [
108 cfg.StrOpt('command',
109 short='c',
110 default='',
111 help="This required argument is used to specify the "
112 "coverage command to run. Only 'start', "
113 "'stop', or 'report' are valid fields."),
114 cfg.StrOpt('filename',
115 default='tempest-coverage',
116 help="Specify a filename to be used for generated report "
117 "files"),
118 cfg.BoolOpt('xml',
119 default=False,
120 help='Generate XML reports instead of text'),
121 cfg.BoolOpt('html',
122 default=False,
123 help='Generate HTML reports instead of text'),
124 cfg.BoolOpt('combine',
125 default=False,
126 help='Generate a single report for all services'),
127 cfg.StrOpt('output',
128 short='o',
129 default=None,
130 help='Optional directory to copy generated coverage data or'
131 ' reports into. This directory must not already exist '
132 'it will be created')
133 ]
134 CLI = cfg.ConfigOpts()
135 CLI.register_cli_opts(cli_opts)
136 CLI(argv[1:])
137 return CLI
138
139
140def main(argv):
141 CLI = parse_opts(argv)
Attila Fazekascadcb1f2013-01-21 23:10:53 +0100142 client_args = (CONF, CONF.identity.admin_username,
143 CONF.identity.admin_password, CONF.identity.uri,
144 CONF.identity.admin_tenant_name)
Matthew Treinishd15705b2012-10-16 14:04:48 -0400145 coverage_client = CoverageClientJSON(*client_args)
146
147 if CLI.command == 'start':
148 if CLI.combine:
149 coverage_client.start_coverage_combine()
150 else:
151 coverage_client.start_coverage()
152
153 elif CLI.command == 'stop':
154 resp, body = coverage_client.stop_coverage()
155 if not resp['status'] == '200':
156 print 'coverage stop failed with: %s:' % (resp['status'] + ': '
157 + body)
158 exit(int(resp['status']))
159 path = body['path']
160 if CLI.output:
161 shutil.copytree(path, CLI.output)
162 else:
163 print "Data files located at: %s" % path
164
165 elif CLI.command == 'report':
166 if CLI.xml:
167 resp, body = coverage_client.report_coverage_xml(file=CLI.filename)
168 elif CLI.html:
169 resp, body = coverage_client.report_coverage_html(
170 file=CLI.filename)
171 else:
172 resp, body = coverage_client.report_coverage(file=CLI.filename)
173 if not resp['status'] == '200':
174 print 'coverage report failed with: %s:' % (resp['status'] + ': '
175 + body)
176 exit(int(resp['status']))
177 path = body['path']
178 if CLI.output:
179 if CLI.html:
180 shutil.copytree(path, CLI.output)
181 else:
182 path = os.path.dirname(path)
183 shutil.copytree(path, CLI.output)
184 else:
185 if not CLI.html:
186 path = os.path.dirname(path)
187 print 'Report files located at: %s' % path
188
189 else:
190 print 'Invalid command'
191 exit(1)
192
193
194if __name__ == "__main__":
195 main(sys.argv)