blob: 7e3f2bfb784a2a373c44faa80486e139924cb4e1 [file] [log] [blame]
Petr Lomakin47fee0a2017-08-01 10:46:05 -07001package com.mirantis.mcp
2
3/**
4 *
5 * Tests providing functions
6 *
7 */
8
9/**
10 * Configure docker image with tests
11 *
12 * @param dockerImageLink Docker image link with rally and tempest
13 * @param target Host to run tests
14 * @param output_dir Directory for results
Dmitrii Kabanov65fdc282017-09-29 10:53:08 -070015 * @param ext_variables The set of external variables
Petr Lomakin47fee0a2017-08-01 10:46:05 -070016 */
Dmitrii Kabanov65fdc282017-09-29 10:53:08 -070017def runContainerConfiguration(master, dockerImageLink, target, output_dir, ext_variables){
Petr Lomakin47fee0a2017-08-01 10:46:05 -070018 def salt = new com.mirantis.mk.Salt()
19 def common = new com.mirantis.mk.Common()
20 def output_file = 'docker.log'
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -070021 def nodes = getNodeList(master)
22 def nodes_hw = getNodeList(master, 'G@virtual:physical')
Sam Stoelinga28bdb722017-09-25 18:29:59 -070023 def _pillar = salt.getPillar(master, 'I@keystone:server', 'keystone:server')
24 def keystone = _pillar['return'][0].values()[0]
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -070025 def ssh_key = getFileContent(master, 'I@salt:master', '/root/.ssh/id_rsa')
Petr Lomakin47fee0a2017-08-01 10:46:05 -070026 salt.cmdRun(master, target, "docker run -tid --net=host --name=qa_tools " +
Dmitrii Kabanov65fdc282017-09-29 10:53:08 -070027 " ${ext_variables} " +
Petr Lomakin47fee0a2017-08-01 10:46:05 -070028 "-e tempest_version=15.0.0 -e OS_USERNAME=${keystone.admin_name} " +
29 "-e OS_PASSWORD=${keystone.admin_password} -e OS_TENANT_NAME=${keystone.admin_tenant} " +
30 "-e OS_AUTH_URL=http://${keystone.bind.private_address}:${keystone.bind.private_port}/v2.0 " +
31 "-e OS_REGION_NAME=${keystone.region} -e OS_ENDPOINT_TYPE=admin ${dockerImageLink} /bin/bash")
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -070032 salt.cmdRun(master, target, "docker exec qa_tools bash -c \"sudo mkdir -p /root/.ssh; " +
33 "echo \'${ssh_key}\' | sudo tee /root/.ssh/id_rsa > /dev/null; " +
34 "sudo chmod 700 /root/.ssh; sudo chmod 600 /root/.ssh/id_rsa; " +
35 "echo -e '${nodes}' > nodes.json; echo -e '${nodes_hw}' > nodes_hw.json\"")
Petr Lomakin47fee0a2017-08-01 10:46:05 -070036 salt.cmdRun(master, target, "docker exec qa_tools bash -c /opt/devops-qa-tools/deployment/configure.sh > ${output_file}")
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -070037 def file_content = getFileContent(master, target, output_file)
Petr Lomakin47fee0a2017-08-01 10:46:05 -070038 writeFile file: "${output_dir}${output_file}", text: file_content
39}
40
41/**
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -070042 * Get file content. Extended version
43 *
44 * @param target Compound target (should target only one host)
45 * @param file File path to read
46 * @return The content of the file
47 */
48def getFileContent(master, target, file) {
49 def salt = new com.mirantis.mk.Salt()
50 def _result = null
51 def file_content = null
52 def result = salt.cmdRun(master, target, "if [ \$(wc -c <${file}) -gt 1048575 ]; then echo 1; fi", false, null, false)
53 def large_file = result['return'][0].values()[0]
54 if ( large_file ) {
55 salt.cmdRun(master, target, "split -b 1MB -d ${file} ${file}__", false, null, false)
56 def list_files = salt.cmdRun(master, target, "ls ${file}__*", false, null, false)
57 for ( item in list_files['return'][0].values()[0].tokenize() ) {
58 _result = salt.cmdRun(master, target, "cat ${item}", false, null, false)
59 file_content = file_content + _result['return'][0].values()[0].replaceAll('Salt command execution success','')
60 }
61 salt.cmdRun(master, target, "rm ${file}__*", false, null, false)
62 return file_content
63 } else {
64 _result = salt.cmdRun(master, target, "cat ${file}", false, null, false)
65 return _result['return'][0].values()[0].replaceAll('Salt command execution success','')
66 }
67}
68
69/**
70 * Get reclass value
71 *
72 * @param target The host for which the values will be provided
73 * @param filter Parameters divided by dots
74 * @return The pillar data
75 */
76def getReclassValue(master, target, filter) {
77 def common = new com.mirantis.mk.Common()
78 def salt = new com.mirantis.mk.Salt()
79 def items = filter.tokenize('.')
80 def _result = salt.cmdRun(master, 'I@salt:master', "reclass-salt -o json -p ${target} | " +
81 "python -c 'import json,sys; print(json.dumps(json.loads(sys.stdin.read()).get(\"${items[0]}\")))'", false, null, false)
82 _result = common.parseJSON(_result['return'][0].values()[0])
83 for ( item in items.tail()) {
84 if ( _result ) {
85 _result = _result["${item}"]
86 }
87 }
88 return _result
89}
90
91/**
92 * Create list of nodes in JSON format.
93 *
94 * @param filter The Salt's matcher
95 * @return JSON list of nodes
96 */
97def getNodeList(master, filter = null) {
98 def salt = new com.mirantis.mk.Salt()
99 def common = new com.mirantis.mk.Common()
100 def builder = new groovy.json.JsonBuilder()
101 def nodes = []
102 def n_counter = 0
103 def filtered_list = null
104 def controllers = salt.getMinions(master, 'I@nova:controller')
105 def hw_nodes = salt.getMinions(master, 'G@virtual:physical')
106 def json = builder (ip: '', roles: '', id: '', network_data: [ builder (name: 'management', ip: '')])
107 if ( filter ) {
108 filtered_list = salt.getMinions(master, filter)
109 filtered_list.addAll(controllers)
110 }
111 def _result = salt.cmdRun(master, 'I@salt:master', "reclass-salt -o json -t", false, null, false)
112 def reclass_top = common.parseJSON(_result['return'][0].values()[0])
113 for (item in reclass_top.base) {
114 if ( filtered_list ) {
115 if ( ! filtered_list.contains(item.getKey()) ) {
116 continue
117 }
118 }
119 n_counter += 1
120 json.id = n_counter.toString()
121 json.ip = getReclassValue(master, item.getKey(), '_param.linux_single_interface.address')
122 json.network_data[0].ip = json.ip
123 json.roles = item.getKey().tokenize('.')[0]
124 if ( controllers.contains(item.getKey()) ) {
125 json.roles = "${json.roles}, controller"
126 }
127 if ( hw_nodes.contains(item.getKey()) ) {
128 json.roles = "${json.roles}, hw_node"
129 }
130 def node = builder.toPrettyString().replace('"', '\\"')
131 nodes.add(node)
132 }
133 return nodes
134}
135
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500136/**
137 * Execute mcp sanity tests
138 *
139 * @param salt_url Salt master url
140 * @param salt_credentials Salt credentials
141 * @param test_set Test set for mcp sanity framework
142 * @param output_dir Directory for results
143 */
144def runSanityTests(salt_url, salt_credentials, test_set, output_dir) {
145 def common = new com.mirantis.mk.Common()
146 creds = common.getCredentials(salt_credentials)
147 username = creds.username
148 password = creds.password
149 def script = ". ${env.WORKSPACE}/venv/bin/activate; pytest --junitxml ${output_dir}cvp_sanity.xml -sv ${env.WORKSPACE}/cvp-sanity-checks/cvp_checks/tests/${test_set}"
150 withEnv(["SALT_USERNAME=${username}", "SALT_PASSWORD=${password}", "SALT_URL=${salt_url}"]) {
151 def statusCode = sh script:script, returnStatus:true
152 }
153}
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700154
155/**
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700156 * Execute tempest tests
157 *
158 * @param target Host to run tests
159 * @param pattern If not false, will run only tests matched the pattern
160 * @param output_dir Directory for results
161 */
162def runTempestTests(master, target, output_dir, pattern = "false") {
163 def salt = new com.mirantis.mk.Salt()
164 def output_file = 'docker-tempest.log'
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700165 def path = '/opt/devops-qa-tools/generate_test_report/test_results'
166 def jsonfile = 'tempest_results.json'
167 def htmlfile = 'tempest_results.html'
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700168 if (pattern == "false") {
169 salt.cmdRun(master, target, "docker exec qa_tools rally verify start --pattern set=full " +
170 "--detailed > ${output_file}")
171 }
172 else {
173 salt.cmdRun(master, target, "docker exec qa_tools rally verify start --pattern ${pattern} " +
174 "--detailed > ${output_file}")
175 }
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700176 salt.cmdRun(master, target, "docker exec qa_tools rally verify report --type json " +
177 "--to ${path}/report-tempest.json")
178 salt.cmdRun(master, target, "docker exec qa_tools rally verify report --type html " +
179 "--to ${path}/report-tempest.html")
180
181 salt.cmdRun(master, target, "docker cp qa_tools:${path}/report-tempest.json ${jsonfile}")
182 salt.cmdRun(master, target, "docker cp qa_tools:${path}/report-tempest.html ${htmlfile}")
183 def file_content = getFileContent(master, target, jsonfile)
184 writeFile file: "${output_dir}/report-tempest.json", text: file_content
185 file_content = getFileContent(master, target, htmlfile)
186 writeFile file: "${output_dir}/report-tempest.html", text: file_content
187 file_content = getFileContent(master, target, output_file)
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700188 writeFile file: "${output_dir}${output_file}", text: file_content
189}
190
191/**
192 * Execute rally tests
193 *
194 * @param target Host to run tests
195 * @param pattern If not false, will run only tests matched the pattern
196 * @param output_dir Directory for results
197 */
198def runRallyTests(master, target, output_dir, pattern = "false") {
199 def salt = new com.mirantis.mk.Salt()
200 def output_file = 'docker-rally.log'
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700201 def path = '/opt/devops-qa-tools/generate_test_report/test_results'
202 def xmlfile = 'rally_results.xml'
203 def htmlfile = 'rally_results.html'
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700204 salt.cmdRun(master, target, "docker exec qa_tools rally task start combined_scenario.yaml --task-args-file " +
205 "/opt/devops-qa-tools/rally-scenarios/task_arguments.yaml | tee ${output_file}")
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700206
207 salt.cmdRun(master, target, "docker exec qa_tools rally task export --type junit-xml " +
208 "--to ${path}/report-rally.xml")
209 salt.cmdRun(master, target, "docker exec qa_tools rally task report --out ${path}/report-rally.html")
210 salt.cmdRun(master, target, "docker cp qa_tools:${path}/report-rally.xml ${xmlfile}")
211 salt.cmdRun(master, target, "docker cp qa_tools:${path}/report-rally.html ${htmlfile}")
212
213 def file_content = getFileContent(master, target, xmlfile)
214 writeFile file: "${output_dir}/report-rally.xml", text: file_content
215 file_content = getFileContent(master, target, htmlfile)
216 writeFile file: "${output_dir}/report-rally.html", text: file_content
217 file_content = getFileContent(master, target, output_file)
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700218 writeFile file: "${output_dir}${output_file}", text: file_content
219}
220
221/**
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700222 * Generate test report
223 *
224 * @param target Host to run script from
225 * @param output_dir Directory for results
226 */
227def generateTestReport(master, target, output_dir) {
228 def report_file = 'jenkins_test_report.html'
229 def path = '/opt/devops-qa-tools/generate_test_report/'
230 def res_path = '/opt/devops-qa-tools/generate_test_report/test_results/'
231 def salt = new com.mirantis.mk.Salt()
232 def common = new com.mirantis.mk.Common()
233
234 // Create 'test_results' directory in case it doesn't exist in container
235 def test_results = salt.cmdRun(master, target, "docker exec qa_tools bash -c \"if [ ! -d ${res_path} ]; " +
236 "then echo Creating directory ${res_path}; mkdir ${res_path}; fi\"")
237
238 def reports = ['report-tempest.json', 'report-rally.xml', 'report-k8s-e2e-tests.txt', 'report-ha.json', 'report-spt.txt']
239
240 for (report in reports) {
241 def _result = salt.cmdRun(master, target, "docker exec qa_tools bash -c \"if [ -f ${res_path}${report} ]; then echo 1; fi\"", checkResponse=false)
242 res = _result['return'][0].values()[0]
243 if ( res ) {
244 common.infoMsg("File ${report} already exists in docker container")
245 continue
246 }
247 if ( fileExists("${output_dir}${report}") ) {
248 common.infoMsg("Copying ${report} to docker container")
249 if ("${report}" == "report-tempest.json") {
250 def temp_file = readJSON file: "${output_dir}/${report}"
251 def tempest_cont = temp_file['verifications']
252 def json = common.prettify(["verifications":tempest_cont])
253 json = sh(script: "echo '${json}' | base64 -w 0", returnStdout: true)
254 salt.cmdRun(master, target, "docker exec qa_tools bash -c \"echo \"${json}\" | base64 -d | tee ${res_path}${report}\"", false, null, true)
255 }
256 else if ( "${report}" == "report-k8s-e2e-tests.txt" ) {
257 def k8s_content = sh(script: "cat ${output_dir}${report}| tail -20 | base64 -w 0", returnStdout: true)
258 salt.cmdRun(master, target, "docker exec qa_tools bash -c \"echo ${k8s_content} | base64 -d | tee ${res_path}${report}\"", false, null, true)
259 }
260 else {
261 def rep_content = sh(script: "cat ${output_dir}${report} | base64 -w 0", returnStdout: true)
262 salt.cmdRun(master, target, "docker exec qa_tools bash -c \"echo \"${rep_content}\" | base64 -d | tee ${res_path}${report}\"", false, null, true)
263 }
264 }
265 }
266 salt.cmdRun(master, target, "docker exec qa_tools jenkins_report.py --path ${path}")
267 salt.cmdRun(master, target, "docker cp qa_tools:/home/rally/${report_file} ${report_file}")
268
269 def report_content = salt.getFileContent(master, target, report_file)
270 writeFile file: "${output_dir}${report_file}", text: report_content
271}
272
273/**
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700274 * Execute SPT tests
275 *
276 * @param target Host to run tests
277 * @param output_dir Directory for results
278 */
279def runSptTests(master, target, output_dir) {
280 def salt = new com.mirantis.mk.Salt()
281 def output_file = 'docker-spt.log'
282 def report_file = 'report-spt.txt'
283 def report_file_hw = 'report-spt-hw.txt'
284 def archive_file = 'results-spt.tar.gz'
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700285 def path = '/opt/devops-qa-tools/generate_test_report/test_results'
286
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700287 salt.cmdRun(master, target, "docker exec qa_tools sudo timmy -c simplified-performance-testing/config.yaml " +
288 "--nodes-json nodes.json --log-file ${output_file}")
289 salt.cmdRun(master, target, "docker exec qa_tools ./simplified-performance-testing/SPT_parser.sh > ${report_file}")
290 salt.cmdRun(master, target, "docker exec qa_tools custom_spt_parser.sh > ${report_file_hw}")
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700291
292 salt.cmdRun(master, target, "docker cp ${report_file} qa_tools:${path}/report-spt.txt")
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700293 salt.cmdRun(master, target, "docker cp qa_tools:/home/rally/${output_file} ${output_file}")
294 salt.cmdRun(master, target, "docker cp qa_tools:/tmp/timmy/archives/general.tar.gz ${archive_file}")
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700295
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700296 def file_content = getFileContent(master, target, output_file)
297 writeFile file: "${output_dir}${output_file}", text: file_content
298 file_content = getFileContent(master, target, report_file)
299 writeFile file: "${output_dir}${report_file}", text: file_content
300 file_content = getFileContent(master, target, report_file_hw)
301 writeFile file: "${output_dir}${report_file_hw}", text: file_content
302}
303
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700304/**
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700305 * Cleanup
306 *
307 * @param target Host to run commands
308 * @param output_dir Directory for results
309 */
310def runCleanup(master, target, output_dir) {
311 def salt = new com.mirantis.mk.Salt()
Dmitrii Kabanov321405a2017-08-16 16:38:51 -0700312 if ( salt.cmdRun(master, target, "docker ps -f name=qa_tools -q", false, null, false)['return'][0].values()[0] ) {
313 salt.cmdRun(master, target, "docker rm -f qa_tools")
314 }
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700315}
316
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500317/**
318 * Prepare venv for any python project
319 * Note: <repo_name>\/requirements.txt content will be used
320 * for this venv
321 *
322 * @param repo_url Repository url to clone
323 * @param proxy Proxy address to use
324 */
325def prepareVenv(repo_url, proxy) {
326 def python = new com.mirantis.mk.Python()
327 repo_name = "${repo_url}".tokenize("/").last()
328 sh "rm -rf ${repo_name}"
329 withEnv(["HTTPS_PROXY=${proxy}", "HTTP_PROXY=${proxy}", "https_proxy=${proxy}", "http_proxy=${proxy}"]) {
330 sh "git clone ${repo_url}"
331 python.setupVirtualenv("${env.WORKSPACE}/venv", "python2", [], "${env.WORKSPACE}/${repo_name}/requirements.txt", true)
332 }
333}
334
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700335/** Install docker if needed
336 *
337 * @param target Target node to install docker pkg
338 */
339def installDocker(master, target) {
340 def salt = new com.mirantis.mk.Salt()
341 if ( ! salt.runSaltProcessStep(master, target, 'pkg.version', ["docker-engine"]) ) {
342 salt.runSaltProcessStep(master, target, 'pkg.install', ["docker.io"])
343 }
344}