blob: ec840d8fea240c52f7b0cf0aaba2ca181b86270b [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)
Ales Komarek0e558ee2016-12-23 13:02:55 +010062 rc = """export OS_USERNAME=${creds.username}
63export OS_PASSWORD=${creds.password.toString()}
64export OS_TENANT_NAME=${project}
65export OS_AUTH_URL=${url}
66export OS_AUTH_STRATEGY=keystone
67"""
68 writeFile file: rcFile, text: rc
69 return rcFile
Sergey Kolekonovba203982016-12-21 18:32:17 +040070}
71
72/**
73 * Run command with OpenStack env params and optional python env
74 *
75 * @param cmd Command to be executed
76 * @param env Environmental parameters with endpoint credentials
77 * @param path Optional path to virtualenv with specific clients
78 */
79def runOpenstackCommand(cmd, venv, path = null) {
80 def python = new com.mirantis.mk.python()
81 openstackCmd = ". ${venv}; ${cmd}"
82 if (path) {
83 output = python.runVirtualenvCommand(path, openstackCmd)
84 }
85 else {
86 echo("[Command]: ${openstackCmd}")
87 output = sh (
88 script: openstackCmd,
89 returnStdout: true
90 ).trim()
91 }
92 return output
93}
94
95/**
96 * Get OpenStack Keystone token for current credentials
97 *
98 * @param env Connection parameters for OpenStack API endpoint
99 * @param path Optional path to the custom virtualenv
100 */
101def getKeystoneToken(client, path = null) {
102 def python = new com.mirantis.mk.python()
103 cmd = "keystone token-get"
104 outputTable = runOpenstackCommand(cmd, client, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100105 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400106 return output
107}
108
109/**
110 * Get OpenStack Keystone token for current credentials
111 *
112 * @param env Connection parameters for OpenStack API endpoint
113 * @param path Optional path to the custom virtualenv
114 */
115def createHeatEnv(file, environment = [], original_file = null) {
116 if (original_file) {
117 envString = readFile file: original_file
118 }
119 else {
120 envString = "parameters:\n"
121 }
122 for ( int i = 0; i < environment.size; i++ ) {
123 envString = "${envString} ${environment.get(i).get(0)}: ${environment.get(i).get(1)}\n"
124 }
125 writeFile file: file, text: envString
126}
127
128/**
129 * Create new OpenStack Heat stack
130 *
131 * @param env Connection parameters for OpenStack API endpoint
132 * @param template HOT template for the new Heat stack
133 * @param environment Environmentale parameters of the new Heat stack
134 * @param name Name of the new Heat stack
135 * @param path Optional path to the custom virtualenv
136 */
137def createHeatStack(client, name, template, params = [], environment = null, path = null) {
138 def python = new com.mirantis.mk.python()
139 templateFile = "${env.WORKSPACE}/template/template/${template}.hot"
140 if (environment) {
141 envFile = "${env.WORKSPACE}/template/env/${template}/${name}.env"
142 envSource = "${env.WORKSPACE}/template/env/${template}/${environment}.env"
143 createHeatEnv(envFile, params, envSource)
144 }
145 else {
146 envFile = "${env.WORKSPACE}/template/${name}.env"
147 createHeatEnv(envFile, params)
148 }
149 cmd = "heat stack-create -f ${templateFile} -e ${envFile} ${name}"
150 dir("${env.WORKSPACE}/template/template") {
151 outputTable = runOpenstackCommand(cmd, client, path)
152 }
Ales Komareke11e8792016-12-28 09:42:25 +0100153 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400154
155 i = 1
Ales Komarekdce8b472016-12-30 16:56:07 +0100156
Sergey Kolekonovba203982016-12-21 18:32:17 +0400157 while (true) {
158 status = getHeatStackStatus(client, name, path)
159 echo("[Heat Stack] Status: ${status}, Check: ${i}")
Ales Komarekdce8b472016-12-30 16:56:07 +0100160
161 if (status.indexOf('CREATE_FAILED') != -1) {
Sergey Kolekonovba203982016-12-21 18:32:17 +0400162 info = getHeatStackInfo(client, name, path)
163 throw new Exception(info.stack_status_reason)
164 }
Ales Komarekdce8b472016-12-30 16:56:07 +0100165 else if (status.indexOf('CREATE_COMPLETE') != -1) {
Sergey Kolekonovba203982016-12-21 18:32:17 +0400166 info = getHeatStackInfo(client, name, path)
167 echo(info.stack_status_reason)
168 break
169 }
170 sh('sleep 5s')
171 i++
172 }
173 echo("[Heat Stack] Status: ${status}")
174}
175
176/**
177 * Get life cycle status for existing OpenStack Heat stack
178 *
179 * @param env Connection parameters for OpenStack API endpoint
180 * @param name Name of the managed Heat stack instance
181 * @param path Optional path to the custom virtualenv
182 */
183def getHeatStackStatus(client, name, path = null) {
184 cmd = 'heat stack-list | awk -v stack='+name+' \'{if ($4==stack) print $6}\''
185 return runOpenstackCommand(cmd, client, path)
186}
187
188/**
189 * Get info about existing OpenStack Heat stack
190 *
191 * @param env Connection parameters for OpenStack API endpoint
192 * @param name Name of the managed Heat stack instance
193 * @param path Optional path to the custom virtualenv
194 */
195def getHeatStackInfo(env, name, path = null) {
196 def python = new com.mirantis.mk.python()
197 cmd = "heat stack-show ${name}"
198 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100199 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400200 return output
201}
202
203/**
204 * Get existing OpenStack Heat stack output parameter
205 *
206 * @param env Connection parameters for OpenStack API endpoint
207 * @param name Name of the managed Heat stack
208 * @param parameter Name of the output parameter
209 * @param path Optional path to the custom virtualenv
210 */
211def getHeatStackOutputParam(env, name, outputParam, path = null) {
212 cmd = "heat output-show ${name} ${outputParam}"
213 output = runOpenstackCommand(cmd, env, path)
Ales Komarekeedc2222017-01-03 10:10:03 +0100214 echo("${cmd}: ${output}")
Ales Komarek7ebd0062017-01-03 10:59:29 +0100215 return "${output}".substring(1, output.length()-1)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400216}
217
218/**
219 * List all resources from existing OpenStack Heat stack
220 *
221 * @param env Connection parameters for OpenStack API endpoint
222 * @param name Name of the managed Heat stack instance
223 * @param path Optional path to the custom virtualenv
224 */
225def getHeatStackResources(env, name, path = null) {
226 def python = new com.mirantis.mk.python()
227 cmd = "heat resource-list ${name}"
228 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100229 output = python.parseTextTable(outputTable, 'list', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400230 return output
231}
232
233/**
234 * Get info about resource from existing OpenStack Heat stack
235 *
236 * @param env Connection parameters for OpenStack API endpoint
237 * @param name Name of the managed Heat stack instance
238 * @param path Optional path to the custom virtualenv
239 */
240def getHeatStackResourceInfo(env, name, resource, path = null) {
241 def python = new com.mirantis.mk.python()
242 cmd = "heat resource-show ${name} ${resource}"
243 outputTable = runOpenstackCommand(cmd, env, path)
Ales Komareke11e8792016-12-28 09:42:25 +0100244 output = python.parseTextTable(outputTable, 'item', 'prettytable', path)
Sergey Kolekonovba203982016-12-21 18:32:17 +0400245 return output
246}
247
248/**
249 * Update 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 updateHeatStack(env, name, path = null) {
256 def python = new com.mirantis.mk.python()
257 cmd = "heat stack-update ${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 * Delete existing OpenStack Heat stack
265 *
266 * @param env Connection parameters for OpenStack API endpoint
267 * @param name Name of the managed Heat stack instance
268 * @param path Optional path to the custom virtualenv
269 */
270def deleteHeatStack(env, name, path = null) {
271 cmd = "heat stack-delete ${name}"
272 outputTable = runOpenstackCommand(cmd, env, path)
273}
274
275/**
276 * Return list of servers from OpenStack Heat stack
277 *
278 * @param env Connection parameters for OpenStack API endpoint
279 * @param name Name of the managed Heat stack instance
280 * @param path Optional path to the custom virtualenv
281 */
282def getHeatStackServers(env, name, path = null) {
283 resources = heatGetStackResources(env, name, path)
284 servers = []
285 for (resource in resources) {
286 if (resource.resource_type == 'OS::Nova::Server') {
287 resourceName = resource.resource_name
288 server = heatGetStackResourceInfo(env, name, resourceName, path)
289 servers.add(server.attributes.name)
290 }
291 }
292 echo("[Stack ${name}] Servers: ${servers}")
293 return servers
294}