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