blob: f4ad5bc82274db6ea42106db65fffa8bd9e9784d [file] [log] [blame]
Petr Lomakin47fee0a2017-08-01 10:46:05 -07001package com.mirantis.mcp
2
3/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -05004 * DEPRECATED
Petr Lomakin47fee0a2017-08-01 10:46:05 -07005 * Tests providing functions
6 *
7 */
8
9/**
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -060010 * Run docker container with basic (keystone) parameters
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050011 * For backward compatibility. Deprecated.
12 * Will be removed soon.
Petr Lomakin47fee0a2017-08-01 10:46:05 -070013 *
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -060014 * @param target Host to run container
15 * @param dockerImageLink Docker image link. May be custom or default rally image
Petr Lomakin47fee0a2017-08-01 10:46:05 -070016 */
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050017def runBasicContainer(master, target, dockerImageLink="xrally/xrally-openstack:0.10.1"){
Petr Lomakin47fee0a2017-08-01 10:46:05 -070018 def salt = new com.mirantis.mk.Salt()
19 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -050020 common.errorMsg('You are using deprecated method! Please migrate to validate.runContainer. This method will be removed')
21 error('You are using deprecated method! Please migrate to validate.runContainer. This method will be removed')
Sam Stoelinga28bdb722017-09-25 18:29:59 -070022 def _pillar = salt.getPillar(master, 'I@keystone:server', 'keystone:server')
23 def keystone = _pillar['return'][0].values()[0]
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -060024 if ( salt.cmdRun(master, target, "docker ps -f name=cvp -q", false, null, false)['return'][0].values()[0] ) {
25 salt.cmdRun(master, target, "docker rm -f cvp")
26 }
27 salt.cmdRun(master, target, "docker run -tid --net=host --name=cvp " +
28 "-u root -e OS_USERNAME=${keystone.admin_name} " +
Petr Lomakin47fee0a2017-08-01 10:46:05 -070029 "-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 " +
Oleksii Zhurba1bf9be12018-01-17 15:20:00 -060031 "-e OS_REGION_NAME=${keystone.region} -e OS_ENDPOINT_TYPE=admin --entrypoint /bin/bash ${dockerImageLink}")
Petr Lomakin47fee0a2017-08-01 10:46:05 -070032}
33
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050034
35/**
36 * Run docker container with parameters
37 *
Oleksii Zhurbaf1138b22019-03-26 16:15:56 -050038 * @param target Host to run container
39 * @param dockerImageLink Docker image link. May be custom or default rally image
40 * @param name Name for container
41 * @param env_var Environment variables to set in container
42 * @param entrypoint Set entrypoint to /bin/bash or leave default
43 * @param mounts Map with mounts for container
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050044**/
45
Oleksii Zhurbaf1138b22019-03-26 16:15:56 -050046def runContainer(Map params){
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050047 def common = new com.mirantis.mk.Common()
Oleksii Zhurbaf1138b22019-03-26 16:15:56 -050048 defaults = ["name": "cvp", "env_var": [], "entrypoint": true]
49 params = defaults + params
50 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050051 def variables = ''
52 def entry_point = ''
Oleksii Zhurbaf1138b22019-03-26 16:15:56 -050053 def tempest_conf_mount = ''
54 def mounts = ''
55 def cluster_name = salt.getPillar(params.master, 'I@salt:master', '_param:cluster_name')['return'][0].values()[0]
56 default_mounts = ["/etc/ssl/certs/": "/etc/ssl/certs/",
57 "/srv/salt/pki/${cluster_name}/": "/etc/certs",
58 "/root/test/": "/root/tempest/",
59 "/tmp/": "/tmp/",
60 "/etc/hosts": "/etc/hosts"]
61 params.mounts = default_mounts + params.mounts
62 if ( salt.cmdRun(params.master, params.target, "docker ps -f name=${params.name} -q", false, null, false)['return'][0].values()[0] ) {
63 salt.cmdRun(params.master, params.target, "docker rm -f ${params.name}")
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050064 }
Oleksii Zhurbaf1138b22019-03-26 16:15:56 -050065 if (params.env_var.size() > 0) {
66 variables = ' -e ' + params.env_var.join(' -e ')
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050067 }
Oleksii Zhurbaf1138b22019-03-26 16:15:56 -050068 if (params.entrypoint) {
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050069 entry_point = '--entrypoint /bin/bash'
70 }
Oleksii Zhurbaf1138b22019-03-26 16:15:56 -050071 params.mounts.each { local, container ->
72 mounts = mounts + " -v ${local}:${container}"
73 }
74 salt.cmdRun(params.master, params.target, "docker run -tid --net=host --name=${params.name}" +
75 "${mounts} -u root ${entry_point} ${variables} ${params.dockerImageLink}")
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050076}
77
Oleksii Zhurbaf1138b22019-03-26 16:15:56 -050078def runContainer(master, target, dockerImageLink, name='cvp', env_var=[], entrypoint=true, mounts=[:]){
79 def common = new com.mirantis.mk.Common()
80 common.infoMsg("This method will be deprecated. Convert you method call to use Map as input parameter")
81 // Convert to Map
82 params = ['master': master, 'target': target, 'dockerImageLink': dockerImageLink, 'name': name, 'env_var': env_var,
83 'entrypoint': entrypoint, 'mounts': mounts]
84 // Call new method with Map as parameter
85 return runContainer(params)
86}
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050087
Petr Lomakin47fee0a2017-08-01 10:46:05 -070088/**
Oleksii Zhurba4bcf07f2018-09-11 15:23:18 -050089 * Get v2 Keystone credentials from pillars
90 *
91 */
92def _get_keystone_creds_v2(master){
93 def salt = new com.mirantis.mk.Salt()
94 def common = new com.mirantis.mk.Common()
95 def keystone = []
96 common.infoMsg("Fetching Keystone v2 credentials")
97 _pillar = salt.getPillar(master, 'I@keystone:server', 'keystone:server')['return'][0].values()[0]
98 keystone.add("OS_USERNAME=${_pillar.admin_name}")
99 keystone.add("OS_PASSWORD=${_pillar.admin_password}")
100 keystone.add("OS_TENANT_NAME=${_pillar.admin_tenant}")
101 keystone.add("OS_AUTH_URL=http://${_pillar.bind.private_address}:${_pillar.bind.private_port}/v2.0")
102 keystone.add("OS_REGION_NAME=${_pillar.region}")
103 keystone.add("OS_ENDPOINT_TYPE=admin")
104 return keystone
105}
106
107/**
108 * Get v3 Keystone credentials from pillars
109 *
110 */
111def _get_keystone_creds_v3(master){
112 def salt = new com.mirantis.mk.Salt()
113 def common = new com.mirantis.mk.Common()
114 pillar_name = 'keystone:client:os_client_config:cfgs:root:content:clouds:admin_identity'
115 common.infoMsg("Fetching Keystone v3 credentials")
116 def _pillar = salt.getPillar(master, 'I@keystone:client', pillar_name)['return'][0].values()[0]
117 def keystone = []
118 if (_pillar) {
119 keystone.add("OS_USERNAME=${_pillar.auth.username}")
120 keystone.add("OS_PASSWORD=${_pillar.auth.password}")
121 keystone.add("OS_TENANT_NAME=${_pillar.auth.project_name}")
122 keystone.add("OS_PROJECT_NAME=${_pillar.auth.project_name}")
123 keystone.add("OS_AUTH_URL=${_pillar.auth.auth_url}/v3")
124 keystone.add("OS_REGION_NAME=${_pillar.region_name}")
125 keystone.add("OS_IDENTITY_API_VERSION=${_pillar.identity_api_version}")
Oleksii Zhurbafa885ed2019-02-13 18:27:31 -0600126 keystone.add("OS_ENDPOINT_TYPE=internal")
Oleksii Zhurba4bcf07f2018-09-11 15:23:18 -0500127 keystone.add("OS_PROJECT_DOMAIN_NAME=${_pillar.auth.project_domain_name}")
128 keystone.add("OS_USER_DOMAIN_NAME=${_pillar.auth.user_domain_name}")
Oleksii Zhurbafa885ed2019-02-13 18:27:31 -0600129 // we mount /srv/salt/pki/${cluster_name}/:/etc/certs with certs for cvp container
130 keystone.add("OS_CACERT='/etc/certs/proxy-with-chain.crt'")
Oleksii Zhurba4bcf07f2018-09-11 15:23:18 -0500131 return keystone
132 }
133 else {
134 common.warningMsg("Failed to fetch Keystone v3 credentials")
135 return false
136 }
137}
138
139/**
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700140 * Get file content (encoded). The content encoded by Base64.
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700141 *
142 * @param target Compound target (should target only one host)
143 * @param file File path to read
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700144 * @return The encoded content of the file
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700145 */
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700146def getFileContentEncoded(master, target, file) {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700147 def salt = new com.mirantis.mk.Salt()
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700148 def file_content = ''
149 def cmd = "base64 -w0 ${file} > ${file}_encoded; " +
150 "split -b 1MB -d ${file}_encoded ${file}__; " +
151 "rm ${file}_encoded"
152 salt.cmdRun(master, target, cmd, false, null, false)
153 def filename = file.tokenize('/').last()
154 def folder = file - filename
155 def parts = salt.runSaltProcessStep(master, target, 'file.find', ["${folder}", "type=f", "name=${filename}__*"])
156 for ( part in parts['return'][0].values()[0]) {
157 def _result = salt.cmdRun(master, target, "cat ${part}", false, null, false)
158 file_content = file_content + _result['return'][0].values()[0].replaceAll('Salt command execution success','')
159 }
160 salt.runSaltProcessStep(master, target, 'file.find', ["${folder}", "type=f", "name=${filename}__*", "delete"])
161 return file_content
162}
163
164/**
165 * Copy files from remote to local directory. The content of files will be
166 * decoded by Base64.
167 *
168 * @param target Compound target (should target only one host)
169 * @param folder The path to remote folder.
170 * @param output_dir The path to local folder.
171 */
172def addFiles(master, target, folder, output_dir) {
173 def salt = new com.mirantis.mk.Salt()
174 def _result = salt.runSaltProcessStep(master, target, 'file.find', ["${folder}", "type=f"])
175 def files = _result['return'][0].values()[0]
176 for (file in files) {
177 def file_content = getFileContentEncoded(master, target, "${file}")
178 def fileName = file.tokenize('/').last()
179 writeFile file: "${output_dir}${fileName}_encoded", text: file_content
180 def cmd = "base64 -d ${output_dir}${fileName}_encoded > ${output_dir}${fileName}; " +
181 "rm ${output_dir}${fileName}_encoded"
182 sh(script: cmd)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700183 }
184}
185
186/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500187 * DEPRECATED
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700188 * Get reclass value
189 *
190 * @param target The host for which the values will be provided
191 * @param filter Parameters divided by dots
192 * @return The pillar data
193 */
194def getReclassValue(master, target, filter) {
195 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500196 common.errorMsg('You are using deprecated method! This method will be removed')
197 error('You are using deprecated method! This method will be removed')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700198 def salt = new com.mirantis.mk.Salt()
199 def items = filter.tokenize('.')
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700200 def _result = salt.cmdRun(master, 'I@salt:master', "reclass-salt -o json -p ${target}", false, null, false)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700201 _result = common.parseJSON(_result['return'][0].values()[0])
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700202 for (int k = 0; k < items.size(); k++) {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700203 if ( _result ) {
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700204 _result = _result["${items[k]}"]
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700205 }
206 }
207 return _result
208}
209
210/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500211 * DEPRECATED
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700212 * Create list of nodes in JSON format.
213 *
214 * @param filter The Salt's matcher
215 * @return JSON list of nodes
216 */
217def getNodeList(master, filter = null) {
218 def salt = new com.mirantis.mk.Salt()
219 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500220 common.errorMsg('You are using deprecated method! This method will be removed')
221 error('You are using deprecated method! This method will be removed')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700222 def nodes = []
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700223 def filtered_list = null
224 def controllers = salt.getMinions(master, 'I@nova:controller')
225 def hw_nodes = salt.getMinions(master, 'G@virtual:physical')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700226 if ( filter ) {
227 filtered_list = salt.getMinions(master, filter)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700228 }
229 def _result = salt.cmdRun(master, 'I@salt:master', "reclass-salt -o json -t", false, null, false)
230 def reclass_top = common.parseJSON(_result['return'][0].values()[0])
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700231 def nodesList = reclass_top['base'].keySet()
232 for (int i = 0; i < nodesList.size(); i++) {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700233 if ( filtered_list ) {
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700234 if ( ! filtered_list.contains(nodesList[i]) ) {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700235 continue
236 }
237 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700238 def ip = getReclassValue(master, nodesList[i], '_param.linux_single_interface.address')
239 def network_data = [ip: ip, name: 'management']
240 def roles = [nodesList[i].tokenize('.')[0]]
241 if ( controllers.contains(nodesList[i]) ) {
242 roles.add('controller')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700243 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700244 if ( hw_nodes.contains(nodesList[i]) ) {
245 roles.add('hw_node')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700246 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700247 nodes.add([id: i+1, ip: ip, roles: roles, network_data: [network_data]])
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700248 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700249 return common.prettify(nodes)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700250}
251
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500252/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500253 * DEPRECATED
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500254 * Execute mcp sanity tests
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500255 * Deprecated. Will be removed soon
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500256 *
257 * @param salt_url Salt master url
258 * @param salt_credentials Salt credentials
259 * @param test_set Test set for mcp sanity framework
Oleksii Zhurba0a7b0702017-11-10 16:02:16 -0600260 * @param env_vars Additional environment variables for cvp-sanity-checks
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500261 * @param output_dir Directory for results
262 */
Oleksii Zhurba0a7b0702017-11-10 16:02:16 -0600263def runSanityTests(salt_url, salt_credentials, test_set="", output_dir="validation_artifacts/", env_vars="") {
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500264 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500265 common.errorMsg('You are using deprecated method! Please migrate to validate.runTests. This method will be removed')
266 error('You are using deprecated method! Please migrate to validate.runTests. This method will be removed')
Oleksii Zhurba0a7b0702017-11-10 16:02:16 -0600267 def creds = common.getCredentials(salt_credentials)
268 def username = creds.username
269 def password = creds.password
270 def settings = ""
271 if ( env_vars != "" ) {
272 for (var in env_vars.tokenize(";")) {
273 settings += "export ${var}; "
274 }
275 }
276 def script = ". ${env.WORKSPACE}/venv/bin/activate; ${settings}" +
Oleksii Zhurba5250a9c2018-03-21 15:47:03 -0500277 "pytest --junitxml ${output_dir}cvp_sanity.xml --tb=short -sv ${env.WORKSPACE}/cvp-sanity-checks/cvp_checks/tests/${test_set}"
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500278 withEnv(["SALT_USERNAME=${username}", "SALT_PASSWORD=${password}", "SALT_URL=${salt_url}"]) {
279 def statusCode = sh script:script, returnStatus:true
280 }
281}
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700282
283/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500284 * DEPRECATED
Oleksii Zhurba4e366ff2018-02-16 20:06:52 -0600285 * Execute pytest framework tests
286 *
287 * @param salt_url Salt master url
288 * @param salt_credentials Salt credentials
289 * @param test_set Test set to run
290 * @param env_vars Additional environment variables for cvp-sanity-checks
291 * @param output_dir Directory for results
292 */
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500293def runPyTests(salt_url, salt_credentials, test_set="", env_vars="", name='cvp', container_node="", remote_dir='/root/qa_results/', artifacts_dir='validation_artifacts/') {
294 def xml_file = "${name}_report.xml"
295 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500296 common.errorMsg('You are using deprecated method! Please migrate to validate.runTests. This method will be removed')
297 error('You are using deprecated method! Please migrate to validate.runTests. This method will be removed')
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500298 def salt = new com.mirantis.mk.Salt()
299 def creds = common.getCredentials(salt_credentials)
300 def username = creds.username
301 def password = creds.password
302 if (container_node != "") {
303 def saltMaster
304 saltMaster = salt.connection(salt_url, salt_credentials)
305 def script = "pytest --junitxml ${xml_file} --tb=short -sv ${test_set}"
306 env_vars.addAll("SALT_USERNAME=${username}", "SALT_PASSWORD=${password}",
307 "SALT_URL=${salt_url}")
308 variables = ' -e ' + env_vars.join(' -e ')
309 salt.cmdRun(saltMaster, container_node, "docker exec ${variables} ${name} bash -c '${script}'", false)
310 salt.cmdRun(saltMaster, container_node, "docker cp ${name}:/var/lib/${xml_file} ${remote_dir}${xml_file}")
311 addFiles(saltMaster, container_node, remote_dir+xml_file, artifacts_dir)
312 }
313 else {
314 if (env_vars.size() > 0) {
315 variables = 'export ' + env_vars.join(';export ')
316 }
317 def script = ". ${env.WORKSPACE}/venv/bin/activate; ${variables}; " +
318 "pytest --junitxml ${artifacts_dir}${xml_file} --tb=short -sv ${env.WORKSPACE}/${test_set}"
319 withEnv(["SALT_USERNAME=${username}", "SALT_PASSWORD=${password}", "SALT_URL=${salt_url}"]) {
320 def statusCode = sh script:script, returnStatus:true
321 }
322 }
323}
324
325/**
326 * Execute pytest framework tests
327 * For backward compatibility
328 * Will be removed soon
329 *
330 * @param salt_url Salt master url
331 * @param salt_credentials Salt credentials
332 * @param test_set Test set to run
333 * @param env_vars Additional environment variables for cvp-sanity-checks
334 * @param output_dir Directory for results
335 */
Oleksii Zhurba4e366ff2018-02-16 20:06:52 -0600336def runTests(salt_url, salt_credentials, test_set="", output_dir="validation_artifacts/", env_vars="") {
337 def common = new com.mirantis.mk.Common()
338 def creds = common.getCredentials(salt_credentials)
339 def username = creds.username
340 def password = creds.password
341 def settings = ""
342 if ( env_vars != "" ) {
343 for (var in env_vars.tokenize(";")) {
344 settings += "export ${var}; "
345 }
346 }
347 def script = ". ${env.WORKSPACE}/venv/bin/activate; ${settings}" +
348 "pytest --junitxml ${output_dir}report.xml --tb=short -sv ${env.WORKSPACE}/${test_set}"
349 withEnv(["SALT_USERNAME=${username}", "SALT_PASSWORD=${password}", "SALT_URL=${salt_url}"]) {
350 def statusCode = sh script:script, returnStatus:true
351 }
352}
353
354/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500355 * DEPRECATED
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700356 * Execute tempest tests
357 *
358 * @param target Host to run tests
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700359 * @param dockerImageLink Docker image link
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700360 * @param pattern If not false, will run only tests matched the pattern
361 * @param output_dir Directory for results
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800362 * @param confRepository Git repository with configuration files for Tempest
363 * @param confBranch Git branch which will be used during the checkout
364 * @param repository Git repository with Tempest
365 * @param version Version of Tempest (tag, branch or commit)
Sergey Galkind1068e22018-02-13 13:59:32 +0400366 * @param results The reports directory
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700367 */
Sergey Galkind1068e22018-02-13 13:59:32 +0400368def runTempestTests(master, target, dockerImageLink, output_dir, confRepository, confBranch, repository, version, pattern = "false", results = '/root/qa_results') {
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700369 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500370 def common = new com.mirantis.mk.Common()
371 common.errorMsg('You are using deprecated method! This method will be removed')
372 error('You are using deprecated method! This method will be removed')
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700373 def output_file = 'docker-tempest.log'
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700374 def dest_folder = '/home/rally/qa_results'
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800375 def skip_list = '--skip-list /opt/devops-qa-tools/deployment/skip_contrail.list'
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700376 salt.runSaltProcessStep(master, target, 'file.remove', ["${results}"])
377 salt.runSaltProcessStep(master, target, 'file.mkdir', ["${results}", "mode=777"])
378 def _pillar = salt.getPillar(master, 'I@keystone:server', 'keystone:server')
379 def keystone = _pillar['return'][0].values()[0]
Dmitry Tsapikovb6911922018-07-24 15:21:23 +0000380 def env_vars = ['tempest_version=15.0.0',
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700381 "OS_USERNAME=${keystone.admin_name}",
382 "OS_PASSWORD=${keystone.admin_password}",
383 "OS_TENANT_NAME=${keystone.admin_tenant}",
384 "OS_AUTH_URL=http://${keystone.bind.private_address}:${keystone.bind.private_port}/v2.0",
385 "OS_REGION_NAME=${keystone.region}",
386 'OS_ENDPOINT_TYPE=admin'].join(' -e ')
387 def cmd = '/opt/devops-qa-tools/deployment/configure.sh; '
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800388 if (confRepository != '' ) {
389 cmd = "git clone -b ${confBranch ?: 'master'} ${confRepository} test_config; " +
390 'rally deployment create --fromenv --name=tempest; rally deployment config; ' +
391 'rally verify create-verifier --name tempest_verifier --type tempest ' +
Dmitry Tsapikovb6911922018-07-24 15:21:23 +0000392 "--source ${repository ?: '/tmp/tempest/'} --version ${version: '15.0.0'}; " +
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800393 'rally verify configure-verifier --extend test_config/tempest/tempest.conf --show; '
394 skip_list = '--skip-list test_config/tempest/skip-list.yaml'
395 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700396 if (pattern == 'false') {
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800397 cmd += "rally verify start --pattern set=full ${skip_list} --detailed; "
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700398 }
399 else {
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800400 cmd += "rally verify start --pattern set=${pattern} ${skip_list} --detailed; "
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700401 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700402 cmd += "rally verify report --type json --to ${dest_folder}/report-tempest.json; " +
403 "rally verify report --type html --to ${dest_folder}/report-tempest.html"
mkraynovd49daf52018-07-12 16:11:14 +0400404 salt.cmdRun(master, target, "docker run -w /home/rally -i --rm --net=host -e ${env_vars} " +
Sergey Galkin193ef872017-11-29 14:20:35 +0400405 "-v ${results}:${dest_folder} --entrypoint /bin/bash ${dockerImageLink} " +
406 "-c \"${cmd}\" > ${results}/${output_file}")
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700407 addFiles(master, target, results, output_dir)
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700408}
409
410/**
Oleg Basov40e502c2018-09-04 20:42:21 +0200411 * Make all-in-one scenario cmd for rally tests
412 *
413 * @param scenarios_path Path to scenarios folder/file
414 * @param skip_scenarios Comma-delimited list of scenarios names to skip
415 * @param bundle_file Bundle name to create
416*/
Oleg Basov06fce2a2018-11-09 21:39:03 +0100417def bundle_up_scenarios(scenarios_path, skip_scenarios, bundle_file = '' ) {
Oleg Basov40e502c2018-09-04 20:42:21 +0200418 def skip_names = ''
419 def skip_dirs = ''
420 def result = ''
421 if (skip_scenarios != ''){
422 for ( scen in skip_scenarios.split(',') ) {
423 if ( scen.contains('yaml')) {
424 skip_names += "! -name ${scen} "
425 }
426 else {
Oleg Basovde899e02019-03-26 12:31:27 +0100427 skip_dirs += "-path '${scenarios_path}/${scen}' -prune -o "
Oleg Basov40e502c2018-09-04 20:42:21 +0200428 }
429 }
430 }
Oleg Basov06fce2a2018-11-09 21:39:03 +0100431 if (bundle_file != '') {
432 result = "if [ -f ${scenarios_path} ]; then cp ${scenarios_path} ${bundle_file}; " +
Oleg Basov40e502c2018-09-04 20:42:21 +0200433 "else " +
434 "find -L ${scenarios_path} " + skip_dirs +
435 " -name '*.yaml' " + skip_names +
436 "-exec cat {} >> ${bundle_file} \\; ; " +
437 "sed -i '/---/d' ${bundle_file}; fi; "
Oleg Basov06fce2a2018-11-09 21:39:03 +0100438 } else {
439 result = "find -L ${scenarios_path} " + skip_dirs +
Oleg Basovde899e02019-03-26 12:31:27 +0100440 " -name '*.yaml' -print " + skip_names
Oleg Basov06fce2a2018-11-09 21:39:03 +0100441 }
Oleg Basov40e502c2018-09-04 20:42:21 +0200442
443 return result
444}
445
446/**
Oleg Basovde899e02019-03-26 12:31:27 +0100447 * Prepare setupDockerAndTest() commands to start Rally tests (optionally with K8S/Stacklight plugins)
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700448 *
Oleg Basovde899e02019-03-26 12:31:27 +0100449 * @param platform Map with underlay platform data
Oleg Basov20afb152018-06-10 03:09:25 +0200450 * @param scenarios Directory inside repo with specific scenarios
Oleg Basov40e502c2018-09-04 20:42:21 +0200451 * @param sl_scenarios Directory inside repo with specific scenarios for stacklight
Oleg Basov20afb152018-06-10 03:09:25 +0200452 * @param tasks_args_file Argument file that is used for throttling settings
Oleg Basov1fa6c662019-03-05 22:04:01 +0100453 * @param db_connection_str Rally-compliant external DB connection string
454 * @param tags Additional tags used for tagging tasks or building trends
455 * @param trends Build rally trends if enabled
Oleg Basovde899e02019-03-26 12:31:27 +0100456 *
457 * Returns: map
458 *
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700459 */
Oleg Basov1fa6c662019-03-05 22:04:01 +0100460def runRallyTests(
Oleg Basovde899e02019-03-26 12:31:27 +0100461 platform, scenarios = '',
462 sl_scenarios = '', tasks_args_file = '',
Oleg Basov1fa6c662019-03-05 22:04:01 +0100463 db_connection_str = '', tags = [],
Oleg Basovde899e02019-03-26 12:31:27 +0100464 trends = false, skip_list = ''
465 ) {
Oleg Basov1fa6c662019-03-05 22:04:01 +0100466
Oleg Basovde899e02019-03-26 12:31:27 +0100467 def dest_folder = '/home/rally'
468 def pluginsDir = "${dest_folder}/rally-plugins"
469 def scenariosDir = "${dest_folder}/rally-scenarios"
470 def resultsDir = "${dest_folder}/test_results"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100471 def date = new Date()
472 date = date.format("yyyyMMddHHmm")
Oleg Basovde899e02019-03-26 12:31:27 +0100473 // compile rally deployment name
474 deployment_name = "env=${platform.cluster_name}:platform=${platform.type}:" +
475 "date=${date}:cmp=${platform.cmp_count}"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100476
Oleg Basovde899e02019-03-26 12:31:27 +0100477 // set up Rally DB
478 def cmd_rally_init = ''
Oleg Basov1fa6c662019-03-05 22:04:01 +0100479 if (db_connection_str) {
480 cmd_rally_init = "sudo sed -i -e " +
481 "'s#connection=.*#connection=${db_connection_str}#' " +
482 "/etc/rally/rally.conf; "
483 }
Oleg Basovde899e02019-03-26 12:31:27 +0100484 cmd_rally_init += 'rally db ensure; '
485 // if several jobs are running in parallel (same deployment name),
486 // then try to find and use existing in db env
487 if (db_connection_str) {
488 cmd_rally_init += 'rally env use --env $(rally env list|awk \'/' +
489 deployment_name + '/ {print $2}\') ||'
490 }
491
492 def cmd_rally_start
493 def cmd_rally_stacklight
494 def cmd_rally_task_args = tasks_args_file ?: 'job-params-light.yaml'
495 def cmd_rally_report = 'rally task export ' +
496 '--uuid $(rally task list --uuids-only --status finished) ' +
497 "--type junit-xml --to ${resultsDir}/report-rally.xml; " +
498 'rally task report --uuid $(rally task list --uuids-only --status finished) ' +
499 "--out ${resultsDir}/report-rally.html"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100500 def cmd_filter_tags = ''
Oleg Basovde899e02019-03-26 12:31:27 +0100501 def trends_limit = 20
Oleg Basov1fa6c662019-03-05 22:04:01 +0100502
503 // build rally trends if required
504 if (trends && db_connection_str) {
505 if (tags) {
506 cmd_filter_tags = "--tag " + tags.join(' ')
507 }
Oleg Basovde899e02019-03-26 12:31:27 +0100508 cmd_rally_report += '; rally task trends --tasks ' +
509 '$(rally task list ' + cmd_filter_tags +
510 ' --all-deployments --uuids-only --status finished ' +
511 "| head -${trends_limit} ) " +
512 "--out ${resultsDir}/trends-rally.html"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100513 }
514
515 // add default env tags for inserting into rally tasks
516 tags = tags + [
Oleg Basovde899e02019-03-26 12:31:27 +0100517 "env=${platform.cluster_name}",
Oleg Basov1fa6c662019-03-05 22:04:01 +0100518 "platform=${platform.type}",
Oleg Basovde899e02019-03-26 12:31:27 +0100519 "cmp=${platform.cmp_count}"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100520 ]
521
Oleg Basovde899e02019-03-26 12:31:27 +0100522 // set up rally deployment cmd
Oleg Basov40e502c2018-09-04 20:42:21 +0200523 if (platform['type'] == 'openstack') {
Oleg Basov1fa6c662019-03-05 22:04:01 +0100524 cmd_rally_init += "rally deployment create --name='${deployment_name}' --fromenv; " +
525 "rally deployment check; "
Oleg Basov40e502c2018-09-04 20:42:21 +0200526 } else if (platform['type'] == 'k8s') {
Oleg Basov1fa6c662019-03-05 22:04:01 +0100527 cmd_rally_init += "rally env create --name='${deployment_name}' --from-sysenv; " +
528 "rally env check; "
Oleg Basov20afb152018-06-10 03:09:25 +0200529 } else {
530 throw new Exception("Platform ${platform} is not supported yet")
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800531 }
Oleg Basov1fa6c662019-03-05 22:04:01 +0100532
533 // set up rally task args file
Oleg Basov06fce2a2018-11-09 21:39:03 +0100534 switch(tasks_args_file) {
535 case 'none':
Oleg Basovde899e02019-03-26 12:31:27 +0100536 cmd_rally_task_args = ''
Oleg Basov20afb152018-06-10 03:09:25 +0200537 break
Oleg Basov06fce2a2018-11-09 21:39:03 +0100538 case '':
Oleg Basovde899e02019-03-26 12:31:27 +0100539 cmd_rally_task_args = "--task-args-file ${scenariosDir}/job-params-light.yaml"
Oleg Basov06fce2a2018-11-09 21:39:03 +0100540 break
541 default:
Oleg Basovde899e02019-03-26 12:31:27 +0100542 cmd_rally_task_args = "--task-args-file ${scenariosDir}/${tasks_args_file}"
Oleg Basov06fce2a2018-11-09 21:39:03 +0100543 break
544 }
Oleg Basovde899e02019-03-26 12:31:27 +0100545
546 // configure Rally for Stacklight (only with Openstack for now)
547 if (platform['stacklight']['enabled'] && (platform['type'] == 'openstack')) {
548 if (! sl_scenarios) {
549 throw new Exception("There's no Stacklight scenarios to execute")
550 }
551 def scenBundle = "${resultsDir}/scenarios_${platform.type}_stacklight.yaml"
552 cmd_rally_stacklight = bundle_up_scenarios(
553 scenariosDir + '/' + sl_scenarios,
Oleg Basov1fa6c662019-03-05 22:04:01 +0100554 skip_list,
Oleg Basovde899e02019-03-26 12:31:27 +0100555 scenBundle,
Oleg Basov1fa6c662019-03-05 22:04:01 +0100556 )
Oleg Basovde899e02019-03-26 12:31:27 +0100557 tags.add('stacklight')
558 cmd_rally_stacklight += "sed -i 's/grafana_password: .*/grafana_password: ${platform.stacklight.grafanaPass}/' " +
559 "${scenariosDir}/${tasks_args_file}; rally --log-file ${resultsDir}/tasks_stacklight.log task start --tag " + tags.join(' ') +
560 " --task ${scenBundle} ${cmd_rally_task_args} || true "
Oleg Basov20afb152018-06-10 03:09:25 +0200561 }
Oleg Basovaaeb51f2018-10-17 01:07:10 +0200562
Oleg Basovde899e02019-03-26 12:31:27 +0100563 // prepare scenarios and rally task cmd
564 if (scenarios) {
565 switch (platform['type']) {
566 case 'openstack':
567 def scenBundle = "${resultsDir}/scenarios_${platform.type}.yaml"
568 cmd_rally_start = bundle_up_scenarios(
569 scenariosDir + '/' + scenarios,
570 skip_list,
571 scenBundle,
572 )
573 cmd_rally_start += "rally --log-file ${resultsDir}/tasks_openstack.log task start --tag " + tags.join(' ') +
574 " --task ${scenBundle} ${cmd_rally_task_args} || true; "
575 break
576 // due to the bug in Rally threads, K8S plugin gets stuck on big all-in-one scenarios
577 // so we have to feed them separately for K8S case
578 case 'k8s':
579 cmd_rally_start = 'for task in $(' +
580 bundle_up_scenarios(scenariosDir + '/' + scenarios, skip_list) + '); do ' +
581 "rally --log-file ${resultsDir}/tasks_k8s.log task start --tag " + tags.join(' ') +
582 ' --task $task ' + cmd_rally_task_args + ' || true; done; '
583 break
584 }
585 } else {
586 if (! cmd_rally_stacklight) {
587 throw new Exception("No scenarios found to run Rally on")
588 }
Oleg Basov1fa6c662019-03-05 22:04:01 +0100589 }
590
Oleg Basovde899e02019-03-26 12:31:27 +0100591 // compile full rally cmd map
592 def full_cmd = [
593 '001_install_plugins': "sudo pip install --upgrade ${pluginsDir}",
594 '002_init_rally': cmd_rally_init,
595 '003_start_rally': cmd_rally_start ?: "echo no tasks to run",
596 '004_start_rally_stacklight': cmd_rally_stacklight ?: "echo no tasks to run",
597 '005_rally_report': cmd_rally_report,
598 ]
599
600 return full_cmd
601
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700602}
603
604/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500605 * DEPRECATED
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700606 * Generate test report
607 *
608 * @param target Host to run script from
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700609 * @param dockerImageLink Docker image link
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700610 * @param output_dir Directory for results
Sergey Galkind1068e22018-02-13 13:59:32 +0400611 * @param results The reports directory
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700612 */
Sergey Galkind1068e22018-02-13 13:59:32 +0400613def generateTestReport(master, target, dockerImageLink, output_dir, results = '/root/qa_results') {
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700614 def report_file = 'jenkins_test_report.html'
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700615 def salt = new com.mirantis.mk.Salt()
616 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500617 common.errorMsg('You are using deprecated method! This method will be removed')
618 error('You are using deprecated method! This method will be removed')
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700619 def dest_folder = '/opt/devops-qa-tools/generate_test_report/test_results'
620 salt.runSaltProcessStep(master, target, 'file.remove', ["${results}"])
621 salt.runSaltProcessStep(master, target, 'file.mkdir', ["${results}", "mode=777"])
622 def reports = ['report-tempest.json',
623 'report-rally.xml',
624 'report-k8s-e2e-tests.txt',
625 'report-ha.json',
626 'report-spt.txt']
627 for ( report in reports ) {
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700628 if ( fileExists("${output_dir}${report}") ) {
629 common.infoMsg("Copying ${report} to docker container")
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700630 def items = sh(script: "base64 -w0 ${output_dir}${report} > ${output_dir}${report}_encoded; " +
631 "split -b 100KB -d -a 4 ${output_dir}${report}_encoded ${output_dir}${report}__; " +
632 "rm ${output_dir}${report}_encoded; " +
633 "find ${output_dir} -type f -name ${report}__* -printf \'%f\\n\' | sort", returnStdout: true)
634 for ( item in items.tokenize() ) {
635 def content = sh(script: "cat ${output_dir}${item}", returnStdout: true)
636 salt.cmdRun(master, target, "echo \"${content}\" >> ${results}/${report}_encoded", false, null, false)
637 sh(script: "rm ${output_dir}${item}")
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700638 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700639 salt.cmdRun(master, target, "base64 -d ${results}/${report}_encoded > ${results}/${report}; " +
640 "rm ${results}/${report}_encoded", false, null, false)
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700641 }
642 }
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700643
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700644 def cmd = "jenkins_report.py --path /opt/devops-qa-tools/generate_test_report/; " +
645 "cp ${report_file} ${dest_folder}/${report_file}"
646 salt.cmdRun(master, target, "docker run -i --rm --net=host " +
647 "-v ${results}:${dest_folder} ${dockerImageLink} " +
648 "/bin/bash -c \"${cmd}\"")
649 def report_content = salt.getFileContent(master, target, "${results}/${report_file}")
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700650 writeFile file: "${output_dir}${report_file}", text: report_content
651}
652
653/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500654 * DEPRECATED
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700655 * Execute SPT tests
656 *
657 * @param target Host to run tests
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700658 * @param dockerImageLink Docker image link
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700659 * @param output_dir Directory for results
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700660 * @param ext_variables The list of external variables
Sergey Galkind1068e22018-02-13 13:59:32 +0400661 * @param results The reports directory
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700662 */
Sergey Galkind1068e22018-02-13 13:59:32 +0400663def runSptTests(master, target, dockerImageLink, output_dir, ext_variables = [], results = '/root/qa_results') {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700664 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500665 def common = new com.mirantis.mk.Common()
666 common.errorMsg('You are using deprecated method! This method will be removed')
667 error('You are using deprecated method! This method will be removed')
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700668 def dest_folder = '/home/rally/qa_results'
669 salt.runSaltProcessStep(master, target, 'file.remove', ["${results}"])
670 salt.runSaltProcessStep(master, target, 'file.mkdir', ["${results}", "mode=777"])
671 def nodes = getNodeList(master)
672 def nodes_hw = getNodeList(master, 'G@virtual:physical')
673 def _pillar = salt.getPillar(master, 'I@keystone:server', 'keystone:server')
674 def keystone = _pillar['return'][0].values()[0]
675 def ssh_key = salt.getFileContent(master, 'I@salt:master', '/root/.ssh/id_rsa')
676 def env_vars = ( ['tempest_version=15.0.0',
677 "OS_USERNAME=${keystone.admin_name}",
678 "OS_PASSWORD=${keystone.admin_password}",
679 "OS_TENANT_NAME=${keystone.admin_tenant}",
680 "OS_AUTH_URL=http://${keystone.bind.private_address}:${keystone.bind.private_port}/v2.0",
681 "OS_REGION_NAME=${keystone.region}",
682 'OS_ENDPOINT_TYPE=admin'] + ext_variables ).join(' -e ')
683 salt.runSaltProcessStep(master, target, 'file.write', ["${results}/nodes.json", nodes])
684 salt.runSaltProcessStep(master, target, 'file.write', ["${results}/nodes_hw.json", nodes_hw])
685 def cmd = '/opt/devops-qa-tools/deployment/configure.sh; ' +
686 'sudo mkdir -p /root/.ssh; sudo chmod 700 /root/.ssh; ' +
687 "echo \\\"${ssh_key}\\\" | sudo tee /root/.ssh/id_rsa > /dev/null; " +
688 'sudo chmod 600 /root/.ssh/id_rsa; ' +
689 "sudo timmy -c simplified-performance-testing/config.yaml " +
690 "--nodes-json ${dest_folder}/nodes.json --log-file ${dest_folder}/docker-spt2.log; " +
691 "./simplified-performance-testing/SPT_parser.sh > ${dest_folder}/report-spt.txt; " +
692 "custom_spt_parser.sh ${dest_folder}/nodes_hw.json > ${dest_folder}/report-spt-hw.txt; " +
693 "cp /tmp/timmy/archives/general.tar.gz ${dest_folder}/results-spt.tar.gz"
694 salt.cmdRun(master, target, "docker run -i --rm --net=host -e ${env_vars} " +
695 "-v ${results}:${dest_folder} ${dockerImageLink} /bin/bash -c " +
696 "\"${cmd}\" > ${results}/docker-spt.log")
697 addFiles(master, target, results, output_dir)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700698}
699
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700700/**
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600701 * Configure docker container
702 *
703 * @param target Host to run container
704 * @param proxy Proxy for accessing github and pip
705 * @param testing_tools_repo Repo with testing tools: configuration script, skip-list, etc.
Oleksii Zhurba1579b972017-12-14 15:21:56 -0600706 * @param tempest_repo Tempest repo to clone. Can be upstream tempest (default, recommended), your customized tempest in local/remote repo or path inside container. If not specified, tempest will not be configured.
707 * @param tempest_endpoint_type internalURL or adminURL or publicURL to use in tests
Oleksii Zhurba198dd682018-09-07 18:16:59 -0500708 * @param tempest_version Version of tempest to use. This value will be just passed to configure.sh script (cvp-configuration repo).
Oleksii Zhurba1579b972017-12-14 15:21:56 -0600709 * @param conf_script_path Path to configuration script.
710 * @param ext_variables Some custom extra variables to add into container
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600711 */
712def configureContainer(master, target, proxy, testing_tools_repo, tempest_repo,
Oleksii Zhurba198dd682018-09-07 18:16:59 -0500713 tempest_endpoint_type="internalURL", tempest_version="",
Oleksii Zhurba1579b972017-12-14 15:21:56 -0600714 conf_script_path="", ext_variables = []) {
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600715 def salt = new com.mirantis.mk.Salt()
716 if (testing_tools_repo != "" ) {
Oleksii Zhurba0cda6e02018-06-20 14:53:19 -0500717 if (testing_tools_repo.contains('http://') || testing_tools_repo.contains('https://')) {
718 salt.cmdRun(master, target, "docker exec cvp git clone ${testing_tools_repo} cvp-configuration")
719 configure_script = conf_script_path != "" ? conf_script_path : "cvp-configuration/configure.sh"
720 }
721 else {
722 configure_script = testing_tools_repo
723 }
724 ext_variables.addAll("PROXY=${proxy}", "TEMPEST_REPO=${tempest_repo}",
725 "TEMPEST_ENDPOINT_TYPE=${tempest_endpoint_type}",
726 "tempest_version=${tempest_version}")
727 salt.cmdRun(master, target, "docker exec -e " + ext_variables.join(' -e ') + " cvp bash -c ${configure_script}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600728 }
Oleksii Zhurba0cda6e02018-06-20 14:53:19 -0500729 else {
730 common.infoMsg("TOOLS_REPO is empty, no confguration is needed for container")
731 }
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600732}
733
734/**
735 * Run Tempest
736 *
737 * @param target Host to run container
738 * @param test_pattern Test pattern to run
739 * @param skip_list Path to skip-list
740 * @param output_dir Directory on target host for storing results (containers is not a good place)
741 */
742def runCVPtempest(master, target, test_pattern="set=smoke", skip_list="", output_dir, output_filename="docker-tempest") {
743 def salt = new com.mirantis.mk.Salt()
744 def xml_file = "${output_filename}.xml"
Oleksii Zhurba44045312017-12-12 15:38:26 -0600745 def html_file = "${output_filename}.html"
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600746 skip_list_cmd = ''
747 if (skip_list != '') {
748 skip_list_cmd = "--skip-list ${skip_list}"
749 }
Oleksii Zhurba77896d42018-05-25 18:11:30 -0500750 salt.cmdRun(master, target, "docker exec cvp rally verify start --pattern ${test_pattern} ${skip_list_cmd} --detailed")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600751 salt.cmdRun(master, target, "docker exec cvp rally verify report --type junit-xml --to /home/rally/${xml_file}")
Oleksii Zhurba44045312017-12-12 15:38:26 -0600752 salt.cmdRun(master, target, "docker exec cvp rally verify report --type html --to /home/rally/${html_file}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600753 salt.cmdRun(master, target, "docker cp cvp:/home/rally/${xml_file} ${output_dir}")
Oleksii Zhurba44045312017-12-12 15:38:26 -0600754 salt.cmdRun(master, target, "docker cp cvp:/home/rally/${html_file} ${output_dir}")
Oleksii Zhurba77896d42018-05-25 18:11:30 -0500755 return salt.cmdRun(master, target, "docker exec cvp rally verify show | head -5 | tail -1 | " +
756 "awk '{print \$4}'")['return'][0].values()[0].split()[0]
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600757}
758
759/**
760 * Run Rally
761 *
762 * @param target Host to run container
763 * @param test_pattern Test pattern to run
764 * @param scenarios_path Path to Rally scenarios
765 * @param output_dir Directory on target host for storing results (containers is not a good place)
766 */
767def runCVPrally(master, target, scenarios_path, output_dir, output_filename="docker-rally") {
768 def salt = new com.mirantis.mk.Salt()
769 def xml_file = "${output_filename}.xml"
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600770 def html_file = "${output_filename}.html"
Oleksii Zhurba77896d42018-05-25 18:11:30 -0500771 salt.cmdRun(master, target, "docker exec cvp rally task start ${scenarios_path}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600772 salt.cmdRun(master, target, "docker exec cvp rally task report --out ${html_file}")
Oleksii Zhurba1bf9be12018-01-17 15:20:00 -0600773 salt.cmdRun(master, target, "docker exec cvp rally task report --junit --out ${xml_file}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600774 salt.cmdRun(master, target, "docker cp cvp:/home/rally/${xml_file} ${output_dir}")
775 salt.cmdRun(master, target, "docker cp cvp:/home/rally/${html_file} ${output_dir}")
776}
777
778
779/**
780 * Shutdown node
781 *
782 * @param target Host to run command
783 * @param mode How to shutdown node
784 * @param retries # of retries to make to check node status
785 */
786def shutdown_vm_node(master, target, mode, retries=200) {
787 def salt = new com.mirantis.mk.Salt()
788 def common = new com.mirantis.mk.Common()
789 if (mode == 'reboot') {
790 try {
791 def out = salt.runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'cmd.run', null, ['reboot'], null, 3, 3)
792 } catch (Exception e) {
793 common.warningMsg('Timeout from minion: node must be rebooting now')
794 }
795 common.warningMsg("Checking that minion is down")
796 status = "True"
797 for (i = 0; i < retries; i++) {
798 status = salt.minionsReachable(master, 'I@salt:master', target, null, 5, 1)
799 if (status != "True") {
800 break
801 }
802 }
803 if (status == "True") {
804 throw new Exception("Tired to wait for minion ${target} to stop responding")
805 }
806 }
807 if (mode == 'hard_shutdown' || mode == 'soft_shutdown') {
808 kvm = locate_node_on_kvm(master, target)
809 if (mode == 'soft_shutdown') {
810 salt.cmdRun(master, target, "shutdown -h 0")
811 }
812 if (mode == 'hard_shutdown') {
813 salt.cmdRun(master, kvm, "virsh destroy ${target}")
814 }
815 common.warningMsg("Checking that vm on kvm is in power off state")
816 status = 'running'
817 for (i = 0; i < retries; i++) {
818 status = check_vm_status(master, target, kvm)
819 echo "Current status - ${status}"
820 if (status != 'running') {
821 break
822 }
823 sleep (1)
824 }
825 if (status == 'running') {
826 throw new Exception("Tired to wait for node ${target} to shutdown")
827 }
828 }
829}
830
831
832/**
833 * Locate kvm where target host is located
834 *
835 * @param target Host to check
836 */
837def locate_node_on_kvm(master, target) {
838 def salt = new com.mirantis.mk.Salt()
839 def list = salt.runSaltProcessStep(master, "I@salt:control", 'cmd.run', ["virsh list --all | grep ' ${target}'"])['return'][0]
840 for (item in list.keySet()) {
841 if (list[item]) {
842 return item
843 }
844 }
845}
846
847/**
848 * Check target host status
849 *
850 * @param target Host to check
851 * @param kvm KVM node where target host is located
852 */
853def check_vm_status(master, target, kvm) {
854 def salt = new com.mirantis.mk.Salt()
855 def list = salt.runSaltProcessStep(master, "${kvm}", 'cmd.run', ["virsh list --all | grep ' ${target}'"])['return'][0]
856 for (item in list.keySet()) {
857 if (list[item]) {
858 return list[item].split()[2]
859 }
860 }
861}
862
863/**
864 * Find vip on nodes
865 *
866 * @param target Pattern, e.g. ctl*
867 */
868def get_vip_node(master, target) {
869 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba5f73cf62018-08-03 16:11:10 -0500870 def list = salt.runSaltProcessStep(master, "${target}", 'cmd.run', ["ip a | grep '/32'"])['return'][0]
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600871 for (item in list.keySet()) {
872 if (list[item]) {
873 return item
874 }
875 }
876}
877
878/**
879 * Find vip on nodes
880 *
881 * @param target Host with cvp container
882 */
Oleksii Zhurba5250a9c2018-03-21 15:47:03 -0500883def openstack_cleanup(master, target, script_path="/home/rally/cvp-configuration/cleanup.sh") {
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600884 def salt = new com.mirantis.mk.Salt()
885 salt.runSaltProcessStep(master, "${target}", 'cmd.run', ["docker exec cvp bash -c ${script_path}"])
886}
887
888
889/**
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700890 * Cleanup
891 *
892 * @param target Host to run commands
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500893 * @param name Name of container to remove
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700894 */
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500895def runCleanup(master, target, name='cvp') {
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700896 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500897 if ( salt.cmdRun(master, target, "docker ps -f name=${name} -q", false, null, false)['return'][0].values()[0] ) {
898 salt.cmdRun(master, target, "docker rm -f ${name}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600899 }
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700900}
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500901/**
902 * Prepare venv for any python project
903 * Note: <repo_name>\/requirements.txt content will be used
904 * for this venv
905 *
906 * @param repo_url Repository url to clone
907 * @param proxy Proxy address to use
908 */
dtsapikovf2e1bb12018-11-29 18:49:48 +0400909def prepareVenv(repo_url, proxy, useSystemPackages=false) {
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500910 def python = new com.mirantis.mk.Python()
911 repo_name = "${repo_url}".tokenize("/").last()
Oleksii Zhurbae711ebb2018-06-15 16:36:38 -0500912 if (repo_url.tokenize().size() > 1){
913 if (repo_url.tokenize()[1] == '-b'){
914 repo_name = repo_url.tokenize()[0].tokenize("/").last()
915 }
916 }
Oleksii Zhurba83e3e5c2018-06-27 16:59:29 -0500917 path_venv = "${env.WORKSPACE}/venv"
918 path_req = "${env.WORKSPACE}/${repo_name}/requirements.txt"
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500919 sh "rm -rf ${repo_name}"
Oleksii Zhurba83e3e5c2018-06-27 16:59:29 -0500920 // this is temporary W/A for offline deployments
921 // Jenkins slave image has /opt/pip-mirror/ folder
922 // where pip wheels for cvp projects are located
923 if (proxy != 'offline') {
924 withEnv(["HTTPS_PROXY=${proxy}", "HTTP_PROXY=${proxy}", "https_proxy=${proxy}", "http_proxy=${proxy}"]) {
925 sh "git clone ${repo_url}"
dtsapikovf2e1bb12018-11-29 18:49:48 +0400926 python.setupVirtualenv(path_venv, "python2", [], path_req, true, useSystemPackages)
Oleksii Zhurba83e3e5c2018-06-27 16:59:29 -0500927 }
928 }
929 else {
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500930 sh "git clone ${repo_url}"
Oleksii Zhurba83e3e5c2018-06-27 16:59:29 -0500931 sh "virtualenv ${path_venv} --python python2"
932 python.runVirtualenvCommand(path_venv, "pip install --no-index --find-links=/opt/pip-mirror/ -r ${path_req}", true)
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500933 }
934}
935
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700936/** Install docker if needed
937 *
938 * @param target Target node to install docker pkg
939 */
940def installDocker(master, target) {
941 def salt = new com.mirantis.mk.Salt()
942 if ( ! salt.runSaltProcessStep(master, target, 'pkg.version', ["docker-engine"]) ) {
943 salt.runSaltProcessStep(master, target, 'pkg.install', ["docker.io"])
944 }
945}