blob: b504922c1b6f768b6714c2213271fcdfb7e33eb6 [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 *
38 * @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**/
44
45
46def runContainer(master, target, dockerImageLink, name='cvp', env_var=[], entrypoint=true){
47 def salt = new com.mirantis.mk.Salt()
48 def common = new com.mirantis.mk.Common()
49 def variables = ''
50 def entry_point = ''
51 if ( salt.cmdRun(master, target, "docker ps -f name=${name} -q", false, null, false)['return'][0].values()[0] ) {
52 salt.cmdRun(master, target, "docker rm -f ${name}")
53 }
54 if (env_var.size() > 0) {
55 variables = ' -e ' + env_var.join(' -e ')
56 }
57 if (entrypoint) {
58 entry_point = '--entrypoint /bin/bash'
59 }
60 salt.cmdRun(master, target, "docker run -tid --net=host --name=${name} " +
Oleksii Zhurbafa885ed2019-02-13 18:27:31 -060061 "-u root ${entry_point} ${variables} " +
62 "-v /srv/salt/pki/${cluster_name}/:/etc/certs ${dockerImageLink}")
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -050063}
64
65
Petr Lomakin47fee0a2017-08-01 10:46:05 -070066/**
Oleksii Zhurba4bcf07f2018-09-11 15:23:18 -050067 * Get v2 Keystone credentials from pillars
68 *
69 */
70def _get_keystone_creds_v2(master){
71 def salt = new com.mirantis.mk.Salt()
72 def common = new com.mirantis.mk.Common()
73 def keystone = []
74 common.infoMsg("Fetching Keystone v2 credentials")
75 _pillar = salt.getPillar(master, 'I@keystone:server', 'keystone:server')['return'][0].values()[0]
76 keystone.add("OS_USERNAME=${_pillar.admin_name}")
77 keystone.add("OS_PASSWORD=${_pillar.admin_password}")
78 keystone.add("OS_TENANT_NAME=${_pillar.admin_tenant}")
79 keystone.add("OS_AUTH_URL=http://${_pillar.bind.private_address}:${_pillar.bind.private_port}/v2.0")
80 keystone.add("OS_REGION_NAME=${_pillar.region}")
81 keystone.add("OS_ENDPOINT_TYPE=admin")
82 return keystone
83}
84
85/**
86 * Get v3 Keystone credentials from pillars
87 *
88 */
89def _get_keystone_creds_v3(master){
90 def salt = new com.mirantis.mk.Salt()
91 def common = new com.mirantis.mk.Common()
92 pillar_name = 'keystone:client:os_client_config:cfgs:root:content:clouds:admin_identity'
93 common.infoMsg("Fetching Keystone v3 credentials")
94 def _pillar = salt.getPillar(master, 'I@keystone:client', pillar_name)['return'][0].values()[0]
95 def keystone = []
96 if (_pillar) {
97 keystone.add("OS_USERNAME=${_pillar.auth.username}")
98 keystone.add("OS_PASSWORD=${_pillar.auth.password}")
99 keystone.add("OS_TENANT_NAME=${_pillar.auth.project_name}")
100 keystone.add("OS_PROJECT_NAME=${_pillar.auth.project_name}")
101 keystone.add("OS_AUTH_URL=${_pillar.auth.auth_url}/v3")
102 keystone.add("OS_REGION_NAME=${_pillar.region_name}")
103 keystone.add("OS_IDENTITY_API_VERSION=${_pillar.identity_api_version}")
Oleksii Zhurbafa885ed2019-02-13 18:27:31 -0600104 keystone.add("OS_ENDPOINT_TYPE=internal")
Oleksii Zhurba4bcf07f2018-09-11 15:23:18 -0500105 keystone.add("OS_PROJECT_DOMAIN_NAME=${_pillar.auth.project_domain_name}")
106 keystone.add("OS_USER_DOMAIN_NAME=${_pillar.auth.user_domain_name}")
Oleksii Zhurbafa885ed2019-02-13 18:27:31 -0600107 // we mount /srv/salt/pki/${cluster_name}/:/etc/certs with certs for cvp container
108 keystone.add("OS_CACERT='/etc/certs/proxy-with-chain.crt'")
Oleksii Zhurba4bcf07f2018-09-11 15:23:18 -0500109 return keystone
110 }
111 else {
112 common.warningMsg("Failed to fetch Keystone v3 credentials")
113 return false
114 }
115}
116
117/**
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700118 * Get file content (encoded). The content encoded by Base64.
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700119 *
120 * @param target Compound target (should target only one host)
121 * @param file File path to read
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700122 * @return The encoded content of the file
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700123 */
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700124def getFileContentEncoded(master, target, file) {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700125 def salt = new com.mirantis.mk.Salt()
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700126 def file_content = ''
127 def cmd = "base64 -w0 ${file} > ${file}_encoded; " +
128 "split -b 1MB -d ${file}_encoded ${file}__; " +
129 "rm ${file}_encoded"
130 salt.cmdRun(master, target, cmd, false, null, false)
131 def filename = file.tokenize('/').last()
132 def folder = file - filename
133 def parts = salt.runSaltProcessStep(master, target, 'file.find', ["${folder}", "type=f", "name=${filename}__*"])
134 for ( part in parts['return'][0].values()[0]) {
135 def _result = salt.cmdRun(master, target, "cat ${part}", false, null, false)
136 file_content = file_content + _result['return'][0].values()[0].replaceAll('Salt command execution success','')
137 }
138 salt.runSaltProcessStep(master, target, 'file.find', ["${folder}", "type=f", "name=${filename}__*", "delete"])
139 return file_content
140}
141
142/**
143 * Copy files from remote to local directory. The content of files will be
144 * decoded by Base64.
145 *
146 * @param target Compound target (should target only one host)
147 * @param folder The path to remote folder.
148 * @param output_dir The path to local folder.
149 */
150def addFiles(master, target, folder, output_dir) {
151 def salt = new com.mirantis.mk.Salt()
152 def _result = salt.runSaltProcessStep(master, target, 'file.find', ["${folder}", "type=f"])
153 def files = _result['return'][0].values()[0]
154 for (file in files) {
155 def file_content = getFileContentEncoded(master, target, "${file}")
156 def fileName = file.tokenize('/').last()
157 writeFile file: "${output_dir}${fileName}_encoded", text: file_content
158 def cmd = "base64 -d ${output_dir}${fileName}_encoded > ${output_dir}${fileName}; " +
159 "rm ${output_dir}${fileName}_encoded"
160 sh(script: cmd)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700161 }
162}
163
164/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500165 * DEPRECATED
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700166 * Get reclass value
167 *
168 * @param target The host for which the values will be provided
169 * @param filter Parameters divided by dots
170 * @return The pillar data
171 */
172def getReclassValue(master, target, filter) {
173 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500174 common.errorMsg('You are using deprecated method! This method will be removed')
175 error('You are using deprecated method! This method will be removed')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700176 def salt = new com.mirantis.mk.Salt()
177 def items = filter.tokenize('.')
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700178 def _result = salt.cmdRun(master, 'I@salt:master', "reclass-salt -o json -p ${target}", false, null, false)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700179 _result = common.parseJSON(_result['return'][0].values()[0])
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700180 for (int k = 0; k < items.size(); k++) {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700181 if ( _result ) {
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700182 _result = _result["${items[k]}"]
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700183 }
184 }
185 return _result
186}
187
188/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500189 * DEPRECATED
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700190 * Create list of nodes in JSON format.
191 *
192 * @param filter The Salt's matcher
193 * @return JSON list of nodes
194 */
195def getNodeList(master, filter = null) {
196 def salt = new com.mirantis.mk.Salt()
197 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500198 common.errorMsg('You are using deprecated method! This method will be removed')
199 error('You are using deprecated method! This method will be removed')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700200 def nodes = []
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700201 def filtered_list = null
202 def controllers = salt.getMinions(master, 'I@nova:controller')
203 def hw_nodes = salt.getMinions(master, 'G@virtual:physical')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700204 if ( filter ) {
205 filtered_list = salt.getMinions(master, filter)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700206 }
207 def _result = salt.cmdRun(master, 'I@salt:master', "reclass-salt -o json -t", false, null, false)
208 def reclass_top = common.parseJSON(_result['return'][0].values()[0])
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700209 def nodesList = reclass_top['base'].keySet()
210 for (int i = 0; i < nodesList.size(); i++) {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700211 if ( filtered_list ) {
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700212 if ( ! filtered_list.contains(nodesList[i]) ) {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700213 continue
214 }
215 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700216 def ip = getReclassValue(master, nodesList[i], '_param.linux_single_interface.address')
217 def network_data = [ip: ip, name: 'management']
218 def roles = [nodesList[i].tokenize('.')[0]]
219 if ( controllers.contains(nodesList[i]) ) {
220 roles.add('controller')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700221 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700222 if ( hw_nodes.contains(nodesList[i]) ) {
223 roles.add('hw_node')
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700224 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700225 nodes.add([id: i+1, ip: ip, roles: roles, network_data: [network_data]])
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700226 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700227 return common.prettify(nodes)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700228}
229
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500230/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500231 * DEPRECATED
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500232 * Execute mcp sanity tests
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500233 * Deprecated. Will be removed soon
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500234 *
235 * @param salt_url Salt master url
236 * @param salt_credentials Salt credentials
237 * @param test_set Test set for mcp sanity framework
Oleksii Zhurba0a7b0702017-11-10 16:02:16 -0600238 * @param env_vars Additional environment variables for cvp-sanity-checks
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500239 * @param output_dir Directory for results
240 */
Oleksii Zhurba0a7b0702017-11-10 16:02:16 -0600241def runSanityTests(salt_url, salt_credentials, test_set="", output_dir="validation_artifacts/", env_vars="") {
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500242 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500243 common.errorMsg('You are using deprecated method! Please migrate to validate.runTests. This method will be removed')
244 error('You are using deprecated method! Please migrate to validate.runTests. This method will be removed')
Oleksii Zhurba0a7b0702017-11-10 16:02:16 -0600245 def creds = common.getCredentials(salt_credentials)
246 def username = creds.username
247 def password = creds.password
248 def settings = ""
249 if ( env_vars != "" ) {
250 for (var in env_vars.tokenize(";")) {
251 settings += "export ${var}; "
252 }
253 }
254 def script = ". ${env.WORKSPACE}/venv/bin/activate; ${settings}" +
Oleksii Zhurba5250a9c2018-03-21 15:47:03 -0500255 "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 -0500256 withEnv(["SALT_USERNAME=${username}", "SALT_PASSWORD=${password}", "SALT_URL=${salt_url}"]) {
257 def statusCode = sh script:script, returnStatus:true
258 }
259}
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700260
261/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500262 * DEPRECATED
Oleksii Zhurba4e366ff2018-02-16 20:06:52 -0600263 * Execute pytest framework tests
264 *
265 * @param salt_url Salt master url
266 * @param salt_credentials Salt credentials
267 * @param test_set Test set to run
268 * @param env_vars Additional environment variables for cvp-sanity-checks
269 * @param output_dir Directory for results
270 */
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500271def runPyTests(salt_url, salt_credentials, test_set="", env_vars="", name='cvp', container_node="", remote_dir='/root/qa_results/', artifacts_dir='validation_artifacts/') {
272 def xml_file = "${name}_report.xml"
273 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500274 common.errorMsg('You are using deprecated method! Please migrate to validate.runTests. This method will be removed')
275 error('You are using deprecated method! Please migrate to validate.runTests. This method will be removed')
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500276 def salt = new com.mirantis.mk.Salt()
277 def creds = common.getCredentials(salt_credentials)
278 def username = creds.username
279 def password = creds.password
280 if (container_node != "") {
281 def saltMaster
282 saltMaster = salt.connection(salt_url, salt_credentials)
283 def script = "pytest --junitxml ${xml_file} --tb=short -sv ${test_set}"
284 env_vars.addAll("SALT_USERNAME=${username}", "SALT_PASSWORD=${password}",
285 "SALT_URL=${salt_url}")
286 variables = ' -e ' + env_vars.join(' -e ')
287 salt.cmdRun(saltMaster, container_node, "docker exec ${variables} ${name} bash -c '${script}'", false)
288 salt.cmdRun(saltMaster, container_node, "docker cp ${name}:/var/lib/${xml_file} ${remote_dir}${xml_file}")
289 addFiles(saltMaster, container_node, remote_dir+xml_file, artifacts_dir)
290 }
291 else {
292 if (env_vars.size() > 0) {
293 variables = 'export ' + env_vars.join(';export ')
294 }
295 def script = ". ${env.WORKSPACE}/venv/bin/activate; ${variables}; " +
296 "pytest --junitxml ${artifacts_dir}${xml_file} --tb=short -sv ${env.WORKSPACE}/${test_set}"
297 withEnv(["SALT_USERNAME=${username}", "SALT_PASSWORD=${password}", "SALT_URL=${salt_url}"]) {
298 def statusCode = sh script:script, returnStatus:true
299 }
300 }
301}
302
303/**
304 * Execute pytest framework tests
305 * For backward compatibility
306 * Will be removed soon
307 *
308 * @param salt_url Salt master url
309 * @param salt_credentials Salt credentials
310 * @param test_set Test set to run
311 * @param env_vars Additional environment variables for cvp-sanity-checks
312 * @param output_dir Directory for results
313 */
Oleksii Zhurba4e366ff2018-02-16 20:06:52 -0600314def runTests(salt_url, salt_credentials, test_set="", output_dir="validation_artifacts/", env_vars="") {
315 def common = new com.mirantis.mk.Common()
316 def creds = common.getCredentials(salt_credentials)
317 def username = creds.username
318 def password = creds.password
319 def settings = ""
320 if ( env_vars != "" ) {
321 for (var in env_vars.tokenize(";")) {
322 settings += "export ${var}; "
323 }
324 }
325 def script = ". ${env.WORKSPACE}/venv/bin/activate; ${settings}" +
326 "pytest --junitxml ${output_dir}report.xml --tb=short -sv ${env.WORKSPACE}/${test_set}"
327 withEnv(["SALT_USERNAME=${username}", "SALT_PASSWORD=${password}", "SALT_URL=${salt_url}"]) {
328 def statusCode = sh script:script, returnStatus:true
329 }
330}
331
332/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500333 * DEPRECATED
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700334 * Execute tempest tests
335 *
336 * @param target Host to run tests
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700337 * @param dockerImageLink Docker image link
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700338 * @param pattern If not false, will run only tests matched the pattern
339 * @param output_dir Directory for results
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800340 * @param confRepository Git repository with configuration files for Tempest
341 * @param confBranch Git branch which will be used during the checkout
342 * @param repository Git repository with Tempest
343 * @param version Version of Tempest (tag, branch or commit)
Sergey Galkind1068e22018-02-13 13:59:32 +0400344 * @param results The reports directory
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700345 */
Sergey Galkind1068e22018-02-13 13:59:32 +0400346def runTempestTests(master, target, dockerImageLink, output_dir, confRepository, confBranch, repository, version, pattern = "false", results = '/root/qa_results') {
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700347 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500348 def common = new com.mirantis.mk.Common()
349 common.errorMsg('You are using deprecated method! This method will be removed')
350 error('You are using deprecated method! This method will be removed')
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700351 def output_file = 'docker-tempest.log'
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700352 def dest_folder = '/home/rally/qa_results'
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800353 def skip_list = '--skip-list /opt/devops-qa-tools/deployment/skip_contrail.list'
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700354 salt.runSaltProcessStep(master, target, 'file.remove', ["${results}"])
355 salt.runSaltProcessStep(master, target, 'file.mkdir', ["${results}", "mode=777"])
356 def _pillar = salt.getPillar(master, 'I@keystone:server', 'keystone:server')
357 def keystone = _pillar['return'][0].values()[0]
Dmitry Tsapikovb6911922018-07-24 15:21:23 +0000358 def env_vars = ['tempest_version=15.0.0',
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700359 "OS_USERNAME=${keystone.admin_name}",
360 "OS_PASSWORD=${keystone.admin_password}",
361 "OS_TENANT_NAME=${keystone.admin_tenant}",
362 "OS_AUTH_URL=http://${keystone.bind.private_address}:${keystone.bind.private_port}/v2.0",
363 "OS_REGION_NAME=${keystone.region}",
364 'OS_ENDPOINT_TYPE=admin'].join(' -e ')
365 def cmd = '/opt/devops-qa-tools/deployment/configure.sh; '
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800366 if (confRepository != '' ) {
367 cmd = "git clone -b ${confBranch ?: 'master'} ${confRepository} test_config; " +
368 'rally deployment create --fromenv --name=tempest; rally deployment config; ' +
369 'rally verify create-verifier --name tempest_verifier --type tempest ' +
Dmitry Tsapikovb6911922018-07-24 15:21:23 +0000370 "--source ${repository ?: '/tmp/tempest/'} --version ${version: '15.0.0'}; " +
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800371 'rally verify configure-verifier --extend test_config/tempest/tempest.conf --show; '
372 skip_list = '--skip-list test_config/tempest/skip-list.yaml'
373 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700374 if (pattern == 'false') {
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800375 cmd += "rally verify start --pattern set=full ${skip_list} --detailed; "
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700376 }
377 else {
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800378 cmd += "rally verify start --pattern set=${pattern} ${skip_list} --detailed; "
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700379 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700380 cmd += "rally verify report --type json --to ${dest_folder}/report-tempest.json; " +
381 "rally verify report --type html --to ${dest_folder}/report-tempest.html"
mkraynovd49daf52018-07-12 16:11:14 +0400382 salt.cmdRun(master, target, "docker run -w /home/rally -i --rm --net=host -e ${env_vars} " +
Sergey Galkin193ef872017-11-29 14:20:35 +0400383 "-v ${results}:${dest_folder} --entrypoint /bin/bash ${dockerImageLink} " +
384 "-c \"${cmd}\" > ${results}/${output_file}")
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700385 addFiles(master, target, results, output_dir)
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700386}
387
388/**
Oleg Basov40e502c2018-09-04 20:42:21 +0200389 * Make all-in-one scenario cmd for rally tests
390 *
391 * @param scenarios_path Path to scenarios folder/file
392 * @param skip_scenarios Comma-delimited list of scenarios names to skip
393 * @param bundle_file Bundle name to create
394*/
Oleg Basov06fce2a2018-11-09 21:39:03 +0100395def bundle_up_scenarios(scenarios_path, skip_scenarios, bundle_file = '' ) {
Oleg Basov40e502c2018-09-04 20:42:21 +0200396 def skip_names = ''
397 def skip_dirs = ''
398 def result = ''
399 if (skip_scenarios != ''){
400 for ( scen in skip_scenarios.split(',') ) {
401 if ( scen.contains('yaml')) {
402 skip_names += "! -name ${scen} "
403 }
404 else {
Oleg Basovde899e02019-03-26 12:31:27 +0100405 skip_dirs += "-path '${scenarios_path}/${scen}' -prune -o "
Oleg Basov40e502c2018-09-04 20:42:21 +0200406 }
407 }
408 }
Oleg Basov06fce2a2018-11-09 21:39:03 +0100409 if (bundle_file != '') {
410 result = "if [ -f ${scenarios_path} ]; then cp ${scenarios_path} ${bundle_file}; " +
Oleg Basov40e502c2018-09-04 20:42:21 +0200411 "else " +
412 "find -L ${scenarios_path} " + skip_dirs +
413 " -name '*.yaml' " + skip_names +
414 "-exec cat {} >> ${bundle_file} \\; ; " +
415 "sed -i '/---/d' ${bundle_file}; fi; "
Oleg Basov06fce2a2018-11-09 21:39:03 +0100416 } else {
417 result = "find -L ${scenarios_path} " + skip_dirs +
Oleg Basovde899e02019-03-26 12:31:27 +0100418 " -name '*.yaml' -print " + skip_names
Oleg Basov06fce2a2018-11-09 21:39:03 +0100419 }
Oleg Basov40e502c2018-09-04 20:42:21 +0200420
421 return result
422}
423
424/**
Oleg Basovde899e02019-03-26 12:31:27 +0100425 * Prepare setupDockerAndTest() commands to start Rally tests (optionally with K8S/Stacklight plugins)
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700426 *
Oleg Basovde899e02019-03-26 12:31:27 +0100427 * @param platform Map with underlay platform data
Oleg Basov20afb152018-06-10 03:09:25 +0200428 * @param scenarios Directory inside repo with specific scenarios
Oleg Basov40e502c2018-09-04 20:42:21 +0200429 * @param sl_scenarios Directory inside repo with specific scenarios for stacklight
Oleg Basov20afb152018-06-10 03:09:25 +0200430 * @param tasks_args_file Argument file that is used for throttling settings
Oleg Basov1fa6c662019-03-05 22:04:01 +0100431 * @param db_connection_str Rally-compliant external DB connection string
432 * @param tags Additional tags used for tagging tasks or building trends
433 * @param trends Build rally trends if enabled
Oleg Basovde899e02019-03-26 12:31:27 +0100434 *
435 * Returns: map
436 *
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700437 */
Oleg Basov1fa6c662019-03-05 22:04:01 +0100438def runRallyTests(
Oleg Basovde899e02019-03-26 12:31:27 +0100439 platform, scenarios = '',
440 sl_scenarios = '', tasks_args_file = '',
Oleg Basov1fa6c662019-03-05 22:04:01 +0100441 db_connection_str = '', tags = [],
Oleg Basovde899e02019-03-26 12:31:27 +0100442 trends = false, skip_list = ''
443 ) {
Oleg Basov1fa6c662019-03-05 22:04:01 +0100444
Oleg Basovde899e02019-03-26 12:31:27 +0100445 def dest_folder = '/home/rally'
446 def pluginsDir = "${dest_folder}/rally-plugins"
447 def scenariosDir = "${dest_folder}/rally-scenarios"
448 def resultsDir = "${dest_folder}/test_results"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100449 def date = new Date()
450 date = date.format("yyyyMMddHHmm")
Oleg Basovde899e02019-03-26 12:31:27 +0100451 // compile rally deployment name
452 deployment_name = "env=${platform.cluster_name}:platform=${platform.type}:" +
453 "date=${date}:cmp=${platform.cmp_count}"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100454
Oleg Basovde899e02019-03-26 12:31:27 +0100455 // set up Rally DB
456 def cmd_rally_init = ''
Oleg Basov1fa6c662019-03-05 22:04:01 +0100457 if (db_connection_str) {
458 cmd_rally_init = "sudo sed -i -e " +
459 "'s#connection=.*#connection=${db_connection_str}#' " +
460 "/etc/rally/rally.conf; "
461 }
Oleg Basovde899e02019-03-26 12:31:27 +0100462 cmd_rally_init += 'rally db ensure; '
463 // if several jobs are running in parallel (same deployment name),
464 // then try to find and use existing in db env
465 if (db_connection_str) {
466 cmd_rally_init += 'rally env use --env $(rally env list|awk \'/' +
467 deployment_name + '/ {print $2}\') ||'
468 }
469
470 def cmd_rally_start
471 def cmd_rally_stacklight
472 def cmd_rally_task_args = tasks_args_file ?: 'job-params-light.yaml'
473 def cmd_rally_report = 'rally task export ' +
474 '--uuid $(rally task list --uuids-only --status finished) ' +
475 "--type junit-xml --to ${resultsDir}/report-rally.xml; " +
476 'rally task report --uuid $(rally task list --uuids-only --status finished) ' +
477 "--out ${resultsDir}/report-rally.html"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100478 def cmd_filter_tags = ''
Oleg Basovde899e02019-03-26 12:31:27 +0100479 def trends_limit = 20
Oleg Basov1fa6c662019-03-05 22:04:01 +0100480
481 // build rally trends if required
482 if (trends && db_connection_str) {
483 if (tags) {
484 cmd_filter_tags = "--tag " + tags.join(' ')
485 }
Oleg Basovde899e02019-03-26 12:31:27 +0100486 cmd_rally_report += '; rally task trends --tasks ' +
487 '$(rally task list ' + cmd_filter_tags +
488 ' --all-deployments --uuids-only --status finished ' +
489 "| head -${trends_limit} ) " +
490 "--out ${resultsDir}/trends-rally.html"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100491 }
492
493 // add default env tags for inserting into rally tasks
494 tags = tags + [
Oleg Basovde899e02019-03-26 12:31:27 +0100495 "env=${platform.cluster_name}",
Oleg Basov1fa6c662019-03-05 22:04:01 +0100496 "platform=${platform.type}",
Oleg Basovde899e02019-03-26 12:31:27 +0100497 "cmp=${platform.cmp_count}"
Oleg Basov1fa6c662019-03-05 22:04:01 +0100498 ]
499
Oleg Basovde899e02019-03-26 12:31:27 +0100500 // set up rally deployment cmd
Oleg Basov40e502c2018-09-04 20:42:21 +0200501 if (platform['type'] == 'openstack') {
Oleg Basov1fa6c662019-03-05 22:04:01 +0100502 cmd_rally_init += "rally deployment create --name='${deployment_name}' --fromenv; " +
503 "rally deployment check; "
Oleg Basov40e502c2018-09-04 20:42:21 +0200504 } else if (platform['type'] == 'k8s') {
Oleg Basov1fa6c662019-03-05 22:04:01 +0100505 cmd_rally_init += "rally env create --name='${deployment_name}' --from-sysenv; " +
506 "rally env check; "
Oleg Basov20afb152018-06-10 03:09:25 +0200507 } else {
508 throw new Exception("Platform ${platform} is not supported yet")
Dmitrii Kabanov999fda92017-11-10 00:18:30 -0800509 }
Oleg Basov1fa6c662019-03-05 22:04:01 +0100510
511 // set up rally task args file
Oleg Basov06fce2a2018-11-09 21:39:03 +0100512 switch(tasks_args_file) {
513 case 'none':
Oleg Basovde899e02019-03-26 12:31:27 +0100514 cmd_rally_task_args = ''
Oleg Basov20afb152018-06-10 03:09:25 +0200515 break
Oleg Basov06fce2a2018-11-09 21:39:03 +0100516 case '':
Oleg Basovde899e02019-03-26 12:31:27 +0100517 cmd_rally_task_args = "--task-args-file ${scenariosDir}/job-params-light.yaml"
Oleg Basov06fce2a2018-11-09 21:39:03 +0100518 break
519 default:
Oleg Basovde899e02019-03-26 12:31:27 +0100520 cmd_rally_task_args = "--task-args-file ${scenariosDir}/${tasks_args_file}"
Oleg Basov06fce2a2018-11-09 21:39:03 +0100521 break
522 }
Oleg Basovde899e02019-03-26 12:31:27 +0100523
524 // configure Rally for Stacklight (only with Openstack for now)
525 if (platform['stacklight']['enabled'] && (platform['type'] == 'openstack')) {
526 if (! sl_scenarios) {
527 throw new Exception("There's no Stacklight scenarios to execute")
528 }
529 def scenBundle = "${resultsDir}/scenarios_${platform.type}_stacklight.yaml"
530 cmd_rally_stacklight = bundle_up_scenarios(
531 scenariosDir + '/' + sl_scenarios,
Oleg Basov1fa6c662019-03-05 22:04:01 +0100532 skip_list,
Oleg Basovde899e02019-03-26 12:31:27 +0100533 scenBundle,
Oleg Basov1fa6c662019-03-05 22:04:01 +0100534 )
Oleg Basovde899e02019-03-26 12:31:27 +0100535 tags.add('stacklight')
536 cmd_rally_stacklight += "sed -i 's/grafana_password: .*/grafana_password: ${platform.stacklight.grafanaPass}/' " +
537 "${scenariosDir}/${tasks_args_file}; rally --log-file ${resultsDir}/tasks_stacklight.log task start --tag " + tags.join(' ') +
538 " --task ${scenBundle} ${cmd_rally_task_args} || true "
Oleg Basov20afb152018-06-10 03:09:25 +0200539 }
Oleg Basovaaeb51f2018-10-17 01:07:10 +0200540
Oleg Basovde899e02019-03-26 12:31:27 +0100541 // prepare scenarios and rally task cmd
542 if (scenarios) {
543 switch (platform['type']) {
544 case 'openstack':
545 def scenBundle = "${resultsDir}/scenarios_${platform.type}.yaml"
546 cmd_rally_start = bundle_up_scenarios(
547 scenariosDir + '/' + scenarios,
548 skip_list,
549 scenBundle,
550 )
551 cmd_rally_start += "rally --log-file ${resultsDir}/tasks_openstack.log task start --tag " + tags.join(' ') +
552 " --task ${scenBundle} ${cmd_rally_task_args} || true; "
553 break
554 // due to the bug in Rally threads, K8S plugin gets stuck on big all-in-one scenarios
555 // so we have to feed them separately for K8S case
556 case 'k8s':
557 cmd_rally_start = 'for task in $(' +
558 bundle_up_scenarios(scenariosDir + '/' + scenarios, skip_list) + '); do ' +
559 "rally --log-file ${resultsDir}/tasks_k8s.log task start --tag " + tags.join(' ') +
560 ' --task $task ' + cmd_rally_task_args + ' || true; done; '
561 break
562 }
563 } else {
564 if (! cmd_rally_stacklight) {
565 throw new Exception("No scenarios found to run Rally on")
566 }
Oleg Basov1fa6c662019-03-05 22:04:01 +0100567 }
568
Oleg Basovde899e02019-03-26 12:31:27 +0100569 // compile full rally cmd map
570 def full_cmd = [
571 '001_install_plugins': "sudo pip install --upgrade ${pluginsDir}",
572 '002_init_rally': cmd_rally_init,
573 '003_start_rally': cmd_rally_start ?: "echo no tasks to run",
574 '004_start_rally_stacklight': cmd_rally_stacklight ?: "echo no tasks to run",
575 '005_rally_report': cmd_rally_report,
576 ]
577
578 return full_cmd
579
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700580}
581
582/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500583 * DEPRECATED
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700584 * Generate test report
585 *
586 * @param target Host to run script from
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700587 * @param dockerImageLink Docker image link
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700588 * @param output_dir Directory for results
Sergey Galkind1068e22018-02-13 13:59:32 +0400589 * @param results The reports directory
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700590 */
Sergey Galkind1068e22018-02-13 13:59:32 +0400591def generateTestReport(master, target, dockerImageLink, output_dir, results = '/root/qa_results') {
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700592 def report_file = 'jenkins_test_report.html'
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700593 def salt = new com.mirantis.mk.Salt()
594 def common = new com.mirantis.mk.Common()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500595 common.errorMsg('You are using deprecated method! This method will be removed')
596 error('You are using deprecated method! This method will be removed')
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700597 def dest_folder = '/opt/devops-qa-tools/generate_test_report/test_results'
598 salt.runSaltProcessStep(master, target, 'file.remove', ["${results}"])
599 salt.runSaltProcessStep(master, target, 'file.mkdir', ["${results}", "mode=777"])
600 def reports = ['report-tempest.json',
601 'report-rally.xml',
602 'report-k8s-e2e-tests.txt',
603 'report-ha.json',
604 'report-spt.txt']
605 for ( report in reports ) {
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700606 if ( fileExists("${output_dir}${report}") ) {
607 common.infoMsg("Copying ${report} to docker container")
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700608 def items = sh(script: "base64 -w0 ${output_dir}${report} > ${output_dir}${report}_encoded; " +
609 "split -b 100KB -d -a 4 ${output_dir}${report}_encoded ${output_dir}${report}__; " +
610 "rm ${output_dir}${report}_encoded; " +
611 "find ${output_dir} -type f -name ${report}__* -printf \'%f\\n\' | sort", returnStdout: true)
612 for ( item in items.tokenize() ) {
613 def content = sh(script: "cat ${output_dir}${item}", returnStdout: true)
614 salt.cmdRun(master, target, "echo \"${content}\" >> ${results}/${report}_encoded", false, null, false)
615 sh(script: "rm ${output_dir}${item}")
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700616 }
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700617 salt.cmdRun(master, target, "base64 -d ${results}/${report}_encoded > ${results}/${report}; " +
618 "rm ${results}/${report}_encoded", false, null, false)
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700619 }
620 }
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700621
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700622 def cmd = "jenkins_report.py --path /opt/devops-qa-tools/generate_test_report/; " +
623 "cp ${report_file} ${dest_folder}/${report_file}"
624 salt.cmdRun(master, target, "docker run -i --rm --net=host " +
625 "-v ${results}:${dest_folder} ${dockerImageLink} " +
626 "/bin/bash -c \"${cmd}\"")
627 def report_content = salt.getFileContent(master, target, "${results}/${report_file}")
Tetiana Korchak3383cc92017-08-25 09:36:19 -0700628 writeFile file: "${output_dir}${report_file}", text: report_content
629}
630
631/**
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500632 * DEPRECATED
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700633 * Execute SPT tests
634 *
635 * @param target Host to run tests
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700636 * @param dockerImageLink Docker image link
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700637 * @param output_dir Directory for results
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700638 * @param ext_variables The list of external variables
Sergey Galkind1068e22018-02-13 13:59:32 +0400639 * @param results The reports directory
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700640 */
Sergey Galkind1068e22018-02-13 13:59:32 +0400641def runSptTests(master, target, dockerImageLink, output_dir, ext_variables = [], results = '/root/qa_results') {
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700642 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba9c456a72019-03-26 18:05:34 -0500643 def common = new com.mirantis.mk.Common()
644 common.errorMsg('You are using deprecated method! This method will be removed')
645 error('You are using deprecated method! This method will be removed')
Dmitrii Kabanov23901c22017-10-20 10:25:36 -0700646 def dest_folder = '/home/rally/qa_results'
647 salt.runSaltProcessStep(master, target, 'file.remove', ["${results}"])
648 salt.runSaltProcessStep(master, target, 'file.mkdir', ["${results}", "mode=777"])
649 def nodes = getNodeList(master)
650 def nodes_hw = getNodeList(master, 'G@virtual:physical')
651 def _pillar = salt.getPillar(master, 'I@keystone:server', 'keystone:server')
652 def keystone = _pillar['return'][0].values()[0]
653 def ssh_key = salt.getFileContent(master, 'I@salt:master', '/root/.ssh/id_rsa')
654 def env_vars = ( ['tempest_version=15.0.0',
655 "OS_USERNAME=${keystone.admin_name}",
656 "OS_PASSWORD=${keystone.admin_password}",
657 "OS_TENANT_NAME=${keystone.admin_tenant}",
658 "OS_AUTH_URL=http://${keystone.bind.private_address}:${keystone.bind.private_port}/v2.0",
659 "OS_REGION_NAME=${keystone.region}",
660 'OS_ENDPOINT_TYPE=admin'] + ext_variables ).join(' -e ')
661 salt.runSaltProcessStep(master, target, 'file.write', ["${results}/nodes.json", nodes])
662 salt.runSaltProcessStep(master, target, 'file.write', ["${results}/nodes_hw.json", nodes_hw])
663 def cmd = '/opt/devops-qa-tools/deployment/configure.sh; ' +
664 'sudo mkdir -p /root/.ssh; sudo chmod 700 /root/.ssh; ' +
665 "echo \\\"${ssh_key}\\\" | sudo tee /root/.ssh/id_rsa > /dev/null; " +
666 'sudo chmod 600 /root/.ssh/id_rsa; ' +
667 "sudo timmy -c simplified-performance-testing/config.yaml " +
668 "--nodes-json ${dest_folder}/nodes.json --log-file ${dest_folder}/docker-spt2.log; " +
669 "./simplified-performance-testing/SPT_parser.sh > ${dest_folder}/report-spt.txt; " +
670 "custom_spt_parser.sh ${dest_folder}/nodes_hw.json > ${dest_folder}/report-spt-hw.txt; " +
671 "cp /tmp/timmy/archives/general.tar.gz ${dest_folder}/results-spt.tar.gz"
672 salt.cmdRun(master, target, "docker run -i --rm --net=host -e ${env_vars} " +
673 "-v ${results}:${dest_folder} ${dockerImageLink} /bin/bash -c " +
674 "\"${cmd}\" > ${results}/docker-spt.log")
675 addFiles(master, target, results, output_dir)
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700676}
677
Dmitrii Kabanovd5f1c5f2017-08-30 14:51:41 -0700678/**
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600679 * Configure docker container
680 *
681 * @param target Host to run container
682 * @param proxy Proxy for accessing github and pip
683 * @param testing_tools_repo Repo with testing tools: configuration script, skip-list, etc.
Oleksii Zhurba1579b972017-12-14 15:21:56 -0600684 * @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.
685 * @param tempest_endpoint_type internalURL or adminURL or publicURL to use in tests
Oleksii Zhurba198dd682018-09-07 18:16:59 -0500686 * @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 -0600687 * @param conf_script_path Path to configuration script.
688 * @param ext_variables Some custom extra variables to add into container
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600689 */
690def configureContainer(master, target, proxy, testing_tools_repo, tempest_repo,
Oleksii Zhurba198dd682018-09-07 18:16:59 -0500691 tempest_endpoint_type="internalURL", tempest_version="",
Oleksii Zhurba1579b972017-12-14 15:21:56 -0600692 conf_script_path="", ext_variables = []) {
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600693 def salt = new com.mirantis.mk.Salt()
694 if (testing_tools_repo != "" ) {
Oleksii Zhurba0cda6e02018-06-20 14:53:19 -0500695 if (testing_tools_repo.contains('http://') || testing_tools_repo.contains('https://')) {
696 salt.cmdRun(master, target, "docker exec cvp git clone ${testing_tools_repo} cvp-configuration")
697 configure_script = conf_script_path != "" ? conf_script_path : "cvp-configuration/configure.sh"
698 }
699 else {
700 configure_script = testing_tools_repo
701 }
702 ext_variables.addAll("PROXY=${proxy}", "TEMPEST_REPO=${tempest_repo}",
703 "TEMPEST_ENDPOINT_TYPE=${tempest_endpoint_type}",
704 "tempest_version=${tempest_version}")
705 salt.cmdRun(master, target, "docker exec -e " + ext_variables.join(' -e ') + " cvp bash -c ${configure_script}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600706 }
Oleksii Zhurba0cda6e02018-06-20 14:53:19 -0500707 else {
708 common.infoMsg("TOOLS_REPO is empty, no confguration is needed for container")
709 }
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600710}
711
712/**
713 * Run Tempest
714 *
715 * @param target Host to run container
716 * @param test_pattern Test pattern to run
717 * @param skip_list Path to skip-list
718 * @param output_dir Directory on target host for storing results (containers is not a good place)
719 */
720def runCVPtempest(master, target, test_pattern="set=smoke", skip_list="", output_dir, output_filename="docker-tempest") {
721 def salt = new com.mirantis.mk.Salt()
722 def xml_file = "${output_filename}.xml"
Oleksii Zhurba44045312017-12-12 15:38:26 -0600723 def html_file = "${output_filename}.html"
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600724 skip_list_cmd = ''
725 if (skip_list != '') {
726 skip_list_cmd = "--skip-list ${skip_list}"
727 }
Oleksii Zhurba77896d42018-05-25 18:11:30 -0500728 salt.cmdRun(master, target, "docker exec cvp rally verify start --pattern ${test_pattern} ${skip_list_cmd} --detailed")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600729 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 -0600730 salt.cmdRun(master, target, "docker exec cvp rally verify report --type html --to /home/rally/${html_file}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600731 salt.cmdRun(master, target, "docker cp cvp:/home/rally/${xml_file} ${output_dir}")
Oleksii Zhurba44045312017-12-12 15:38:26 -0600732 salt.cmdRun(master, target, "docker cp cvp:/home/rally/${html_file} ${output_dir}")
Oleksii Zhurba77896d42018-05-25 18:11:30 -0500733 return salt.cmdRun(master, target, "docker exec cvp rally verify show | head -5 | tail -1 | " +
734 "awk '{print \$4}'")['return'][0].values()[0].split()[0]
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600735}
736
737/**
738 * Run Rally
739 *
740 * @param target Host to run container
741 * @param test_pattern Test pattern to run
742 * @param scenarios_path Path to Rally scenarios
743 * @param output_dir Directory on target host for storing results (containers is not a good place)
744 */
745def runCVPrally(master, target, scenarios_path, output_dir, output_filename="docker-rally") {
746 def salt = new com.mirantis.mk.Salt()
747 def xml_file = "${output_filename}.xml"
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600748 def html_file = "${output_filename}.html"
Oleksii Zhurba77896d42018-05-25 18:11:30 -0500749 salt.cmdRun(master, target, "docker exec cvp rally task start ${scenarios_path}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600750 salt.cmdRun(master, target, "docker exec cvp rally task report --out ${html_file}")
Oleksii Zhurba1bf9be12018-01-17 15:20:00 -0600751 salt.cmdRun(master, target, "docker exec cvp rally task report --junit --out ${xml_file}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600752 salt.cmdRun(master, target, "docker cp cvp:/home/rally/${xml_file} ${output_dir}")
753 salt.cmdRun(master, target, "docker cp cvp:/home/rally/${html_file} ${output_dir}")
754}
755
756
757/**
758 * Shutdown node
759 *
760 * @param target Host to run command
761 * @param mode How to shutdown node
762 * @param retries # of retries to make to check node status
763 */
764def shutdown_vm_node(master, target, mode, retries=200) {
765 def salt = new com.mirantis.mk.Salt()
766 def common = new com.mirantis.mk.Common()
767 if (mode == 'reboot') {
768 try {
769 def out = salt.runSaltCommand(master, 'local', ['expression': target, 'type': 'compound'], 'cmd.run', null, ['reboot'], null, 3, 3)
770 } catch (Exception e) {
771 common.warningMsg('Timeout from minion: node must be rebooting now')
772 }
773 common.warningMsg("Checking that minion is down")
774 status = "True"
775 for (i = 0; i < retries; i++) {
776 status = salt.minionsReachable(master, 'I@salt:master', target, null, 5, 1)
777 if (status != "True") {
778 break
779 }
780 }
781 if (status == "True") {
782 throw new Exception("Tired to wait for minion ${target} to stop responding")
783 }
784 }
785 if (mode == 'hard_shutdown' || mode == 'soft_shutdown') {
786 kvm = locate_node_on_kvm(master, target)
787 if (mode == 'soft_shutdown') {
788 salt.cmdRun(master, target, "shutdown -h 0")
789 }
790 if (mode == 'hard_shutdown') {
791 salt.cmdRun(master, kvm, "virsh destroy ${target}")
792 }
793 common.warningMsg("Checking that vm on kvm is in power off state")
794 status = 'running'
795 for (i = 0; i < retries; i++) {
796 status = check_vm_status(master, target, kvm)
797 echo "Current status - ${status}"
798 if (status != 'running') {
799 break
800 }
801 sleep (1)
802 }
803 if (status == 'running') {
804 throw new Exception("Tired to wait for node ${target} to shutdown")
805 }
806 }
807}
808
809
810/**
811 * Locate kvm where target host is located
812 *
813 * @param target Host to check
814 */
815def locate_node_on_kvm(master, target) {
816 def salt = new com.mirantis.mk.Salt()
817 def list = salt.runSaltProcessStep(master, "I@salt:control", 'cmd.run', ["virsh list --all | grep ' ${target}'"])['return'][0]
818 for (item in list.keySet()) {
819 if (list[item]) {
820 return item
821 }
822 }
823}
824
825/**
826 * Check target host status
827 *
828 * @param target Host to check
829 * @param kvm KVM node where target host is located
830 */
831def check_vm_status(master, target, kvm) {
832 def salt = new com.mirantis.mk.Salt()
833 def list = salt.runSaltProcessStep(master, "${kvm}", 'cmd.run', ["virsh list --all | grep ' ${target}'"])['return'][0]
834 for (item in list.keySet()) {
835 if (list[item]) {
836 return list[item].split()[2]
837 }
838 }
839}
840
841/**
842 * Find vip on nodes
843 *
844 * @param target Pattern, e.g. ctl*
845 */
846def get_vip_node(master, target) {
847 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba5f73cf62018-08-03 16:11:10 -0500848 def list = salt.runSaltProcessStep(master, "${target}", 'cmd.run', ["ip a | grep '/32'"])['return'][0]
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600849 for (item in list.keySet()) {
850 if (list[item]) {
851 return item
852 }
853 }
854}
855
856/**
857 * Find vip on nodes
858 *
859 * @param target Host with cvp container
860 */
Oleksii Zhurba5250a9c2018-03-21 15:47:03 -0500861def openstack_cleanup(master, target, script_path="/home/rally/cvp-configuration/cleanup.sh") {
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600862 def salt = new com.mirantis.mk.Salt()
863 salt.runSaltProcessStep(master, "${target}", 'cmd.run', ["docker exec cvp bash -c ${script_path}"])
864}
865
866
867/**
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700868 * Cleanup
869 *
870 * @param target Host to run commands
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500871 * @param name Name of container to remove
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700872 */
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500873def runCleanup(master, target, name='cvp') {
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700874 def salt = new com.mirantis.mk.Salt()
Oleksii Zhurba1f4a6ff2018-06-27 16:45:17 -0500875 if ( salt.cmdRun(master, target, "docker ps -f name=${name} -q", false, null, false)['return'][0].values()[0] ) {
876 salt.cmdRun(master, target, "docker rm -f ${name}")
Oleksii Zhurba7b44ef12017-11-13 17:50:16 -0600877 }
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700878}
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500879/**
880 * Prepare venv for any python project
881 * Note: <repo_name>\/requirements.txt content will be used
882 * for this venv
883 *
884 * @param repo_url Repository url to clone
885 * @param proxy Proxy address to use
886 */
dtsapikovf2e1bb12018-11-29 18:49:48 +0400887def prepareVenv(repo_url, proxy, useSystemPackages=false) {
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500888 def python = new com.mirantis.mk.Python()
889 repo_name = "${repo_url}".tokenize("/").last()
Oleksii Zhurbae711ebb2018-06-15 16:36:38 -0500890 if (repo_url.tokenize().size() > 1){
891 if (repo_url.tokenize()[1] == '-b'){
892 repo_name = repo_url.tokenize()[0].tokenize("/").last()
893 }
894 }
Oleksii Zhurba83e3e5c2018-06-27 16:59:29 -0500895 path_venv = "${env.WORKSPACE}/venv"
896 path_req = "${env.WORKSPACE}/${repo_name}/requirements.txt"
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500897 sh "rm -rf ${repo_name}"
Oleksii Zhurba83e3e5c2018-06-27 16:59:29 -0500898 // this is temporary W/A for offline deployments
899 // Jenkins slave image has /opt/pip-mirror/ folder
900 // where pip wheels for cvp projects are located
901 if (proxy != 'offline') {
902 withEnv(["HTTPS_PROXY=${proxy}", "HTTP_PROXY=${proxy}", "https_proxy=${proxy}", "http_proxy=${proxy}"]) {
903 sh "git clone ${repo_url}"
dtsapikovf2e1bb12018-11-29 18:49:48 +0400904 python.setupVirtualenv(path_venv, "python2", [], path_req, true, useSystemPackages)
Oleksii Zhurba83e3e5c2018-06-27 16:59:29 -0500905 }
906 }
907 else {
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500908 sh "git clone ${repo_url}"
Oleksii Zhurba83e3e5c2018-06-27 16:59:29 -0500909 sh "virtualenv ${path_venv} --python python2"
910 python.runVirtualenvCommand(path_venv, "pip install --no-index --find-links=/opt/pip-mirror/ -r ${path_req}", true)
Oleksii Zhurbabcb97e22017-10-05 14:10:39 -0500911 }
912}
913
Petr Lomakin47fee0a2017-08-01 10:46:05 -0700914/** Install docker if needed
915 *
916 * @param target Target node to install docker pkg
917 */
918def installDocker(master, target) {
919 def salt = new com.mirantis.mk.Salt()
920 if ( ! salt.runSaltProcessStep(master, target, 'pkg.version', ["docker-engine"]) ) {
921 salt.runSaltProcessStep(master, target, 'pkg.install', ["docker.io"])
922 }
923}