blob: d12c00477f9582761de77050c154bce09ce412f0 [file] [log] [blame]
Sergey Kolekonovba203982016-12-21 18:32:17 +04001package com.mirantis.mk
2
3/**
4 *
5 * Openstack functions
6 *
7 */
8
9/**
10 * Install OpenStack service clients in isolated environment
11 *
12 * @param path Path where virtualenv is created
13 * @param version Version of the OpenStack clients
14 */
15
16def setupOpenstackVirtualenv(path, version = 'kilo'){
17 def python = new com.mirantis.mk.python()
18
19 def openstack_kilo_packages = [
20 'python-cinderclient>=1.3.1,<1.4.0',
21 'python-glanceclient>=0.19.0,<0.20.0',
22 'python-heatclient>=0.6.0,<0.7.0',
23 'python-keystoneclient>=1.6.0,<1.7.0',
24 'python-neutronclient>=2.2.6,<2.3.0',
25 'python-novaclient>=2.19.0,<2.20.0',
26 'python-swiftclient>=2.5.0,<2.6.0',
27 'oslo.config>=2.2.0,<2.3.0',
28 'oslo.i18n>=2.3.0,<2.4.0',
29 'oslo.serialization>=1.8.0,<1.9.0',
30 'oslo.utils>=1.4.0,<1.5.0',
Ales Komarekd874d482016-12-26 10:33:29 +010031 'docutils>=0.12'
Sergey Kolekonovba203982016-12-21 18:32:17 +040032 ]
33
34 def openstack_latest_packages = openstack_kilo_packages
35
36 if(version == 'kilo') {
37 requirements = openstack_kilo_packages
38 }
39 else if(version == 'liberty') {
40 requirements = openstack_kilo_packages
41 }
42 else if(version == 'mitaka') {
43 requirements = openstack_kilo_packages
44 }
45 else {
46 requirements = openstack_latest_packages
47 }
48 python.setupVirtualenv(path, 'python2', requirements)
49}
50
51/**
52 * create connection to OpenStack API endpoint
53 *
54 * @param url OpenStack API endpoint address
55 * @param credentialsId Credentials to the OpenStack API
56 * @param project OpenStack project to connect to
57 */
Sergey Kolekonovba203982016-12-21 18:32:17 +040058def createOpenstackEnv(url, credentialsId, project) {
59 def common = new com.mirantis.mk.common()
Ales Komarek0e558ee2016-12-23 13:02:55 +010060 rcFile = "${env.WORKSPACE}/keystonerc"
Sergey Kolekonovba203982016-12-21 18:32:17 +040061 creds = common.getPasswordCredentials(credentialsId)
Alexander Tivelkovf89a1882017-01-11 13:29:35 +030062 rc = """set +x
63export OS_USERNAME=${creds.username}
Ales Komarek0e558ee2016-12-23 13:02:55 +010064export OS_PASSWORD=${creds.password.toString()}
65export OS_TENANT_NAME=${project}
66export OS_AUTH_URL=${url}
67export OS_AUTH_STRATEGY=keystone
Alexander Tivelkovf89a1882017-01-11 13:29:35 +030068set -x
Ales Komarek0e558ee2016-12-23 13:02:55 +010069"""
70 writeFile file: rcFile, text: rc
71 return rcFile
Sergey Kolekonovba203982016-12-21 18:32:17 +040072}
73
74/**
75 * Run command with OpenStack env params and optional python env
76 *
77 * @param cmd Command to be executed
78 * @param env Environmental parameters with endpoint credentials
79 * @param path Optional path to virtualenv with specific clients
80 */
81def runOpenstackCommand(cmd, venv, path = null) {
82 def python = new com.mirantis.mk.python()
83 openstackCmd = ". ${venv}; ${cmd}"
84 if (path) {
85 output = python.runVirtualenvCommand(path, openstackCmd)
86 }
87 else {
88 echo("[Command]: ${openstackCmd}")
89 output = sh (
90 script: openstackCmd,
91 returnStdout: true
92 ).trim()
93 }
94 return output
95}
96
97/**
98 * Get OpenStack Keystone token for current credentials
99 *
100 * @param env Connection parameters for OpenStack API endpoint
101 * @param path Optional path to the custom virtualenv
102 */
103def getKeystoneToken(client, path = null) {
104 def python = new com.mirantis.mk.python()
105 cmd = "keystone token-get"
106 outputTable = runOpenstackCommand(cmd, client, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100107 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400108 return output
109}
110
111/**
112 * Get OpenStack Keystone token for current credentials
113 *
114 * @param env Connection parameters for OpenStack API endpoint
115 * @param path Optional path to the custom virtualenv
116 */
117def createHeatEnv(file, environment = [], original_file = null) {
118 if (original_file) {
119 envString = readFile file: original_file
120 }
121 else {
122 envString = "parameters:\n"
123 }
124 for ( int i = 0; i < environment.size; i++ ) {
125 envString = "${envString} ${environment.get(i).get(0)}: ${environment.get(i).get(1)}\n"
126 }
127 writeFile file: file, text: envString
128}
129
130/**
131 * Create new OpenStack Heat stack
132 *
133 * @param env Connection parameters for OpenStack API endpoint
134 * @param template HOT template for the new Heat stack
135 * @param environment Environmentale parameters of the new Heat stack
136 * @param name Name of the new Heat stack
137 * @param path Optional path to the custom virtualenv
138 */
139def createHeatStack(client, name, template, params = [], environment = null, path = null) {
140 def python = new com.mirantis.mk.python()
141 templateFile = "${env.WORKSPACE}/template/template/${template}.hot"
142 if (environment) {
143 envFile = "${env.WORKSPACE}/template/env/${template}/${name}.env"
144 envSource = "${env.WORKSPACE}/template/env/${template}/${environment}.env"
145 createHeatEnv(envFile, params, envSource)
146 }
147 else {
148 envFile = "${env.WORKSPACE}/template/${name}.env"
149 createHeatEnv(envFile, params)
150 }
151 cmd = "heat stack-create -f ${templateFile} -e ${envFile} ${name}"
152 dir("${env.WORKSPACE}/template/template") {
153 outputTable = runOpenstackCommand(cmd, client, path)
154 }
Ales Komareke11e8792016-12-28 09:42:25 +0100155 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400156
157 i = 1
Ales Komarekdce8b472016-12-30 16:56:07 +0100158
Sergey Kolekonovba203982016-12-21 18:32:17 +0400159 while (true) {
160 status = getHeatStackStatus(client, name, path)
161 echo("[Heat Stack] Status: ${status}, Check: ${i}")
Ales Komarekdce8b472016-12-30 16:56:07 +0100162
163 if (status.indexOf('CREATE_FAILED') != -1) {
Sergey Kolekonovba203982016-12-21 18:32:17 +0400164 info = getHeatStackInfo(client, name, path)
165 throw new Exception(info.stack_status_reason)
166 }
Ales Komarekdce8b472016-12-30 16:56:07 +0100167 else if (status.indexOf('CREATE_COMPLETE') != -1) {
Sergey Kolekonovba203982016-12-21 18:32:17 +0400168 info = getHeatStackInfo(client, name, path)
169 echo(info.stack_status_reason)
170 break
171 }
172 sh('sleep 5s')
173 i++
174 }
175 echo("[Heat Stack] Status: ${status}")
176}
177
178/**
179 * Get life cycle status for existing OpenStack Heat stack
180 *
181 * @param env Connection parameters for OpenStack API endpoint
182 * @param name Name of the managed Heat stack instance
183 * @param path Optional path to the custom virtualenv
184 */
185def getHeatStackStatus(client, name, path = null) {
186 cmd = 'heat stack-list | awk -v stack='+name+' \'{if ($4==stack) print $6}\''
187 return runOpenstackCommand(cmd, client, path)
188}
189
190/**
191 * Get info about existing OpenStack Heat stack
192 *
193 * @param env Connection parameters for OpenStack API endpoint
194 * @param name Name of the managed Heat stack instance
195 * @param path Optional path to the custom virtualenv
196 */
197def getHeatStackInfo(env, name, path = null) {
198 def python = new com.mirantis.mk.python()
199 cmd = "heat stack-show ${name}"
200 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100201 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400202 return output
203}
204
205/**
206 * Get existing OpenStack Heat stack output parameter
207 *
208 * @param env Connection parameters for OpenStack API endpoint
209 * @param name Name of the managed Heat stack
210 * @param parameter Name of the output parameter
211 * @param path Optional path to the custom virtualenv
212 */
213def getHeatStackOutputParam(env, name, outputParam, path = null) {
214 cmd = "heat output-show ${name} ${outputParam}"
215 output = runOpenstackCommand(cmd, env, path)
Ales Komarekeedc2222017-01-03 10:10:03 +0100216 echo("${cmd}: ${output}")
Ales Komarek7ebd0062017-01-03 10:59:29 +0100217 return "${output}".substring(1, output.length()-1)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400218}
219
220/**
221 * List all resources from existing OpenStack Heat stack
222 *
223 * @param env Connection parameters for OpenStack API endpoint
224 * @param name Name of the managed Heat stack instance
225 * @param path Optional path to the custom virtualenv
226 */
227def getHeatStackResources(env, name, path = null) {
228 def python = new com.mirantis.mk.python()
229 cmd = "heat resource-list ${name}"
230 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100231 output = python.parseTextTable(outputTable, 'list', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400232 return output
233}
234
235/**
236 * Get info about resource from existing OpenStack Heat stack
237 *
238 * @param env Connection parameters for OpenStack API endpoint
239 * @param name Name of the managed Heat stack instance
240 * @param path Optional path to the custom virtualenv
241 */
242def getHeatStackResourceInfo(env, name, resource, path = null) {
243 def python = new com.mirantis.mk.python()
244 cmd = "heat resource-show ${name} ${resource}"
245 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100246 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400247 return output
248}
249
250/**
251 * Update existing OpenStack Heat stack
252 *
253 * @param env Connection parameters for OpenStack API endpoint
254 * @param name Name of the managed Heat stack instance
255 * @param path Optional path to the custom virtualenv
256 */
257def updateHeatStack(env, name, path = null) {
258 def python = new com.mirantis.mk.python()
259 cmd = "heat stack-update ${name}"
260 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100261 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400262 return output
263}
264
265/**
266 * Delete existing OpenStack Heat stack
267 *
268 * @param env Connection parameters for OpenStack API endpoint
269 * @param name Name of the managed Heat stack instance
270 * @param path Optional path to the custom virtualenv
271 */
272def deleteHeatStack(env, name, path = null) {
273 cmd = "heat stack-delete ${name}"
274 outputTable = runOpenstackCommand(cmd, env, path)
275}
276
277/**
278 * Return list of servers from OpenStack Heat stack
279 *
280 * @param env Connection parameters for OpenStack API endpoint
281 * @param name Name of the managed Heat stack instance
282 * @param path Optional path to the custom virtualenv
283 */
284def getHeatStackServers(env, name, path = null) {
285 resources = heatGetStackResources(env, name, path)
286 servers = []
287 for (resource in resources) {
288 if (resource.resource_type == 'OS::Nova::Server') {
289 resourceName = resource.resource_name
290 server = heatGetStackResourceInfo(env, name, resourceName, path)
291 servers.add(server.attributes.name)
292 }
293 }
294 echo("[Stack ${name}] Servers: ${servers}")
295 return servers
296}