blob: 1d6bccaa5941ba9f53c7b7228497bb26128d0c6b [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',
31 ]
32
33 def openstack_latest_packages = openstack_kilo_packages
34
35 if(version == 'kilo') {
36 requirements = openstack_kilo_packages
37 }
38 else if(version == 'liberty') {
39 requirements = openstack_kilo_packages
40 }
41 else if(version == 'mitaka') {
42 requirements = openstack_kilo_packages
43 }
44 else {
45 requirements = openstack_latest_packages
46 }
47 python.setupVirtualenv(path, 'python2', requirements)
48}
49
50/**
51 * create connection to OpenStack API endpoint
52 *
53 * @param url OpenStack API endpoint address
54 * @param credentialsId Credentials to the OpenStack API
55 * @param project OpenStack project to connect to
56 */
57@NonCPS
58def createOpenstackEnv(url, credentialsId, project) {
59 def common = new com.mirantis.mk.common()
60 creds = common.getPasswordCredentials(credentialsId)
61 params = [
62 "OS_USERNAME": creds.username,
63 "OS_PASSWORD": creds.password.toString(),
64 "OS_TENANT_NAME": project,
65 "OS_AUTH_URL": url,
66 "OS_AUTH_STRATEGY": "keystone"
67 ]
68 res = ""
69 for ( e in params ) {
70 res = "${res}export ${e.key}=${e.value}\n"
71 }
72 writeFile file: "${env.WORKSPACE}/keystonerc", text: res
73 return "${env.WORKSPACE}/keystonerc"
74 //return res.substring(1)
75}
76
77/**
78 * Run command with OpenStack env params and optional python env
79 *
80 * @param cmd Command to be executed
81 * @param env Environmental parameters with endpoint credentials
82 * @param path Optional path to virtualenv with specific clients
83 */
84def runOpenstackCommand(cmd, venv, path = null) {
85 def python = new com.mirantis.mk.python()
86 openstackCmd = ". ${venv}; ${cmd}"
87 if (path) {
88 output = python.runVirtualenvCommand(path, openstackCmd)
89 }
90 else {
91 echo("[Command]: ${openstackCmd}")
92 output = sh (
93 script: openstackCmd,
94 returnStdout: true
95 ).trim()
96 }
97 return output
98}
99
100/**
101 * Get OpenStack Keystone token for current credentials
102 *
103 * @param env Connection parameters for OpenStack API endpoint
104 * @param path Optional path to the custom virtualenv
105 */
106def getKeystoneToken(client, path = null) {
107 def python = new com.mirantis.mk.python()
108 cmd = "keystone token-get"
109 outputTable = runOpenstackCommand(cmd, client, path)
110 output = python.parseTextTable(outputTable, 'item', 'prettytable')
111 return output
112}
113
114/**
115 * Get OpenStack Keystone token for current credentials
116 *
117 * @param env Connection parameters for OpenStack API endpoint
118 * @param path Optional path to the custom virtualenv
119 */
120def createHeatEnv(file, environment = [], original_file = null) {
121 if (original_file) {
122 envString = readFile file: original_file
123 }
124 else {
125 envString = "parameters:\n"
126 }
127 for ( int i = 0; i < environment.size; i++ ) {
128 envString = "${envString} ${environment.get(i).get(0)}: ${environment.get(i).get(1)}\n"
129 }
130 writeFile file: file, text: envString
131}
132
133/**
134 * Create new OpenStack Heat stack
135 *
136 * @param env Connection parameters for OpenStack API endpoint
137 * @param template HOT template for the new Heat stack
138 * @param environment Environmentale parameters of the new Heat stack
139 * @param name Name of the new Heat stack
140 * @param path Optional path to the custom virtualenv
141 */
142def createHeatStack(client, name, template, params = [], environment = null, path = null) {
143 def python = new com.mirantis.mk.python()
144 templateFile = "${env.WORKSPACE}/template/template/${template}.hot"
145 if (environment) {
146 envFile = "${env.WORKSPACE}/template/env/${template}/${name}.env"
147 envSource = "${env.WORKSPACE}/template/env/${template}/${environment}.env"
148 createHeatEnv(envFile, params, envSource)
149 }
150 else {
151 envFile = "${env.WORKSPACE}/template/${name}.env"
152 createHeatEnv(envFile, params)
153 }
154 cmd = "heat stack-create -f ${templateFile} -e ${envFile} ${name}"
155 dir("${env.WORKSPACE}/template/template") {
156 outputTable = runOpenstackCommand(cmd, client, path)
157 }
158 output = python.parseTextTable(outputTable, 'item', 'prettytable')
159
160 i = 1
161 while (true) {
162 status = getHeatStackStatus(client, name, path)
163 echo("[Heat Stack] Status: ${status}, Check: ${i}")
164 if (status == 'CREATE_FAILED') {
165 info = getHeatStackInfo(client, name, path)
166 throw new Exception(info.stack_status_reason)
167 }
168 else if (status == 'CREATE_COMPLETE') {
169 info = getHeatStackInfo(client, name, path)
170 echo(info.stack_status_reason)
171 break
172 }
173 sh('sleep 5s')
174 i++
175 }
176 echo("[Heat Stack] Status: ${status}")
177}
178
179/**
180 * Get life cycle status for existing OpenStack Heat stack
181 *
182 * @param env Connection parameters for OpenStack API endpoint
183 * @param name Name of the managed Heat stack instance
184 * @param path Optional path to the custom virtualenv
185 */
186def getHeatStackStatus(client, name, path = null) {
187 cmd = 'heat stack-list | awk -v stack='+name+' \'{if ($4==stack) print $6}\''
188 return runOpenstackCommand(cmd, client, path)
189}
190
191/**
192 * Get info about existing OpenStack Heat stack
193 *
194 * @param env Connection parameters for OpenStack API endpoint
195 * @param name Name of the managed Heat stack instance
196 * @param path Optional path to the custom virtualenv
197 */
198def getHeatStackInfo(env, name, path = null) {
199 def python = new com.mirantis.mk.python()
200 cmd = "heat stack-show ${name}"
201 outputTable = runOpenstackCommand(cmd, env, path)
202 output = python.parseTextTable(outputTable, 'item', 'prettytable')
203 return output
204}
205
206/**
207 * Get existing OpenStack Heat stack output parameter
208 *
209 * @param env Connection parameters for OpenStack API endpoint
210 * @param name Name of the managed Heat stack
211 * @param parameter Name of the output parameter
212 * @param path Optional path to the custom virtualenv
213 */
214def getHeatStackOutputParam(env, name, outputParam, path = null) {
215 cmd = "heat output-show ${name} ${outputParam}"
216 output = runOpenstackCommand(cmd, env, path)
217 return output.substring(1, output.length()-1)
218}
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)
231 output = python.parseTextTable(outputTable, 'list', 'prettytable')
232 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)
246 output = python.parseTextTable(outputTable, 'item', 'prettytable')
247 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)
261 output = python.parseTextTable(outputTable, 'item', 'prettytable')
262 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}