Add Jenkins file for pipeline testing

Change-Id: Iff703121d77e09b2b7ade81d092a1b3f60f05209
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100755
index 0000000..3ca638a
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,175 @@
+import java.util.regex.Pattern
+/**
+ *
+ * Images build pipeline
+ *
+ * Expected parameters:
+ *    BUILD_OS
+ *    BUILD_ONLY
+ *    PACKER_DEBUG
+ *    PACKER_URL
+ *    PACKER_ZIP
+ *    PACKER_ZIP_MD5
+ *    PACKER_ARGS
+ *    UPLOAD_URL
+ *    SKIP_UPLOAD
+ *    CLEANUP_OLD
+ *    CLEANUP_KEEP
+ *    PIPELINE_LIBS_URL
+ *    PIPELINE_LIBS_BRANCH
+ *    PIPELINE_LIBS_CREDENTIALS_ID
+ */
+
+
+// Load shared libs
+def common
+fileLoader.withGit(PIPELINE_LIBS_URL, PIPELINE_LIBS_BRANCH, PIPELINE_LIBS_CREDENTIALS_ID, '') {
+    common = fileLoader.load("common");
+}
+
+node('qemu') {
+    // Define global variables
+    def workspace = common.getWorkspace()
+    def buildTypes = BUILD_ONLY.tokenize(" ")
+    checkout scm
+    try {
+        stage("prepare") {
+            if (!fileExists("${workspace}/tmp")) {
+                sh "mkdir -p ${workspace}/tmp"
+            }
+            if (!fileExists("${workspace}/images")) {
+                sh "mkdir ${workspace}/images"
+            }
+        }
+        if (!fileExists("bin")) {
+            println("Downloading packer")
+            sh "mkdir bin"
+            dir("bin") {
+                sh "wget -O ${PACKER_ZIP} ${PACKER_URL}"
+                sh "echo \"${PACKER_ZIP_MD5} ${PACKER_ZIP}\" >> md5sum"
+                sh "md5sum -c --status md5sum"
+                sh "unzip ${PACKER_ZIP}"
+            }
+        }
+        stage("build") {
+            dir(BUILD_OS) {
+                withEnv([String.format("PATH=%s:%s/bin", env.PATH, workspace),
+                    "PACKER_LOG_PATH=${workspace}/packer.log",
+                    "PACKER_LOG=1",
+                    "TMPDIR=${workspace}/tmp"
+                ]) {
+                    if (PACKER_DEBUG == 'true') {
+                        PACKER_ARGS = "${PACKER_ARGS} -debug"
+                    }
+                    sh "packer build -only=${BUILD_ONLY} ${PACKER_ARGS} -parallel=false template.json"
+                    def packerStatus = sh(script: "grep \"Some builds didn't complete successfully and had errors\" ${PACKER_LOG_PATH}", returnStatus: true)
+                    // grep returns 0 if find something
+                    if (packerStatus != 0) {
+                        if (buildTypes.contains("qemu")) {
+                            def imageQemu = sh(script: "find images/ | grep -- '-qemu-' | tail -1", returnStdout: true).trim()
+                            if (imageQemu != null && imageQemu != "") {
+                                def qemuConvertStatus = sh(script: "qemu-img convert -c -O qcow2 ${imageQemu} ${imageQemu}.qcow2", returnStatus:true)
+                                if(qemuConvertStatus == 0){
+                                    sh "mv ${imageQemu}/${imageQemu}.qcow2 .."
+                                    sh "rm -f ${imageQemu}"
+                                }else{
+                                    throw new Exception("Qemu image convert failed")
+                                }
+                            }
+                        }
+                        if (buildTypes.contains("docker")) {
+                            def imageDocker = sh(script: "find images/ | grep -- '-docker-' | grep '.tar\$' | tail -1", returnStdout: true).trim()
+                            if (imageDocker != null && imageDocker != "") {
+                                def pbZip2Status = sh(script: "pbzip2 ${imageDocker}", returnStatus: true)
+                                if(pbZip2Status == 0){
+                                    sh "rm -f ${imageDocker}"
+                                }else{
+                                    throw new Exception("pbzip2 image convert failed")
+                                }
+                            }
+                        }
+                    } else {
+                      throw new Exception("Packer build failed")
+                    }
+                }
+            }
+        }
+        stage("upload"){
+            dir(BUILD_OS + "/images") {
+                def images = findFiles(glob: "*.*")
+                def uploadedImages=[]
+                def cleanedImages=[]
+                def imageBuilds = [:]
+                for (int i = 0; i < images.size(); i++) {
+                    def imageName = images[i].name
+                    def imageNameList = imageName.tokenize(".")
+                    def imageType = "." + imageNameList[imageNameList.size() - 1]
+                    if(imageType.equals(".md5")){
+                        continue;
+                    }
+                    imageBuilds["build${i}"]={
+                        if (SKIP_UPLOAD != 'true') {
+                            sh "md5sum ${imageName} > ${imageName}.md5"
+                            println("Uploading image " + imageName)
+                            def uploadImageStatus = sh(script: "curl -f -T ${imageName} ${UPLOAD_URL}", returnStatus: true)
+                            def uploadMd5Status = sh(script: "curl -f -T ${imageName}.md5 ${UPLOAD_URL}", returnStatus: true)
+                            if(uploadImageStatus==0 && uploadMd5Status == 0){
+                                uploadedImages.add(imageName)
+                                sh(String.format("rm -r *%s*", BUILD_OS.replaceAll(/\./,"-")))
+                            }else{
+                                throw new Exception("Image upload failed")
+                            }
+                        }
+                        if (CLEANUP_OLD == 'true') {
+                            def remoteImages = sh(script: "curl -f -sss ${UPLOAD_URL} | grep -Eo '>.*\\.(qcow2|box|tar\\.bz2)</a>' | sed -e 's,>,,g' -e 's,</a,,g'", returnStdout: true)
+                            if (remoteImages != "") {
+                                def cleanupImages = getCleanupImageList(remoteImages, imageType, BUILD_OS)
+                                def deleteCount = cleanupImages.size() - Integer.parseInt(CLEANUP_KEEP)
+                                if (deleteCount > 0) {
+                                    for (int j = 0; j < deleteCount; j++) {
+                                        println(String.format("Deleting image %s from aptly", cleanupImages[j]))
+                                        sh "curl -f -X DELETE ${UPLOAD_URL}/" + cleanupImages[j]
+                                        def imageTypeForRegex = Pattern.quote(imageType)
+                                        def imageMd5 = cleanupImages[j].replaceAll(/${imageTypeForRegex}$/, ".md5")
+                                        sh "curl -f -X DELETE ${UPLOAD_URL}/" + imageMd5
+
+                                        sh "curl -f -X DELETE ${UPLOAD_URL}/${cleanupImages[j]} || true"
+                                        sh "curl -f -X DELETE ${UPLOAD_URL}/${imageMd5} || true"
+                                        cleanedImages.add(cleanupImages[j])
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                parallel imageBuilds
+                println(String.format("Uploaded %s images with names %s", uploadedImages.size(), uploadedImages.toString()))
+                println(String.format("Cleaned %s images with names %s", cleanedImages.size(), cleanedImages.toString()))
+            }
+        }
+    } catch (Throwable e) {
+        // If there was an error or exception thrown, the build failed
+        currentBuild.result = "FAILURE"
+        throw e
+    } finally {
+        common.sendNotification(currentBuild.result, "", ["slack"])
+        if (buildTypes.contains("docker")) {
+            withEnv(["PACKER_LOG_PATH=${workspace}/packer.log"]) {
+                sh "docker rmi --force \$(grep \"docker: Image ID:\" ${PACKER_LOG_PATH} | cut -d : -f 6 | head -1 | sed s,\\ ,,g) || true"
+            }
+        }
+    }
+}
+
+@NonCPS
+def getCleanupImageList(remoteImagesString, imageType, osImage) {
+    def remoteImages = remoteImagesString.tokenize("\n")
+    def imageTypeForRegex = Pattern.quote(imageType)
+    def osImageForRegex = Pattern.quote(osImage)
+    def remoteImagesSameType = remoteImages.findAll {
+        it = ~/${imageTypeForRegex}$/
+    }
+    return remoteImagesSameType.toSorted().findAll {
+        it = ~/^${osImageForRegex}-/
+    }
+}
\ No newline at end of file