Martin Polreich | 4a9f71c | 2018-10-17 16:40:51 +0200 | [diff] [blame] | 1 | /** |
| 2 | * Generate cookiecutter cluster by individual products |
| 3 | * |
| 4 | * Expected parameters: |
| 5 | * COOKIECUTTER_TEMPLATE_CONTEXT Context parameters for the template generation. |
| 6 | * SALT_MASTER_URL URL of Salt master |
| 7 | * SALT_MASTER_CREDENTIALS Credentials to the Salt API |
| 8 | * |
| 9 | **/ |
| 10 | |
| 11 | import static groovy.json.JsonOutput.toJson |
| 12 | |
| 13 | common = new com.mirantis.mk.Common() |
| 14 | python = new com.mirantis.mk.Python() |
| 15 | salt = new com.mirantis.mk.Salt() |
| 16 | ssh = new com.mirantis.mk.Ssh() |
| 17 | |
| 18 | pepperEnv = "pepperEnv" |
| 19 | |
| 20 | slaveNode = env.SLAVE_NODE ?: 'python&&docker' |
| 21 | model_job = 0 |
| 22 | |
| 23 | timeout(time: 2, unit: 'HOURS') { |
| 24 | node(slaveNode) { |
| 25 | try { |
| 26 | def templateContext = readYaml text: COOKIECUTTER_TEMPLATE_CONTEXT |
| 27 | def clusterName = templateContext.default_context.cluster_name |
| 28 | def aioNodeHostname = templateContext.default_context.aio_node_hostname |
| 29 | def aioInternalAddress = templateContext.default_context.aio_internal_address |
| 30 | def drivetrainInternalAddress = templateContext.default_context.drivetrain_internal_address |
| 31 | def artifact_tar_file = "${clusterName}.tar.gz" |
Martin Polreich | 4a9f71c | 2018-10-17 16:40:51 +0200 | [diff] [blame] | 32 | def masterIP = templateContext.default_context.drivetrain_external_address |
Adam Tengler | c9ed4dc | 2018-10-31 18:26:28 +0100 | [diff] [blame] | 33 | if ( templateContext.default_context.get("docker_deployment", "False").toBoolean() ) { |
| 34 | masterIP = drivetrainInternalAddress |
| 35 | } |
Martin Polreich | 4a9f71c | 2018-10-17 16:40:51 +0200 | [diff] [blame] | 36 | def masterUrl = "http://" + masterIP + ":6969" |
Martin Polreich | 4a9f71c | 2018-10-17 16:40:51 +0200 | [diff] [blame] | 37 | def outputDirectory = env.WORKSPACE + "/" |
Martin Polreich | 4a9f71c | 2018-10-17 16:40:51 +0200 | [diff] [blame] | 38 | def outputDestination = outputDirectory + artifact_tar_file |
| 39 | def outputCluster = outputDirectory + "/classes/cluster/" + clusterName |
Adam Tengler | c9ed4dc | 2018-10-31 18:26:28 +0100 | [diff] [blame] | 40 | def rsyncLocation = templateContext.default_context.get("rsync_location", "/srv/salt/reclass/classes/cluster") |
| 41 | def rsyncCredentials = templateContext.default_context.get("rsync_credentials", "lab") |
| 42 | c = common.getSshCredentials(rsyncCredentials) |
| 43 | def rsyncSSHKey = c.getPrivateKey() |
| 44 | def rsyncUser = c.getUsername() |
| 45 | def rsyncKeyFile = outputDirectory + "rsync_key" |
| 46 | def rsyncPath = rsyncUser + "@" + masterIP + ":" + rsyncLocation |
Martin Polreich | 4a9f71c | 2018-10-17 16:40:51 +0200 | [diff] [blame] | 47 | currentBuild.description = "Cluster " + clusterName + " on " + masterIP |
| 48 | |
| 49 | stage("Generate AIO model") { |
| 50 | model_job = build(job: 'generate-salt-model-separated-products', |
| 51 | parameters: [ |
| 52 | [$class: 'StringParameterValue', name: 'COOKIECUTTER_TEMPLATE_CONTEXT', value: COOKIECUTTER_TEMPLATE_CONTEXT ], |
| 53 | [$class: 'BooleanParameterValue', name: 'TEST_MODEL', value: false], |
| 54 | ]) |
| 55 | } |
| 56 | |
| 57 | stage("Download artifact with model") { |
| 58 | artifact_tar_url = "${env.JENKINS_URL}/job/generate-salt-model-separated-products/${model_job.number}/artifact/output-${clusterName}/${artifact_tar_file}" |
| 59 | sh "wget --progress=dot:mega --auth-no-challenge -O ${outputDestination} '${artifact_tar_url}'" |
| 60 | sh "tar -xzvf ${outputDestination}" |
| 61 | } |
| 62 | |
| 63 | stage("Send model to Salt master node") { |
| 64 | ssh.ensureKnownHosts(masterIP) |
| 65 | writeFile(file: rsyncKeyFile, text: rsyncSSHKey) |
| 66 | sh("chmod 600 ${rsyncKeyFile}") |
| 67 | common.infoMsg("Copying cluster model to ${rsyncPath}") |
| 68 | sh("rsync -r -e \"ssh -i ${rsyncKeyFile}\" ${outputCluster} ${rsyncPath}") |
| 69 | } |
| 70 | |
| 71 | stage("Setup virtualenv for Pepper") { |
Ivan Berezovskiy | 46b7bbc | 2018-10-30 22:32:13 +0400 | [diff] [blame] | 72 | python.setupPepperVirtualenv(pepperEnv, masterUrl, SALT_MASTER_CREDENTIALS) |
Martin Polreich | 4a9f71c | 2018-10-17 16:40:51 +0200 | [diff] [blame] | 73 | } |
| 74 | |
| 75 | stage("Prepare AIO node"){ |
| 76 | tgt = "S@" + aioInternalAddress |
| 77 | // Classify AIO node |
| 78 | eventData = [:] |
| 79 | eventData["node_control_ip"] = aioInternalAddress |
| 80 | eventData["node_os"] = "xenial" |
| 81 | eventData["node_master_ip"] = drivetrainInternalAddress |
| 82 | eventData["node_hostname"] = aioNodeHostname |
| 83 | eventData["node_cluster"] = clusterName |
| 84 | eventJson = toJson(eventData) |
| 85 | event = "salt-call event.send \"reclass/minion/classify\" \'" + eventJson + "\'" |
| 86 | salt.cmdRun(pepperEnv, tgt, event) |
| 87 | sleep(30) |
| 88 | // Upgrade Salt minion |
| 89 | salt.runSaltProcessStep(pepperEnv, tgt, 'pkg.install', "salt-minion") |
| 90 | sleep(10) |
| 91 | // Run core states on AIO node |
| 92 | salt.fullRefresh(pepperEnv, '*') |
| 93 | salt.enforceState(pepperEnv, tgt, 'linux') |
| 94 | salt.enforceState(pepperEnv, tgt, 'salt') |
| 95 | salt.enforceState(pepperEnv, tgt, 'openssh') |
| 96 | salt.enforceState(pepperEnv, tgt, 'ntp') |
| 97 | salt.enforceState(pepperEnv, tgt, 'rsyslog') |
| 98 | } |
| 99 | |
| 100 | stage("Deploy Openstack") { |
| 101 | build(job: 'deploy_openstack', |
| 102 | parameters: [ |
Ivan Berezovskiy | 46b7bbc | 2018-10-30 22:32:13 +0400 | [diff] [blame] | 103 | [$class: 'StringParameterValue', name: 'SALT_MASTER_CREDENTIALS', value: SALT_MASTER_CREDENTIALS], |
Martin Polreich | 4a9f71c | 2018-10-17 16:40:51 +0200 | [diff] [blame] | 104 | [$class: 'StringParameterValue', name: 'SALT_MASTER_URL', value: masterUrl], |
| 105 | [$class: 'StringParameterValue', name: 'STACK_INSTALL', value: 'openstack'] |
| 106 | ]) |
| 107 | } |
| 108 | } catch (Throwable e) { |
| 109 | currentBuild.result = "FAILURE" |
| 110 | currentBuild.description = currentBuild.description ? e.message + " " + currentBuild.description : e.message |
| 111 | throw e |
| 112 | } finally { |
| 113 | stage('Clean workspace directories') { |
| 114 | sh(script: 'find . -mindepth 1 -delete > /dev/null || true') |
| 115 | } |
| 116 | // common.sendNotification(currentBuild.result,"",["slack"]) |
| 117 | } |
| 118 | } |
| 119 | } |