blob: d0a538fc0101992dcd71326978ba5923a742926c [file] [log] [blame]
alshabib82e7fbc2017-01-06 11:41:41 -08001def filename = 'manifest-${branch}.xml'
Luca Prete8c3afd22017-06-29 10:30:08 +02002def manifestUrl = 'https://gerrit.opencord.org/manifest'
3def config = null;
alshabib4e1c96e2016-09-28 16:26:24 -07004
alshabib23ac16d2017-01-07 09:46:43 -08005node ('master') {
Luca Prete8c3afd22017-06-29 10:30:08 +02006 checkout changelog: false, poll: false, scm: [$class: 'RepoScm', currentBranch: true, manifestBranch: params.branch, manifestRepositoryUrl: "${manifestUrl}", quiet: true]
alshabib82e7fbc2017-01-06 11:41:41 -08007
Luca Prete8c3afd22017-06-29 10:30:08 +02008 stage ("Generate and Copy Manifest file") {
9 sh returnStdout: true, script: 'repo manifest -r -o ' + filename
10 sh returnStdout: true, script: 'cp ' + filename + ' ' + env.JENKINS_HOME + '/tmp'
11 }
12
13 stage ("Parse deployment configuartion file") {
14 sh returnStdout: true, script: 'rm -rf ${configRepoBaseDir}'
Luca Prete1f8f8612017-06-30 14:28:34 +020015 sh returnStdout: true, script: 'git clone -b ${branch} ${configRepoUrl}'
Luca Prete8c3afd22017-06-29 10:30:08 +020016 config = readYaml file: "${configRepoBaseDir}${configRepoFile}"
17 }
alshabib23ac16d2017-01-07 09:46:43 -080018}
19
Luca Prete8c3afd22017-06-29 10:30:08 +020020node ("${config.dev_node.name}") {
21 timeout (time: 240) {
22 stage ('Checkout cord repo') {
23 checkout changelog: false, poll: false, scm: [$class: 'RepoScm', currentBranch: true, manifestBranch: params.branch, manifestRepositoryUrl: "${manifestUrl}", quiet: true]
24 }
alshabib82e7fbc2017-01-06 11:41:41 -080025
Luca Prete8c3afd22017-06-29 10:30:08 +020026 dir('build') {
alshabib82e7fbc2017-01-06 11:41:41 -080027 try {
Luca Prete8c3afd22017-06-29 10:30:08 +020028 stage ("Re-deploy head node and Build Vagrant box") {
29 parallel(
30 maasOps: {
31 sh "maas login maas http://${config.maas.ip}/MAAS/api/2.0 ${config.maas.api_key}"
32 sh "maas maas machine release ${config.maas.head_system_id}"
alshabib82e7fbc2017-01-06 11:41:41 -080033
Luca Prete8c3afd22017-06-29 10:30:08 +020034 timeout(time: 15) {
35 waitUntil {
36 try {
37 sh "maas maas machine read ${config.maas.head_system_id} | grep Ready"
38 return true
39 } catch (exception) {
40 return false
41 }
42 }
43 }
44
45 sh 'maas maas machines allocate'
46 sh "maas maas machine deploy ${config.maas.head_system_id}"
47
48 timeout(time: 30) {
49 waitUntil {
50 try {
51 sh "maas maas machine read ${config.maas.head_system_id} | grep Deployed"
52 return true
53 } catch (exception) {
54 return false
55 }
56 }
57 }
58
59 }, vagrantOps: {
60 sh 'vagrant up corddev'
61 }, failFast : true
62 )
63 }
64
65 stage ("Fetch CORD packages") {
66 sh "vagrant ssh -c \"cd /cord/build; ./gradlew fetch\" corddev"
67 }
68
69 stage ("Build CORD Images") {
70 sh "vagrant ssh -c \"cd /cord/build; ./gradlew buildImages\" corddev"
71 }
72
73 stage ("Downloading CORD POD configuration") {
Luca Prete1f8f8612017-06-30 14:28:34 +020074 sh "vagrant ssh -c \"cd /cord/build/config; git clone -b ${branch} ${config.pod_config.repo_url}\" corddev"
Luca Prete8c3afd22017-06-29 10:30:08 +020075 }
76
77 stage ("Publish to headnode") {
78 sh "vagrant ssh -c \"cd /cord/build; ./gradlew -PtargetReg=${config.head.ip}:5000 -PdeployConfig=config/pod-configs/${config.pod_config.file_name} publish\" corddev"
79 }
80
81 stage ("Deploy") {
82 sh "vagrant ssh -c \"cd /cord/build; ./gradlew -PtargetReg=${config.head.ip}:5000 -PdeployConfig=config/pod-configs/${config.pod_config.file_name} deploy\" corddev"
83 }
84
85 stage ("Power cycle compute nodes") {
86 for(int i=0; i < config.compute_nodes.size(); i++) {
87 sh "ipmitool -U ${config.compute_nodes[i].ipmi.user} -P ${config.compute_nodes[i].ipmi.pass} -H ${config.compute_nodes[i].ipmi.ip} power cycle"
88 }
89 }
90
91 stage ("Wait for compute nodes to get deployed") {
92 sh "ssh-keygen -f /home/${config.dev_node.user}/.ssh/known_hosts -R ${config.head.ip}"
93 def cordApiKey = runCmd("${config.head.ip}",
94 "${config.head.user}",
95 "${config.head.pass}",
96 "sudo maas-region-admin apikey --username ${config.head.user}")
97 runCmd("${config.head.ip}",
98 "${config.head.user}",
99 "${config.head.pass}",
100 "maas login pod-maas http://${config.head.ip}/MAAS/api/1.0 ${cordApiKey}")
101 timeout(time: 45) {
102 waitUntil {
103 try {
104 num = runCmd("${config.head.ip}",
105 "${config.head.user}",
106 "${config.head.pass}",
107 "maas pod-maas nodes list | grep -i deployed | wc -l").trim()
Luca Prete611274f2017-07-07 12:29:38 +0200108 return num.toInteger() == config.compute_nodes.size()
Luca Prete8c3afd22017-06-29 10:30:08 +0200109 } catch (exception) {
110 return false
111 }
112 }
113 }
114 }
115
116 stage ("Wait for computes nodes to be provisioned") {
117 ip = runCmd("${config.head.ip}",
118 "${config.head.user}",
119 "${config.head.pass}",
120 "docker inspect --format '{{.NetworkSettings.Networks.maas_default.IPAddress}}' provisioner").trim()
121 timeout(time:45) {
122 waitUntil {
123 try {
124 out = runCmd("${config.head.ip}",
125 "${config.head.user}",
126 "${config.head.pass}",
Luca Prete611274f2017-07-07 12:29:38 +0200127 "curl -sS http://$ip:4243/provision/ | jq -c \".[] | select(.status | contains(${config.compute_nodes.size()}))\"".trim())
Luca Prete8c3afd22017-06-29 10:30:08 +0200128 return out != ""
129 } catch (exception) {
130 return false
131 }
132 }
133 }
134 }
135
136 if (config.fabric_switches != null) {
137 stage("Reserve IPs for fabric switches and restart maas-dhcp service") {
138 for(int i=0; i < config.fabric_switches.size(); i++) {
139 def append = "";
140 if (i!=0) {
141 append = "-a";
142 }
143 def str = createMACIPbindingStr(i+1,
144 "${config.fabric_switches[i].mac}",
145 "${config.fabric_switches[i].ip}")
146 runCmd("${config.head.ip}",
147 "${config.head.user}",
148 "${config.head.pass}",
149 "echo -e $str '|' sudo tee $append /etc/dhcp/dhcpd.reservations > /dev/null")
150 }
151 runCmd("${config.head.ip}",
152 "${config.head.user}",
153 "${config.head.pass}",
154 "sudo restart maas-dhcpd")
155
156 runCmd("${config.head.ip}",
157 "${config.head.user}",
158 "${config.head.pass}",
159 "cord harvest go")
160 }
161
162 stage ("Wait for fabric switches to get deployed") {
163 for(int i=0; i < config.fabric_switches.size(); i++) {
164 runFabricCmd("${config.head.ip}",
165 "${config.head.user}",
166 "${config.head.pass}",
167 "${config.fabric_switches[i].ip}",
168 "${config.fabric_switches[i].user}",
169 "${config.fabric_switches[i].pass}",
170 "sudo onl-onie-boot-mode install")
171
172 runFabricCmd("${config.head.ip}",
173 "${config.head.user}",
174 "${config.head.pass}",
175 "${config.fabric_switches[i].ip}",
176 "${config.fabric_switches[i].user}",
177 "${config.fabric_switches[i].pass}",
178 "sudo reboot")
179 }
180 timeout(time: 45) {
alshabib82e7fbc2017-01-06 11:41:41 -0800181 waitUntil {
Luca Prete8c3afd22017-06-29 10:30:08 +0200182 try {
183 def harvestCompleted = runCmd("${config.head.ip}",
184 "${config.head.user}",
185 "${config.head.pass}",
186 "cord harvest list '|' grep -i fabric '|' wc -l").trim()
Luca Prete611274f2017-07-07 12:29:38 +0200187 return harvestCompleted.toInteger() == config.fabric_switches.size()
alshabib82e7fbc2017-01-06 11:41:41 -0800188 } catch (exception) {
189 return false
190 }
alshabibef069942016-09-09 17:08:36 -0700191 }
192 }
Luca Prete8c3afd22017-06-29 10:30:08 +0200193 }
alshabib4e1c96e2016-09-28 16:26:24 -0700194
Luca Prete8c3afd22017-06-29 10:30:08 +0200195 stage ("Wait for fabric switches to be provisioned") {
196 timeout(time:45) {
alshabib82e7fbc2017-01-06 11:41:41 -0800197 waitUntil {
Luca Prete8c3afd22017-06-29 10:30:08 +0200198 try {
199 def provCompleted = 0
200 for(int i=0; i < config.fabric_switches.size(); i++) {
201 def count = runCmd("${config.head.ip}",
202 "${config.head.user}",
203 "${config.head.pass}",
204 "cord prov list '|' grep -i ${config.fabric_switches[i].ip} '|' grep -i complete '|' wc -l").trim()
205 provCompleted = provCompleted + count.toInteger()
206 }
207 return provCompleted == config.fabric_switches.size()
alshabib82e7fbc2017-01-06 11:41:41 -0800208 } catch (exception) {
209 return false
210 }
alshabibef069942016-09-09 17:08:36 -0700211 }
212 }
alshabib4e1c96e2016-09-28 16:26:24 -0700213 }
214 }
alshabib4e1c96e2016-09-28 16:26:24 -0700215
Luca Prete8c3afd22017-06-29 10:30:08 +0200216 if (config.make_release == true) {
217 stage ("Trigger Build") {
218 url = 'https://jenkins.opencord.org/job/release-build/job/' + params.branch + '/build'
219 httpRequest authentication: 'auto-release', httpMode: 'POST', url: url, validResponseCodes: '201'
alshabib7f3be8d2016-09-27 18:04:56 -0700220 }
221 }
alshabib82e7fbc2017-01-06 11:41:41 -0800222
alshabib82e7fbc2017-01-06 11:41:41 -0800223 currentBuild.result = 'SUCCESS'
224 } catch (err) {
225 currentBuild.result = 'FAILURE'
Luca Prete2bec54d2017-03-10 10:40:17 -0800226 step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: "${notificationEmail}", sendToIndividuals: false])
alshabib82e7fbc2017-01-06 11:41:41 -0800227 } finally {
228 sh 'vagrant destroy -f corddev'
Luca Prete6f9f8482017-03-10 16:46:20 -0800229 sh 'rm -rf config/pod-configs'
alshabib7f3be8d2016-09-27 18:04:56 -0700230 }
alshabib82e7fbc2017-01-06 11:41:41 -0800231 echo "RESULT: ${currentBuild.result}"
232 }
alshabib82e7fbc2017-01-06 11:41:41 -0800233 }
alshabib152823c2016-09-07 23:49:12 -0700234}
Luca Prete8c3afd22017-06-29 10:30:08 +0200235
236/**
237 * Returns a string used to bind IPs and MAC addresses, substituting the values
238 * given.
239 *
240 * @param counter the counter used to generate the host name
241 * @param mac the MAC address to substitute
242 * @param ip the IP address to substitute
243 */
244def createMACIPbindingStr(counter, mac, ip) {
245 return """\\'host fabric${counter} {'\n'hardware ethernet ${mac}';''\n'fixed-address ${ip}';''\n'}\\'"""
246}
247
248/**
249 * Runs a command on a remote host using sshpass.
250 *
251 * @param ip the node IP address
252 * @param user the node user name
253 * @param pass the node password
254 * @param command the command to run
255 * @return the output of the command
256 */
257def runCmd(ip, user, pass, command) {
Luca Prete611274f2017-07-07 12:29:38 +0200258 return sh(returnStdout: true, script: "sshpass -p ${pass} ssh -oStrictHostKeyChecking=no -l ${user} ${ip} ${command}")
Luca Prete8c3afd22017-06-29 10:30:08 +0200259}
260
261/**
262 * Runs a command on a fabric switch.
263 *
264 * @param headIp the head node IP address
265 * @param headUser the head node user name
266 * @param headPass the head node password
267 * @param ip the mgmt IP of the fabric switch, reachable from the head node
268 * @param user the mgmt user name of the fabric switch
269 * @param pass the mgmt password of the fabric switch
270 * @param command the command to run on the fabric switch
271 * @return the output of the command
272 */
Luca Pretec116f202017-06-30 11:15:03 +0200273def runFabricCmd(headIp, headUser, headPass, ip, user, pass, command) {
Luca Prete611274f2017-07-07 12:29:38 +0200274 return sh(returnStdout: true, script: "sshpass -p ${headPass} ssh -oStrictHostKeyChecking=no -l ${headUser} ${headIp} \"sshpass -p ${pass} ssh -oStrictHostKeyChecking=no -l ${user} ${ip} ${command}\"")
Luca Prete8c3afd22017-06-29 10:30:08 +0200275}