blob: 01aae1404694cf393514f55949d346a72b2d0794 [file] [log] [blame]
Anton Samoylovc6400692019-01-16 00:36:00 +04001/**
2 * Update pipeline for OpenContrail 4X versions
3 *
4 * Expected parameters:
5 * SALT_MASTER_CREDENTIALS Credentials to the Salt API.
6 * SALT_MASTER_URL Full Salt API address [http://10.10.10.1:8000].
7 * STAGE_CONTROLLERS_UPDATE Run update on OpenContrail controller and analytic nodes (bool)
8 * STAGE_COMPUTES_UPDATE Run update OpenContrail components on compute nodes (bool)
9 *
10 **/
11
12common = new com.mirantis.mk.Common()
13salt = new com.mirantis.mk.Salt()
14python = new com.mirantis.mk.Python()
15
16def pepperEnv = "pepperEnv"
17def supportedOcTargetVersions = ['4.0', '4.1']
18def neutronServerPkgs = 'neutron-plugin-contrail,contrail-heat,python-contrail'
19def config4Services = ['zookeeper', 'contrail-webui-middleware', 'contrail-webui', 'contrail-api', 'contrail-schema', 'contrail-svc-monitor', 'contrail-device-manager', 'contrail-config-nodemgr', 'contrail-database']
20def dashboardPanelPkg = 'openstack-dashboard-contrail-panels'
21def targetOcVersion
22
23def cmpMinions
24def cmpMinionsFirstSubset
25def cmpMinionsSecondSubset
26def cmpTargetAll
27def cmpTargetFirstSubset
28def cmpTargetSecondSubset
29
30def checkContrailServices(pepperEnv, oc_version, target) {
31
32 def checkCmd
33
34 if (oc_version.startsWith('4')) {
35
36 checkCmd = "doctrail all contrail-status | grep -v == | grep -v FOR | grep -v \\* | grep -v \'disabled on boot\' | grep -v nodemgr | grep -v active | grep -v backup | grep -v -F /var/crashes/"
37
38 if (oc_version == '4.1') {
39 def targetMinions = salt.getMinions(pepperEnv, target)
40 def collectorMinionsInTarget = targetMinions.intersect(salt.getMinions(pepperEnv, 'I@opencontrail:collector'))
41
42 if (collectorMinionsInTarget.size() != 0) {
43 def cassandraConfigYaml = readYaml text: salt.getFileContent(pepperEnv, 'I@opencontrail:control:role:primary', '/etc/cassandra/cassandra.yaml')
44
45 def currentCassandraNativeTransportPort = cassandraConfigYaml['native_transport_port'] ?: "9042"
46 def currentCassandraRpcPort = cassandraConfigYaml['rpc_port'] ?: "9160"
47
48 def cassandraNativeTransportPort = getValueForPillarKey(pepperEnv, "I@opencontrail:control:role:primary", "opencontrail:database:bind:port_configdb")
49 def cassandraCassandraRpcPort = getValueForPillarKey(pepperEnv, "I@opencontrail:control:role:primary", "opencontrail:database:bind:rpc_port_configdb")
50
51 if (currentCassandraNativeTransportPort != cassandraNativeTransportPort) {
52 checkCmd += ' | grep -v \'contrail-collector.*(Database:Cassandra connection down)\''
53 }
54
55 if (currentCassandraRpcPort != cassandraCassandraRpcPort) {
56 checkCmd += ' | grep -v \'contrail-alarm-gen.*(Database:Cassandra\\[\\] connection down)\''
57 }
58 }
59 }
60
61 } else {
62 checkCmd = "contrail-status | grep -v == | grep -v FOR | grep -v \'disabled on boot\' | grep -v nodemgr | grep -v active | grep -v backup | grep -v -F /var/crashes/"
63 }
64
65 salt.commandStatus(pepperEnv, target, checkCmd, null, false, true, null, true, 500)
66}
67
68def getValueForPillarKey(pepperEnv, target, pillarKey) {
69 def out = salt.getReturnValues(salt.getPillar(pepperEnv, target, pillarKey))
70 if (out == '') {
71 throw new Exception("Cannot get value for ${pillarKey} key on ${target} target")
72 }
73 return out.toString()
74}
75
76def cmpNodesUpdate(pepperEnv, target) {
77
78 def cmpPkgs = 'contrail-lib contrail-nodemgr contrail-utils contrail-vrouter-agent contrail-vrouter-utils python-contrail python-contrail-vrouter-api python-opencontrail-vrouter-netns contrail-vrouter-dkms'
79 def aptCmd = "export DEBIAN_FRONTEND=noninteractive; apt install -o Dpkg::Options::=\"--force-confold\" ${cmpPkgs} -y;"
80 def kernelModuleReloadCmd = 'service contrail-vrouter-agent stop; service contrail-vrouter-nodemgr stop; rmmod vrouter; sync && echo 3 > /proc/sys/vm/drop_caches && echo 1 > /proc/sys/vm/compact_memory; service contrail-vrouter-agent start; service contrail-vrouter-nodemgr start'
81 def out
82
83 try {
84 salt.runSaltProcessStep(pepperEnv, target, 'saltutil.refresh_pillar', [], null, true)
85 salt.runSaltProcessStep(pepperEnv, target, 'saltutil.sync_all', [], null, true)
86 salt.runSaltProcessStep(pepperEnv, target, 'file.remove', ["/etc/apt/sources.list.d/mcp_opencontrail.list"], null, true)
87 salt.enforceState(pepperEnv, target, 'linux.system.repo')
88 } catch (Exception er) {
89 common.errorMsg("Opencontrail component on ${target} probably failed to be replaced. Please check availability of contrail packages before continuing.")
90 throw er
91 }
92
93 out = salt.runSaltCommand(pepperEnv, 'local', ['expression': target, 'type': 'compound'], 'cmd.shell', null, aptCmd, null)
94 salt.printSaltCommandResult(out)
95
96 try {
97 salt.enforceState(pepperEnv, target, 'opencontrail')
98 } catch (Exception er) {
99 common.errorMsg("Opencontrail state was executed on ${target} and failed please fix it manually.")
100 }
101
102 salt.runSaltProcessStep(pepperEnv, target, 'cmd.shell', [kernelModuleReloadCmd], null, true)
103 salt.commandStatus(pepperEnv, target, 'contrail-status | grep -v == | grep -v active | grep -v -F /var/crashes/', null, false)
104 out = salt.runSaltCommand(pepperEnv, 'local', ['expression': target, 'type': 'compound'], 'cmd.shell', null, "contrail-status", null)
105 salt.printSaltCommandResult(out)
106}
107
108timeout(time: 12, unit: 'HOURS') {
109 node() {
110
111 stage('Setup virtualenv for Pepper') {
112 python.setupPepperVirtualenv(pepperEnv, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
113 }
114
115 if (STAGE_CONTROLLERS_UPDATE.toBoolean() == true) {
116
117 stage('Sync Salt data') {
118
119 // Sync data on minions
120 salt.runSaltProcessStep(pepperEnv, 'I@keystone:server:role:primary or I@opencontrail:database or I@neutron:server or I@horizon:server', 'saltutil.refresh_pillar', [], null, true)
121 salt.runSaltProcessStep(pepperEnv, 'I@keystone:server:role:primary or I@opencontrail:database or I@neutron:server or I@horizon:server', 'saltutil.sync_all', [], null, true)
122 }
123
124 stage('Verify OpenContrail version compatibility') {
125
126 // Verify specified target OpenContrail version before update
127 targetOcVersion = getValueForPillarKey(pepperEnv, "I@opencontrail:control:role:primary", "_param:opencontrail_version")
128 if (!supportedOcTargetVersions.contains(targetOcVersion)) {
129 throw new Exception("Specified OpenContrail version ${targetOcVersion} is not supported by update pipeline. Supported versions: ${supportedOcTargetVersions}")
130 }
131 }
132
133 stage('Opencontrail controllers health check') {
134 try {
135 salt.enforceState(pepperEnv, 'I@opencontrail:control or I@opencontrail:collector', 'opencontrail.upgrade.verify', true, true)
136 } catch (Exception er) {
137 common.errorMsg("OpenContrail controllers health check stage found issues with services. Please take a look at the logs above.")
138 throw er
139 }
140 }
141
142 stage('Update system repositories') {
143 try {
144 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:control or I@opencontrail:collector', 'file.remove', ["/etc/apt/sources.list.d/mcp_opencontrail.list"], null, true)
145 salt.enforceState(pepperEnv, 'I@opencontrail:control or I@opencontrail:collector or I@neutron:server or I@horizon:server', 'linux.system.repo')
146
147 } catch (Exception er) {
148 common.errorMsg("System repositories failed to be updated on I@opencontrail:control, I@opencontrail:collector, I@neutron:server or I@horizon:server nodes.")
149 throw er
150 }
151 }
152
153 stage('OpenContrail controllers update') {
154
155 // Make sure that dedicated opencontrail user is created
156 salt.enforceState(pepperEnv, 'I@keystone:server:role:primary', 'keystone.client.server')
157
158 // Stop neutron-server to prevent creation of new objects in contrail
159 salt.runSaltProcessStep(pepperEnv, 'I@neutron:server', 'service.stop', ['neutron-server'])
160
161 // Backup Zookeeper data
162 salt.enforceState(pepperEnv, 'I@zookeeper:backup:server', 'zookeeper.backup')
163 salt.enforceState(pepperEnv, 'I@zookeeper:backup:client', 'zookeeper.backup')
164
165 try {
166 salt.cmdRun(pepperEnv, 'I@opencontrail:control', "su root -c '/usr/local/bin/zookeeper-backup-runner.sh'")
167 } catch (Exception er) {
168 common.errorMsg('Zookeeper failed to backup. Please fix it before continuing.')
169 throw er
170 }
171
172 // Backup Cassandra DB
173 salt.enforceState(pepperEnv, 'I@cassandra:backup:server', 'cassandra.backup')
174 salt.enforceState(pepperEnv, 'I@cassandra:backup:client', 'cassandra.backup')
175
176 try {
177 salt.cmdRun(pepperEnv, 'I@cassandra:backup:client', "su root -c '/usr/local/bin/cassandra-backup-runner-call.sh'")
178 } catch (Exception er) {
179 common.errorMsg('Cassandra failed to backup. Please fix it before continuing.')
180 throw er
181 }
182
183 try {
184 // Get docker images info
185 controllerImage = getValueForPillarKey(pepperEnv, "I@opencontrail:control:role:primary", "docker:client:compose:opencontrail:service:controller:image")
186 analyticsImage = getValueForPillarKey(pepperEnv, "I@opencontrail:collector:role:primary", "docker:client:compose:opencontrail:service:analytics:image")
187 analyticsdbImage = getValueForPillarKey(pepperEnv, "I@opencontrail:collector:role:primary", "docker:client:compose:opencontrail:service:analyticsdb:image")
188
189 // Pull new docker images
190 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:control', 'dockerng.pull', [controllerImage])
191 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:collector', 'dockerng.pull', [analyticsImage])
192 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:collector', 'dockerng.pull', [analyticsdbImage])
193
194 } catch (Exception er) {
195 common.errorMsg("OpenContrail docker images failed be upgraded.")
196 throw er
197 }
198
199 try {
200 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:collector', 'cmd.shell', ['cd /etc/docker/compose/opencontrail/; docker-compose down'], null, true)
201
202 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:collector', 'state.sls', ['opencontrail', 'exclude=opencontrail.client'])
203 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:collector', 'state.sls', ['opencontrail.client'])
204
205 salt.enforceState(pepperEnv, 'I@opencontrail:collector', 'docker.client')
206 if (targetOcVersion == '4.1') {
207 sleep(15)
208 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:collector', 'cmd.shell', ["doctrail analyticsdb systemctl restart confluent-kafka"], null, true)
209 }
210 checkContrailServices(pepperEnv, targetOcVersion, 'I@opencontrail:collector')
211 } catch (Exception er) {
212 common.errorMsg("OpenContrail Analytic nodes failed to be upgraded.")
213 throw er
214 }
215
216 try {
217 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:control:role:secondary', 'cmd.shell', ['cd /etc/docker/compose/opencontrail/; docker-compose down'], null, true)
218 for (service in config4Services) {
219 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:control:role:primary', 'cmd.shell', ["doctrail controller systemctl stop ${service}"], null, true)
220 }
221 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:control:role:secondary', 'state.sls', ['opencontrail', 'exclude=opencontrail.client'])
222
223 salt.enforceState(pepperEnv, 'I@opencontrail:control:role:secondary', 'docker.client')
224 checkContrailServices(pepperEnv, targetOcVersion, 'I@opencontrail:control:role:secondary')
225
226 sleep(120)
227
228 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:control:role:primary', 'cmd.shell', ['cd /etc/docker/compose/opencontrail/; docker-compose down'], null, true)
229 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:control:role:primary', 'state.sls', ['opencontrail', 'exclude=opencontrail.client'])
230
231 salt.enforceState(pepperEnv, 'I@opencontrail:control:role:primary', 'docker.client')
232 checkContrailServices(pepperEnv, targetOcVersion, 'I@opencontrail:control:role:primary')
233 } catch (Exception er) {
234 common.errorMsg("OpenContrail Controller nodes failed to be upgraded.")
235 throw er
236 }
237
238 // Run opencontrail.client state once contrail-api is ready to service requests from clients
239 salt.runSaltProcessStep(pepperEnv, 'I@opencontrail:control or I@opencontrail:collector', 'state.sls', ['opencontrail.client'])
240
241 try {
242 salt.runSaltProcessStep(pepperEnv, 'I@neutron:server', 'pkg.install', [neutronServerPkgs])
243 salt.runSaltProcessStep(pepperEnv, 'I@horizon:server', 'pkg.install', [dashboardPanelPkg])
244 salt.runSaltProcessStep(pepperEnv, 'I@neutron:server', 'service.start', ['neutron-server'])
245 salt.enforceState(pepperEnv, 'I@horizon:server', 'horizon')
246 } catch (Exception er) {
247 common.errorMsg("Update of packages on neutron and horizon nodes has been failed")
248 throw er
249 }
250 }
251 }
252
253 if (STAGE_COMPUTES_UPDATE.toBoolean() == true) {
254
255 try {
256 stage('List targeted compute servers') {
257 cmpMinions = salt.getMinions(pepperEnv, COMPUTE_TARGET_SERVERS)
258 cmpMinionsFirstSubset = cmpMinions[0..<Integer.valueOf(COMPUTE_TARGET_SUBSET_LIVE)]
259 cmpMinionsSecondSubset = cmpMinions - cmpMinionsFirstSubset
260
261 if (cmpMinions.isEmpty()) {
262 throw new Exception("No minions were found by specified target")
263 }
264
265 common.infoMsg("Found nodes: ${cmpMinions}")
266 common.infoMsg("Selected sample nodes: ${cmpMinionsFirstSubset}")
267
268 cmpTargetAll = cmpMinions.join(' or ')
269 cmpTargetFirstSubset = cmpMinionsFirstSubset.join(' or ')
270 cmpTargetSecondSubset = cmpMinionsSecondSubset.join(' or ')
271 }
272
273 stage('Compute nodes health check') {
274 try {
275 salt.enforceState(pepperEnv, cmpTargetAll, 'opencontrail.upgrade.verify', true, true)
276 } catch (Exception er) {
277 common.errorMsg("Opencontrail compute nodes health check stage found issues with services. Please take a look at the logs above.")
278 throw er
279 }
280 }
281
282 stage('Confirm update on sample nodes') {
283 input message: "Do you want to continue with the Opencontrail components update on compute sample nodes? ${cmpTargetFirstSubset}"
284 }
285
286 stage("Opencontrail compute update on sample nodes") {
287
288 cmpNodesUpdate(pepperEnv, cmpTargetFirstSubset)
289 }
290
291 stage('Confirm update on all remaining target nodes') {
292
293 input message: "Do you want to continue with the Opencontrail components update on all targeted compute nodes? Node list: ${cmpTargetSecondSubset}"
294 }
295
296 stage("Opencontrail compute update on all targeted nodes") {
297
298 cmpNodesUpdate(pepperEnv, cmpTargetSecondSubset)
299 }
300
301 } catch (Throwable e) {
302 // If there was an error or exception thrown, the build failed
303 currentBuild.result = "FAILURE"
304 currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message
305 throw e
306 }
307 }
308 }
309}