blob: 9ce6aef346f2dcdaac43aecc9716136444d2d0ae [file] [log] [blame]
Sergey Kolekonovba203982016-12-21 18:32:17 +04001package com.mirantis.mk
2
3/**
4 *
5 * Openstack functions
6 *
7 */
8
9/**
Tomáš Kukrálc3964e52017-02-22 14:07:37 +010010 * Convert maps
11 *
12 */
13
14@NonCPS def entries(m) {
15 return m.collect {k, v -> [k, v]}
16}
17
18/**
Sergey Kolekonovba203982016-12-21 18:32:17 +040019 * Install OpenStack service clients in isolated environment
20 *
21 * @param path Path where virtualenv is created
22 * @param version Version of the OpenStack clients
23 */
24
Tomáš Kukrálbee0b992017-08-10 16:50:40 +020025def setupOpenstackVirtualenv(path, version = 'latest') {
iberezovskiyd4240b52017-02-20 17:18:28 +040026 def python = new com.mirantis.mk.Python()
Vasyl Saienko030fc182017-07-12 14:54:42 +030027 python.setupDocutilsVirtualenv(path)
Sergey Kolekonovba203982016-12-21 18:32:17 +040028
29 def openstack_kilo_packages = [
Jakub Josef268bc842017-10-10 14:36:17 +020030 //XXX: hack to fix https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1635463
31 'cliff==2.8',
Sergey Kolekonovba203982016-12-21 18:32:17 +040032 'python-cinderclient>=1.3.1,<1.4.0',
33 'python-glanceclient>=0.19.0,<0.20.0',
34 'python-heatclient>=0.6.0,<0.7.0',
35 'python-keystoneclient>=1.6.0,<1.7.0',
36 'python-neutronclient>=2.2.6,<2.3.0',
37 'python-novaclient>=2.19.0,<2.20.0',
38 'python-swiftclient>=2.5.0,<2.6.0',
Jakub Josefbd927322017-05-30 13:20:27 +000039 'python-openstackclient>=1.7.0,<1.8.0',
Sergey Kolekonovba203982016-12-21 18:32:17 +040040 'oslo.config>=2.2.0,<2.3.0',
41 'oslo.i18n>=2.3.0,<2.4.0',
42 'oslo.serialization>=1.8.0,<1.9.0',
43 'oslo.utils>=1.4.0,<1.5.0',
Jakub Josef60280212017-08-10 19:01:19 +020044 'docutils'
Sergey Kolekonovba203982016-12-21 18:32:17 +040045 ]
46
Tomáš Kukrál381a8c92017-06-21 09:01:52 +020047 def openstack_latest_packages = [
Jakub Josef268bc842017-10-10 14:36:17 +020048 //XXX: hack to fix https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1635463
49 'cliff==2.8',
Vasyl Saienko36a019d2018-05-30 09:51:18 +030050 // NOTE(vsaienko): cmd2 is dependency for cliff, since we don't using upper-contstraints
51 // we have to pin cmd2 < 0.9.0 as later versions are not compatible with python2.
52 // TODO(vsaienko): use upper-constraints here, as in requirements we set only lowest library
53 // versions.
54 'cmd2<0.9.0;python_version=="2.7"',
55 'cmd2>=0.9.1;python_version=="3.4"',
56 'cmd2>=0.9.1;python_version=="3.5"',
Tomáš Kukrál381a8c92017-06-21 09:01:52 +020057 'python-openstackclient',
vnaumova64a4a62019-03-05 18:39:55 +010058 'python-octaviaclient',
Tomáš Kukrál381a8c92017-06-21 09:01:52 +020059 'python-heatclient',
Jakub Josef60280212017-08-10 19:01:19 +020060 'docutils'
Tomáš Kukrálc6a94c62017-06-19 14:44:24 +020061 ]
Sergey Kolekonovba203982016-12-21 18:32:17 +040062
Tomáš Kukrálc6a94c62017-06-19 14:44:24 +020063 if (version == 'kilo') {
Sergey Kolekonovba203982016-12-21 18:32:17 +040064 requirements = openstack_kilo_packages
Tomáš Kukrálc6a94c62017-06-19 14:44:24 +020065 } else if (version == 'liberty') {
Sergey Kolekonovba203982016-12-21 18:32:17 +040066 requirements = openstack_kilo_packages
Tomáš Kukrálc6a94c62017-06-19 14:44:24 +020067 } else if (version == 'mitaka') {
Sergey Kolekonovba203982016-12-21 18:32:17 +040068 requirements = openstack_kilo_packages
Tomáš Kukrál381a8c92017-06-21 09:01:52 +020069 } else {
Sergey Kolekonovba203982016-12-21 18:32:17 +040070 requirements = openstack_latest_packages
71 }
Tomáš Kukrálbee0b992017-08-10 16:50:40 +020072 python.setupVirtualenv(path, 'python2', requirements, null, true)
Sergey Kolekonovba203982016-12-21 18:32:17 +040073}
74
75/**
76 * create connection to OpenStack API endpoint
77 *
Jakub Josef6c963762018-01-18 16:02:22 +010078 * @param path Path to created venv
Sergey Kolekonovba203982016-12-21 18:32:17 +040079 * @param url OpenStack API endpoint address
80 * @param credentialsId Credentials to the OpenStack API
81 * @param project OpenStack project to connect to
82 */
Jakub Josef6c963762018-01-18 16:02:22 +010083def createOpenstackEnv(path, url, credentialsId, project, project_domain="default",
Tomáš Kukrál381a8c92017-06-21 09:01:52 +020084 project_id="", user_domain="default", api_ver="2", cacert="/etc/ssl/certs/ca-certificates.crt") {
iberezovskiyd4240b52017-02-20 17:18:28 +040085 def common = new com.mirantis.mk.Common()
Jakub Josef6c963762018-01-18 16:02:22 +010086 rcFile = "${path}/keystonerc"
Sergey Kolekonovba203982016-12-21 18:32:17 +040087 creds = common.getPasswordCredentials(credentialsId)
Alexander Tivelkovf89a1882017-01-11 13:29:35 +030088 rc = """set +x
89export OS_USERNAME=${creds.username}
Ales Komarek0e558ee2016-12-23 13:02:55 +010090export OS_PASSWORD=${creds.password.toString()}
91export OS_TENANT_NAME=${project}
92export OS_AUTH_URL=${url}
93export OS_AUTH_STRATEGY=keystone
kairat_kushaev0a26bf72017-05-18 13:20:09 +040094export OS_PROJECT_NAME=${project}
Jakub Josefbd927322017-05-30 13:20:27 +000095export OS_PROJECT_ID=${project_id}
kairat_kushaev0a26bf72017-05-18 13:20:09 +040096export OS_PROJECT_DOMAIN_ID=${project_domain}
Jakub Josefbd927322017-05-30 13:20:27 +000097export OS_USER_DOMAIN_NAME=${user_domain}
Kirill Mashchenko234708f2017-07-20 17:00:01 +030098export OS_IDENTITY_API_VERSION=${api_ver}
Tomáš Kukrál381a8c92017-06-21 09:01:52 +020099export OS_CACERT=${cacert}
Alexander Tivelkovf89a1882017-01-11 13:29:35 +0300100set -x
Ales Komarek0e558ee2016-12-23 13:02:55 +0100101"""
102 writeFile file: rcFile, text: rc
103 return rcFile
Sergey Kolekonovba203982016-12-21 18:32:17 +0400104}
105
106/**
107 * Run command with OpenStack env params and optional python env
108 *
109 * @param cmd Command to be executed
110 * @param env Environmental parameters with endpoint credentials
111 * @param path Optional path to virtualenv with specific clients
112 */
113def runOpenstackCommand(cmd, venv, path = null) {
iberezovskiyd4240b52017-02-20 17:18:28 +0400114 def python = new com.mirantis.mk.Python()
Sergey Kolekonovba203982016-12-21 18:32:17 +0400115 openstackCmd = ". ${venv}; ${cmd}"
116 if (path) {
117 output = python.runVirtualenvCommand(path, openstackCmd)
118 }
119 else {
120 echo("[Command]: ${openstackCmd}")
121 output = sh (
122 script: openstackCmd,
123 returnStdout: true
124 ).trim()
125 }
126 return output
127}
128
129/**
130 * Get OpenStack Keystone token for current credentials
131 *
132 * @param env Connection parameters for OpenStack API endpoint
133 * @param path Optional path to the custom virtualenv
134 */
135def getKeystoneToken(client, path = null) {
iberezovskiyd4240b52017-02-20 17:18:28 +0400136 def python = new com.mirantis.mk.Python()
Jakub Josefbd927322017-05-30 13:20:27 +0000137 cmd = "openstack token issue"
Sergey Kolekonovba203982016-12-21 18:32:17 +0400138 outputTable = runOpenstackCommand(cmd, client, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100139 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400140 return output
141}
142
143/**
Ales Komarek51b7b152017-06-27 11:14:50 +0200144 * Create OpenStack environment file
Sergey Kolekonovba203982016-12-21 18:32:17 +0400145 *
146 * @param env Connection parameters for OpenStack API endpoint
147 * @param path Optional path to the custom virtualenv
148 */
149def createHeatEnv(file, environment = [], original_file = null) {
150 if (original_file) {
151 envString = readFile file: original_file
Tomáš Kukrál03029442017-02-21 17:14:29 +0100152 } else {
Sergey Kolekonovba203982016-12-21 18:32:17 +0400153 envString = "parameters:\n"
154 }
Tomáš Kukrál03029442017-02-21 17:14:29 +0100155
Tomáš Kukrálc3964e52017-02-22 14:07:37 +0100156 p = entries(environment)
Tomáš Kukrálb1fe9642017-02-22 11:21:17 +0100157 for (int i = 0; i < p.size(); i++) {
158 envString = "${envString} ${p.get(i)[0]}: ${p.get(i)[1]}\n"
Sergey Kolekonovba203982016-12-21 18:32:17 +0400159 }
Tomáš Kukrál03029442017-02-21 17:14:29 +0100160
Tomáš Kukrále19ddea2017-02-21 11:09:40 +0100161 echo("writing to env file:\n${envString}")
Sergey Kolekonovba203982016-12-21 18:32:17 +0400162 writeFile file: file, text: envString
163}
164
165/**
Vasyl Saienko0adc34b2019-01-23 15:52:37 +0200166 * Create new OpenStack Heat stack. Will wait for action to be complited in
167 * specified amount of time (by default 120min)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400168 *
169 * @param env Connection parameters for OpenStack API endpoint
170 * @param template HOT template for the new Heat stack
171 * @param environment Environmentale parameters of the new Heat stack
172 * @param name Name of the new Heat stack
173 * @param path Optional path to the custom virtualenv
Vasyl Saienko0adc34b2019-01-23 15:52:37 +0200174 * @param timeout Optional number in minutes to wait for stack action is applied.
Sergey Kolekonovba203982016-12-21 18:32:17 +0400175 */
Vasyl Saienko0adc34b2019-01-23 15:52:37 +0200176def createHeatStack(client, name, template, params = [], environment = null, path = null, action="create", timeout=120) {
iberezovskiyd4240b52017-02-20 17:18:28 +0400177 def python = new com.mirantis.mk.Python()
Jakub Josef0a898762017-08-11 16:27:44 +0200178 def templateFile = "${env.WORKSPACE}/template/template/${template}.hot"
179 def envFile
180 def envSource
Sergey Kolekonovba203982016-12-21 18:32:17 +0400181 if (environment) {
Tomáš Kukrála1152742017-08-22 16:21:50 +0200182 envFile = "${env.WORKSPACE}/template/env/${name}.env"
183 if (environment.contains("/")) {
184 //init() returns all elements but the last in a collection.
185 def envPath = environment.tokenize("/").init().join("/")
186 if (envPath) {
187 envFile = "${env.WORKSPACE}/template/env/${envPath}/${name}.env"
188 }
Ales Komarek51b7b152017-06-27 11:14:50 +0200189 }
Tomáš Kukrála1152742017-08-22 16:21:50 +0200190 envSource = "${env.WORKSPACE}/template/env/${environment}.env"
Sergey Kolekonovba203982016-12-21 18:32:17 +0400191 createHeatEnv(envFile, params, envSource)
Jakub Josef9a59aeb2017-08-11 15:50:20 +0200192 } else {
Sergey Kolekonovba203982016-12-21 18:32:17 +0400193 envFile = "${env.WORKSPACE}/template/${name}.env"
194 createHeatEnv(envFile, params)
195 }
Tomáš Kukrála1152742017-08-22 16:21:50 +0200196
Mykyta Karpincf44f812017-08-28 14:45:21 +0300197 def cmd
Vasyl Saienkob91df802019-01-23 17:22:57 +0200198 def cmd_args = "-t ${templateFile} -e ${envFile} --timeout ${timeout} --wait ${name}"
Mykyta Karpincf44f812017-08-28 14:45:21 +0300199
Tomáš Kukrála1152742017-08-22 16:21:50 +0200200 if (action == "create") {
Vasyl Saienko0adc34b2019-01-23 15:52:37 +0200201 cmd = "openstack stack create ${cmd_args}"
Tomáš Kukrála1152742017-08-22 16:21:50 +0200202 } else {
Vasyl Saienko0adc34b2019-01-23 15:52:37 +0200203 cmd = "openstack stack update ${cmd_args}"
Tomáš Kukrála1152742017-08-22 16:21:50 +0200204 }
205
Sergey Kolekonovba203982016-12-21 18:32:17 +0400206 dir("${env.WORKSPACE}/template/template") {
Vasyl Saienkod4254192019-01-23 18:02:01 +0200207 def out = runOpenstackCommand(cmd, client, path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400208 }
Sergey Kolekonovba203982016-12-21 18:32:17 +0400209}
210
211/**
Jakub Josefdb4baf22017-05-10 15:16:09 +0200212 * Returns list of stacks for stack name filter
213 *
214 * @param client Connection parameters for OpenStack API endpoint
215 * @param filter Stack name filter
216 * @param path Optional path to the custom virtualenv
217 */
218def getStacksForNameContains(client, filter, path = null){
Jakub Josef6465fca2017-05-10 16:09:20 +0200219 cmd = 'heat stack-list | awk \'NR>3 {print $4}\' | sed \'$ d\' | grep ' + filter + '|| true'
Jakub Josefdb4baf22017-05-10 15:16:09 +0200220 return runOpenstackCommand(cmd, client, path).trim().tokenize("\n")
221}
222
223
224/**
Jakub Josef5e238a22017-04-19 16:35:15 +0200225 * Get list of stack names with given stack status
226 *
Jakub Josefdb4baf22017-05-10 15:16:09 +0200227 * @param client Connection parameters for OpenStack API endpoint
Jakub Josef5e238a22017-04-19 16:35:15 +0200228 * @param status Stack status
229 * @param path Optional path to the custom virtualenv
230 */
231 def getStacksWithStatus(client, status, path = null) {
232 cmd = 'heat stack-list -f stack_status='+status+' | awk \'NR>3 {print $4}\' | sed \'$ d\''
233 return runOpenstackCommand(cmd, client, path).trim().tokenize("\n")
234 }
235
236/**
Sergey Kolekonovba203982016-12-21 18:32:17 +0400237 * Get life cycle status for existing OpenStack Heat stack
238 *
239 * @param env Connection parameters for OpenStack API endpoint
240 * @param name Name of the managed Heat stack instance
241 * @param path Optional path to the custom virtualenv
242 */
243def getHeatStackStatus(client, name, path = null) {
244 cmd = 'heat stack-list | awk -v stack='+name+' \'{if ($4==stack) print $6}\''
245 return runOpenstackCommand(cmd, client, path)
246}
247
248/**
249 * Get info about existing OpenStack Heat stack
250 *
251 * @param env Connection parameters for OpenStack API endpoint
252 * @param name Name of the managed Heat stack instance
253 * @param path Optional path to the custom virtualenv
254 */
255def getHeatStackInfo(env, name, path = null) {
iberezovskiyd4240b52017-02-20 17:18:28 +0400256 def python = new com.mirantis.mk.Python()
Sergey Kolekonovba203982016-12-21 18:32:17 +0400257 cmd = "heat stack-show ${name}"
258 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100259 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400260 return output
261}
262
263/**
264 * Get existing OpenStack Heat stack output parameter
265 *
266 * @param env Connection parameters for OpenStack API endpoint
267 * @param name Name of the managed Heat stack
268 * @param parameter Name of the output parameter
269 * @param path Optional path to the custom virtualenv
270 */
271def getHeatStackOutputParam(env, name, outputParam, path = null) {
Vasyl Saienkoea4b2812017-07-10 10:36:03 +0000272 cmd = "heat output-show ${name} ${outputParam}"
Sergey Kolekonovba203982016-12-21 18:32:17 +0400273 output = runOpenstackCommand(cmd, env, path)
Ales Komarekeedc2222017-01-03 10:10:03 +0100274 echo("${cmd}: ${output}")
Vasyl Saienko2a1c2de2017-07-11 11:41:53 +0300275 // NOTE(vsaienko) heatclient 1.5.1 returns output in "", while later
276 // versions returns string without "".
277 // TODO Use openstack 'stack output show' when all jobs using at least Mitaka heatclient
278 return "${output}".replaceAll('"', '')
Sergey Kolekonovba203982016-12-21 18:32:17 +0400279}
280
281/**
282 * List all resources from existing OpenStack Heat stack
283 *
284 * @param env Connection parameters for OpenStack API endpoint
285 * @param name Name of the managed Heat stack instance
286 * @param path Optional path to the custom virtualenv
Mykyta Karpin72306362018-02-08 16:40:43 +0200287 * @param depth Optional depth of stack for listing resources,
288 * 0 - do not list nested resources
Sergey Kolekonovba203982016-12-21 18:32:17 +0400289 */
Mykyta Karpin72306362018-02-08 16:40:43 +0200290def getHeatStackResources(env, name, path = null, depth = 0) {
iberezovskiyd4240b52017-02-20 17:18:28 +0400291 def python = new com.mirantis.mk.Python()
Mykyta Karpin72306362018-02-08 16:40:43 +0200292 cmd = "heat resource-list --nested-depth ${depth} ${name}"
Sergey Kolekonovba203982016-12-21 18:32:17 +0400293 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100294 output = python.parseTextTable(outputTable, 'list', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400295 return output
296}
297
298/**
299 * Get info about resource from existing OpenStack Heat stack
300 *
301 * @param env Connection parameters for OpenStack API endpoint
302 * @param name Name of the managed Heat stack instance
303 * @param path Optional path to the custom virtualenv
304 */
305def getHeatStackResourceInfo(env, name, resource, path = null) {
iberezovskiyd4240b52017-02-20 17:18:28 +0400306 def python = new com.mirantis.mk.Python()
Sergey Kolekonovba203982016-12-21 18:32:17 +0400307 cmd = "heat resource-show ${name} ${resource}"
308 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100309 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400310 return output
311}
312
313/**
314 * Update existing OpenStack Heat stack
315 *
316 * @param env Connection parameters for OpenStack API endpoint
317 * @param name Name of the managed Heat stack instance
318 * @param path Optional path to the custom virtualenv
319 */
320def updateHeatStack(env, name, path = null) {
iberezovskiyd4240b52017-02-20 17:18:28 +0400321 def python = new com.mirantis.mk.Python()
Sergey Kolekonovba203982016-12-21 18:32:17 +0400322 cmd = "heat stack-update ${name}"
323 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100324 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400325 return output
326}
327
328/**
329 * Delete existing OpenStack Heat stack
330 *
331 * @param env Connection parameters for OpenStack API endpoint
332 * @param name Name of the managed Heat stack instance
333 * @param path Optional path to the custom virtualenv
334 */
335def deleteHeatStack(env, name, path = null) {
336 cmd = "heat stack-delete ${name}"
337 outputTable = runOpenstackCommand(cmd, env, path)
338}
339
340/**
Mykyta Karpin72306362018-02-08 16:40:43 +0200341 * Return hashmap of hashes server_id:server_name of servers from OpenStack Heat stack
Sergey Kolekonovba203982016-12-21 18:32:17 +0400342 *
343 * @param env Connection parameters for OpenStack API endpoint
344 * @param name Name of the managed Heat stack instance
345 * @param path Optional path to the custom virtualenv
346 */
347def getHeatStackServers(env, name, path = null) {
Mykyta Karpin72306362018-02-08 16:40:43 +0200348 // set depth to 1000 to ensure all nested resources are shown
349 resources = getHeatStackResources(env, name, path, 1000)
350 servers = [:]
Sergey Kolekonovba203982016-12-21 18:32:17 +0400351 for (resource in resources) {
352 if (resource.resource_type == 'OS::Nova::Server') {
Mykyta Karpin67978112018-02-22 11:16:45 +0200353 server = getHeatStackResourceInfo(env, resource.stack_name, resource.resource_name, path)
Mykyta Karpin72306362018-02-08 16:40:43 +0200354 servers[server.attributes.id] = server.attributes.name
Sergey Kolekonovba203982016-12-21 18:32:17 +0400355 }
356 }
357 echo("[Stack ${name}] Servers: ${servers}")
358 return servers
359}
Jiri Broulikf8f96942018-02-15 10:03:42 +0100360
361/**
Mykyta Karpin8306a9d2018-07-27 11:34:10 +0300362 * Delete nova key pair
363 *
364 * @param env Connection parameters for OpenStack API endpoint
365 * @param name Name of the key pair to delete
366 * @param path Optional path to the custom virtualenv
367 */
368def deleteKeyPair(env, name, path = null) {
369 def common = new com.mirantis.mk.Common()
370 common.infoMsg("Removing key pair ${name}")
371 def cmd = "openstack keypair delete ${name}"
372 runOpenstackCommand(cmd, env, path)
373}
374
375/**
376 * Get nova key pair
377 *
378 * @param env Connection parameters for OpenStack API endpoint
379 * @param name Name of the key pair to show
380 * @param path Optional path to the custom virtualenv
381 */
382
383def getKeyPair(env, name, path = null) {
384 def common = new com.mirantis.mk.Common()
385 def cmd = "openstack keypair show ${name}"
386 def outputTable
387 try {
388 outputTable = runOpenstackCommand(cmd, env, path)
389 } catch (Exception e) {
390 common.infoMsg("Key pair ${name} not found")
391 }
392 return outputTable
393}
394
395/**
Jiri Broulikf8f96942018-02-15 10:03:42 +0100396 * Stops all services that contain specific string (for example nova,heat, etc.)
397 * @param env Salt Connection object or pepperEnv
398 * @param probe single node on which to list service names
399 * @param target all targeted nodes
400 * @param services lists of type of services to be stopped
Jiri Broulikf6daac62018-03-08 13:17:53 +0100401 * @param confirm enable/disable manual service stop confirmation
Jiri Broulikf8f96942018-02-15 10:03:42 +0100402 * @return output of salt commands
403 */
Jiri Broulik27e83052018-03-06 11:37:29 +0100404def stopServices(env, probe, target, services=[], confirm=false) {
Jiri Broulikf8f96942018-02-15 10:03:42 +0100405 def salt = new com.mirantis.mk.Salt()
Jiri Broulikf6daac62018-03-08 13:17:53 +0100406 def common = new com.mirantis.mk.Common()
Jiri Broulikf8f96942018-02-15 10:03:42 +0100407 for (s in services) {
Dmitry Ukovd72cd2a2018-09-04 17:31:46 +0400408 def outputServicesStr = salt.getReturnValues(salt.cmdRun(env, probe, "service --status-all | grep ${s} | awk \'{print \$4}\'"))
Jiri Broulikf6daac62018-03-08 13:17:53 +0100409 def servicesList = outputServicesStr.tokenize("\n").init()
Jiri Broulik27e83052018-03-06 11:37:29 +0100410 if (confirm) {
Jiri Broulikf6daac62018-03-08 13:17:53 +0100411 if (servicesList) {
412 try {
413 input message: "Click PROCEED to stop ${servicesList}. Otherwise click ABORT to skip stopping them."
414 for (name in servicesList) {
415 if (!name.contains('Salt command')) {
Dmitry Ukovd72cd2a2018-09-04 17:31:46 +0400416 salt.runSaltProcessStep(env, target, 'service.stop', ["${name}"])
Jiri Broulikf6daac62018-03-08 13:17:53 +0100417 }
418 }
419 } catch (Exception er) {
420 common.infoMsg("skipping stopping ${servicesList} services")
421 }
422 }
423 } else {
424 if (servicesList) {
Jiri Broulik27e83052018-03-06 11:37:29 +0100425 for (name in servicesList) {
426 if (!name.contains('Salt command')) {
Dmitry Ukovd72cd2a2018-09-04 17:31:46 +0400427 salt.runSaltProcessStep(env, target, 'service.stop', ["${name}"])
Jiri Broulik27e83052018-03-06 11:37:29 +0100428 }
429 }
Jiri Broulikf8f96942018-02-15 10:03:42 +0100430 }
431 }
432 }
433}
434
435/**
Vasyl Saienko4129e102018-09-03 10:15:52 +0300436 * Return intersection of globally installed services and those are
437 * defined on specific target according to theirs priorities.
Oleksii Grudev3aaadc22019-03-14 10:54:58 +0200438 * By default services are added to the result list only if
439 * <service>.upgrade.enabled pillar is set to "True". However if it
440 * is needed to obtain list of upgrade services regardless of
441 * <service>.upgrade.enabled pillar value it is needed to set
442 * "upgrade_condition" param to "False".
Vasyl Saienko4129e102018-09-03 10:15:52 +0300443 *
444 * @param env Salt Connection object or env
Oleksii Grudev3aaadc22019-03-14 10:54:58 +0200445 * @param target The target node to get list of apps for
446 * @param upgrade_condition Whether to take "upgrade:enabled"
447 * service pillar into consideration
448 * when obtaining list of upgrade services
Vasyl Saienko4129e102018-09-03 10:15:52 +0300449**/
Oleksii Grudev3aaadc22019-03-14 10:54:58 +0200450def getOpenStackUpgradeServices(env, target, upgrade_condition=true){
Vasyl Saienko4129e102018-09-03 10:15:52 +0300451 def salt = new com.mirantis.mk.Salt()
452 def common = new com.mirantis.mk.Common()
453
454 def global_apps = salt.getConfig(env, 'I@salt:master:enabled:true', 'orchestration.upgrade.applications')
455 def node_apps = salt.getPillar(env, target, '__reclass__:applications')['return'][0].values()[0]
Oleksii Grudev3aaadc22019-03-14 10:54:58 +0200456 if (upgrade_condition) {
457 node_pillar = salt.getPillar(env, target)
458 }
Vasyl Saienko4129e102018-09-03 10:15:52 +0300459 def node_sorted_apps = []
460 if ( !global_apps['return'][0].values()[0].isEmpty() ) {
461 Map<String,Integer> _sorted_apps = [:]
462 for (k in global_apps['return'][0].values()[0].keySet()) {
463 if (k in node_apps) {
Oleksii Grudev3aaadc22019-03-14 10:54:58 +0200464 if (upgrade_condition) {
465 if (node_pillar['return'][0].values()[k]['upgrade']['enabled'][0] != null) {
466 if (node_pillar['return'][0].values()[k]['upgrade']['enabled'][0].toBoolean()) {
467 _sorted_apps[k] = global_apps['return'][0].values()[0][k].values()[0].toInteger()
468 }
Oleksii Grudev3116a732019-02-14 18:16:05 +0200469 }
Oleksii Grudev3aaadc22019-03-14 10:54:58 +0200470 } else {
471 _sorted_apps[k] = global_apps['return'][0].values()[0][k].values()[0].toInteger()
Oleksii Grudev3116a732019-02-14 18:16:05 +0200472 }
Vasyl Saienko4129e102018-09-03 10:15:52 +0300473 }
474 }
475 node_sorted_apps = common.SortMapByValueAsc(_sorted_apps).keySet()
476 common.infoMsg("Applications are placed in following order:"+node_sorted_apps)
477 } else {
478 common.errorMsg("No applications found.")
479 }
480
481 return node_sorted_apps
482}
483
Vasyl Saienko4129e102018-09-03 10:15:52 +0300484/**
485 * Run specified upgrade phase for all services on given node.
486 *
487 * @param env Salt Connection object or env
488 * @param target The target node to run states on.
489 * @param phase The phase name to run.
490**/
491def runOpenStackUpgradePhase(env, target, phase){
492 def salt = new com.mirantis.mk.Salt()
493 def common = new com.mirantis.mk.Common()
494
495 services = getOpenStackUpgradeServices(env, target)
496 def st
497
498 for (service in services){
499 st = "${service}.upgrade.${phase}".trim()
500 common.infoMsg("Running ${phase} for service ${st} on ${target}")
501 salt.enforceState(env, target, st)
502 }
503}
504
505
506/**
507 * Run OpenStack states on specified node.
508 *
509 * @param env Salt Connection object or env
510 * @param target The target node to run states on.
511**/
512def applyOpenstackAppsStates(env, target){
513 def salt = new com.mirantis.mk.Salt()
514 def common = new com.mirantis.mk.Common()
515
516 services = getOpenStackUpgradeServices(env, target)
517 def st
518
519 for (service in services){
520 st = "${service}".trim()
521 common.infoMsg("Running ${st} on ${target}")
522 salt.enforceState(env, target, st)
523 }
524}
525
Martin Polreich232ad902019-01-21 14:31:00 +0100526def verifyGaleraStatus(env, slave=false, checkTimeSync=false) {
Martin Polreich65864b02018-12-05 10:42:50 +0100527 def common = new com.mirantis.mk.Common()
Martin Polreich8f0f3ac2019-02-15 10:03:33 +0100528 def galera = new com.mirantis.mk.Galera()
529 common.warningMsg("verifyGaleraStatus method was moved to Galera class. Please change your calls accordingly.")
530 return galera.verifyGaleraStatus(env, slave, checkTimeSync)
Martin Polreich65864b02018-12-05 10:42:50 +0100531}
532
Martin Polreich9a5d6682018-12-21 16:42:06 +0100533def validateAndPrintGaleraStatusReport(env, out, minion) {
Martin Polreich65864b02018-12-05 10:42:50 +0100534 def common = new com.mirantis.mk.Common()
Martin Polreich8f0f3ac2019-02-15 10:03:33 +0100535 def galera = new com.mirantis.mk.Galera()
536 common.warningMsg("validateAndPrintGaleraStatusReport method was moved to Galera class. Please change your calls accordingly.")
537 return galera.validateAndPrintGaleraStatusReport(env, out, minion)
Martin Polreich65864b02018-12-05 10:42:50 +0100538}
539
Martin Polreich9a5d6682018-12-21 16:42:06 +0100540def getGaleraLastShutdownNode(env) {
Martin Polreich9a5d6682018-12-21 16:42:06 +0100541 def common = new com.mirantis.mk.Common()
Martin Polreich8f0f3ac2019-02-15 10:03:33 +0100542 def galera = new com.mirantis.mk.Galera()
543 common.warningMsg("getGaleraLastShutdownNode method was moved to Galera class. Please change your calls accordingly.")
544 return galera.getGaleraLastShutdownNode(env)
Martin Polreich9a5d6682018-12-21 16:42:06 +0100545}
546
Ivan Berezovskiy004cac22019-02-01 17:03:28 +0400547def restoreGaleraDb(env) {
Jiri Broulikf8f96942018-02-15 10:03:42 +0100548 def common = new com.mirantis.mk.Common()
Martin Polreich8f0f3ac2019-02-15 10:03:33 +0100549 def galera = new com.mirantis.mk.Galera()
550 common.warningMsg("restoreGaleraDb method was moved to Galera class. Please change your calls accordingly.")
551 return galera.restoreGaleraDb(env)
Oleksii Grudev3aaadc22019-03-14 10:54:58 +0200552}