Merge "Clean up artifacts directory before test"
diff --git a/cloud-deploy-pipeline.groovy b/cloud-deploy-pipeline.groovy
index 66e4bc7..3fd2b8d 100644
--- a/cloud-deploy-pipeline.groovy
+++ b/cloud-deploy-pipeline.groovy
@@ -43,6 +43,8 @@
* which have to be added during bootstrap.
* Format: repo 1, repo priority 1, repo pin 1; repo 2, repo priority 2, repo pin 2;
+ * SALT_VERSION Version of Salt which is going to be installed i.e. 'stable 2016.3' or 'stable 2017.7' etc.
+ *
* Test settings:
* TEST_K8S_API_SERVER Kubernetes API address
* TEST_K8S_CONFORMANCE_IMAGE Path to docker image with conformance e2e tests
@@ -208,6 +210,12 @@
}
}
+
+ if (common.validInputParam('SALT_VERSION')) {
+ common.infoMsg("Setting salt version to ${SALT_VERSION}")
+ envParams.put('cfg_saltversion', SALT_VERSION)
+ }
+
openstack.createHeatStack(openstackCloud, STACK_NAME, STACK_TEMPLATE, envParams, HEAT_STACK_ENVIRONMENT, venv)
}
@@ -342,9 +350,8 @@
}
if (common.checkContains('STACK_INSTALL', 'contrail')) {
- stage('Install Contrail for Kubernetes') {
+ stage('Install Contrail control') {
orchestrate.installContrailNetwork(venvPepper)
- orchestrate.installContrailCompute(venvPepper)
}
}
@@ -356,6 +363,12 @@
archiveArtifacts(artifacts: 'kubeconfig')
}
+ if (common.checkContains('STACK_INSTALL', 'contrail')) {
+ stage('Install Contrail compute') {
+ orchestrate.installContrailCompute(venvPepper)
+ }
+ }
+
stage('Install Kubernetes computes') {
if (common.validInputParam('STACK_COMPUTE_COUNT')) {
if (STACK_COMPUTE_COUNT > 0) {
@@ -409,7 +422,10 @@
orchestrate.installOpenstackNetwork(venvPepper)
}
- salt.cmdRun(venvPepper, 'I@keystone:server', '. /root/keystonercv3; openstack network list')
+ // Wait for network to come up, 150s should be enough
+ common.retry(10, 15) {
+ salt.cmdRun(venvPepper, 'I@keystone:server', '. /root/keystonercv3; openstack network list')
+ }
}
if (salt.testTarget(venvPepper, 'I@ironic:conductor')){
diff --git a/cloud-update.groovy b/cloud-update.groovy
index 8c8b8b6..b6a44b6 100644
--- a/cloud-update.groovy
+++ b/cloud-update.groovy
@@ -425,6 +425,22 @@
}
}
+def periodicCheck(pepperEnv, target, maxRetries=50) {
+ def salt = new com.mirantis.mk.Salt()
+ def common = new com.mirantis.mk.Common()
+ def count = 0
+ while(count < maxRetries) {
+ try {
+ sleep(10)
+ salt.minionsReachable(pepperEnv, 'I@salt:master', target)
+ break
+ } catch (Exception e) {
+ common.warningMsg("${target} not ready yet. Waiting ...")
+ }
+ count++
+ }
+}
+
def highstate(pepperEnv, target, type) {
def salt = new com.mirantis.mk.Salt()
def common = new com.mirantis.mk.Common()
@@ -457,9 +473,17 @@
// optionally reboot
if (reboots.contains(type)) {
stage("Reboot ${target} nodes") {
- salt.runSaltProcessStep(pepperEnv, target, 'system.reboot', null, null, true, 5)
- sleep(10)
- salt.minionsReachable(pepperEnv, 'I@salt:master', target)
+ if (type == 'cfg') {
+ try {
+ salt.runSaltProcessStep(pepperEnv, target, 'system.reboot', null, null, true, 5)
+ } catch (Exception e) {
+ periodicCheck(pepperEnv, target)
+ }
+ } else {
+ salt.runSaltProcessStep(pepperEnv, target, 'system.reboot', null, null, true, 5)
+ sleep 10
+ salt.minionsReachable(pepperEnv, 'I@salt:master', target)
+ }
}
}
}
@@ -683,13 +707,26 @@
def verifyAPIs(pepperEnv, target) {
def salt = new com.mirantis.mk.Salt()
def common = new com.mirantis.mk.Common()
- def out = salt.cmdRun(pepperEnv, target, '. /root/keystonercv3; openstack service list; openstack image list; openstack flavor list; openstack compute service list; openstack server list; openstack network list; openstack volume list; openstack orchestration service list')
- if (out.toString().toLowerCase().contains('error')) {
- common.errorMsg(out)
- if (INTERACTIVE.toBoolean()) {
- input message: "APIs are not working as expected. Please fix it manually."
- } else {
- throw new Exception("APIs are not working as expected")
+ def cmds = ["openstack service list",
+ "openstack image list",
+ "openstack flavor list",
+ "openstack compute service list",
+ "openstack server list",
+ "openstack network list",
+ "openstack volume list",
+ "openstack orchestration service list"]
+ def sourcerc = ". /root/keystonercv3;"
+ def cmdOut = ">/dev/null 2>&1;echo \$?"
+ for (c in cmds) {
+ def command = sourcerc + c + cmdOut
+ def out = salt.cmdRun(pepperEnv, target, "${command}")
+ if (!out.toString().toLowerCase().contains('0')) {
+ common.errorMsg(out)
+ if (INTERACTIVE.toBoolean()) {
+ input message: "APIs are not working as expected. Please fix it manually."
+ } else {
+ throw new Exception("APIs are not working as expected")
+ }
}
}
}
@@ -700,7 +737,7 @@
def out
while(count < maxRetries) {
try {
- out = salt.getReturnValues(salt.cmdRun(pepperEnv, target, 'salt-call mysql.status | grep -A1 wsrep_cluster_size'))
+ out = salt.getReturnValues(salt.cmdRun(pepperEnv, target, 'salt-call -l quiet mysql.status | grep -A1 wsrep_cluster_size'))
} catch (Exception er) {
common.infoMsg(er)
}
diff --git a/cvp-ha.groovy b/cvp-ha.groovy
index 5a091f1..ab5b5d4 100644
--- a/cvp-ha.groovy
+++ b/cvp-ha.groovy
@@ -28,8 +28,8 @@
def saltMaster
def artifacts_dir = 'validation_artifacts/'
def remote_artifacts_dir = '/root/qa_results/'
-def current_target_node = ''
-def first_node = ''
+def current_target_node = null
+def first_node = null
def tempest_result = ''
timeout(time: 12, unit: 'HOURS') {
node() {
@@ -61,6 +61,9 @@
}
}
current_target_node = validate.get_vip_node(saltMaster, TARGET_NODES)
+ if (current_target_node == null) {
+ throw new Exception("Cannot current vip node in ${TARGET_NODES} nodes")
+ }
common.warningMsg("Shutdown current vip node ${current_target_node}")
validate.shutdown_vm_node(saltMaster, current_target_node, 'soft_shutdown')
sleep 15
@@ -83,7 +86,7 @@
throw new Exception("Node ${current_target_node} cannot start")
}
first_node = current_target_node
- current_target_node = ''
+ current_target_node = null
sleep 30
}
stage('Check after shutdown') {
@@ -106,6 +109,7 @@
current_target_node = validate.get_vip_node(saltMaster, TARGET_NODES)
common.warningMsg("Shutdown current vip node ${current_target_node}")
validate.shutdown_vm_node(saltMaster, current_target_node, 'hard_shutdown')
+ //TODO:if previous command fails, keeaplived will not be started on first_node
sleep 10
salt.cmdRun(saltMaster, first_node, "service keepalived start")
}
@@ -126,7 +130,7 @@
if (status == null) {
throw new Exception("Node ${current_target_node} cannot start")
}
- current_target_node = ''
+ current_target_node = null
sleep 30
}
stage('Check after hard shutdown') {
@@ -165,6 +169,7 @@
if (status == null) {
throw new Exception("Node ${current_target_node} cannot start")
}
+ current_target_node = null
tempest_result = validate.runCVPtempest(saltMaster, TEMPEST_TARGET_NODE, TEMPEST_TEST_PATTERN, SKIP_LIST_PATH, remote_artifacts_dir, "docker_tempest_after")
validate.openstack_cleanup(saltMaster, TEMPEST_TARGET_NODE)
if (tempest_result != "finished") {
@@ -185,7 +190,7 @@
if (DEBUG_MODE == 'false') {
salt.cmdRun(saltMaster, TEMPEST_TARGET_NODE, "rm -rf ${remote_artifacts_dir}")
validate.runCleanup(saltMaster, TEMPEST_TARGET_NODE)
- if (current_target_node != '') {
+ if (current_target_node != null) {
common.warningMsg("Powering on node ${current_target_node}")
kvm = validate.locate_node_on_kvm(saltMaster, current_target_node)
salt.cmdRun(saltMaster, kvm, "virsh start ${current_target_node}")
diff --git a/cvp-perf.groovy b/cvp-perf.groovy
index 3443f8a..fe86197 100644
--- a/cvp-perf.groovy
+++ b/cvp-perf.groovy
@@ -43,6 +43,7 @@
validate.addFiles(saltMaster, TARGET_NODE, remote_artifacts_dir, artifacts_dir)
archiveArtifacts artifacts: "${artifacts_dir}/*"
junit "${artifacts_dir}/*.xml"
+ perfReport configType: 'PRT', graphType: 'PRT', sourceDataFiles: "${artifacts_dir}/docker-rally.xml"
}
} catch (Throwable e) {
// If there was an error or exception thrown, the build failed
diff --git a/cvp-spt.groovy b/cvp-spt.groovy
new file mode 100644
index 0000000..ea4680f
--- /dev/null
+++ b/cvp-spt.groovy
@@ -0,0 +1,63 @@
+/**
+ *
+ * Launch pytest frameworks in Jenkins
+ *
+ * Expected parameters:
+ * SALT_MASTER_URL URL of Salt master
+ * SALT_MASTER_CREDENTIALS Credentials to the Salt API
+ *
+ * TESTS_SET Leave empty for full run or choose a file (test)
+ * TESTS_REPO Repo to clone
+ * TESTS_SETTINGS Additional environment varibales to apply
+ * PROXY Proxy to use for cloning repo or for pip
+ *
+ */
+
+validate = new com.mirantis.mcp.Validate()
+
+node() {
+ try{
+ stage('Initialization') {
+ validate.prepareVenv(TESTS_REPO, PROXY)
+ }
+
+ stage('Run Tests') {
+ validate.runTests(SALT_MASTER_URL, SALT_MASTER_CREDENTIALS, TESTS_SET, '', TESTS_SETTINGS)
+ }
+ stage ('Publish results') {
+ archiveArtifacts artifacts: "*"
+ junit "*.xml"
+ plot csvFileName: 'plot-8634d2fe-dc48-4713-99f9-b69a381483aa.csv',
+ group: 'SPT',
+ style: 'line',
+ title: 'SPT Glance results',
+ xmlSeries: [[
+ file: "report.xml",
+ nodeType: 'NODESET',
+ url: '',
+ xpath: '/testsuite/testcase[@name="test_speed_glance"]/properties/property']]
+ plot csvFileName: 'plot-8634d2fe-dc48-4713-99f9-b69a381483bb.csv',
+ group: 'SPT',
+ style: 'line',
+ title: 'SPT HW2HW results',
+ xmlSeries: [[
+ file: "report.xml",
+ nodeType: 'NODESET',
+ url: '',
+ xpath: '/testsuite/testcase[@classname="cvp-spt.cvp_spt.tests.test_hw2hw"]/properties/property']]
+ plot csvFileName: 'plot-8634d2fe-dc48-4713-99f9-b69a381483bc.csv',
+ group: 'SPT',
+ style: 'line',
+ title: 'SPT VM2VM results',
+ xmlSeries: [[
+ file: "report.xml",
+ nodeType: 'NODESET',
+ url: '',
+ xpath: '/testsuite/testcase[@classname="cvp-spt.cvp_spt.tests.test_vm2vm"]/properties/property']]
+ }
+ } catch (Throwable e) {
+ // If there was an error or exception thrown, the build failed
+ currentBuild.result = "FAILURE"
+ throw e
+ }
+}
diff --git a/deploy-aws-k8s-kqueen-pipeline.groovy b/deploy-aws-k8s-kqueen-pipeline.groovy
index 89242a8..0a5903e 100644
--- a/deploy-aws-k8s-kqueen-pipeline.groovy
+++ b/deploy-aws-k8s-kqueen-pipeline.groovy
@@ -16,6 +16,9 @@
*
* SALT_MASTER_CREDENTIALS Credentials to the Salt API
* SALT_MASTER_URL URL of Salt master
+ *
+ * optional parameters for overwriting soft params
+ * SALT_OVERRIDES YAML with overrides for Salt deployment
*/
common = new com.mirantis.mk.Common()
@@ -25,6 +28,7 @@
python = new com.mirantis.mk.Python()
salt = new com.mirantis.mk.Salt()
+
// Define global variables
def venv
def venvPepper
@@ -65,7 +69,7 @@
aws.createStack(venv, aws_env_vars, template_file, STACK_NAME, stack_params)
// wait for stack to be ready
- aws.waitForStatus(venv, aws_env_vars, STACK_NAME, 'CREATE_COMPLETE')
+ aws.waitForStatus(venv, aws_env_vars, STACK_NAME, 'CREATE_COMPLETE', ['ROLLBACK_COMPLETE'], 2400, 30)
// get outputs
saltMasterHost = aws.getOutputs(venv, aws_env_vars, STACK_NAME, 'SaltMasterIP')
@@ -85,6 +89,17 @@
python.setupPepperVirtualenv(venvPepper, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
}
+ // Set up override params
+ if (common.validInputParam('SALT_OVERRIDES')) {
+ stage('Set Salt overrides') {
+ salt.setSaltOverrides(venvPepper, SALT_OVERRIDES)
+ }
+ }
+
+ //
+ // Install
+ //
+
stage('Install core infrastructure') {
def staticMgmtNetwork = false
if (common.validInputParam('STATIC_MGMT_NETWORK')) {
diff --git a/docker-build-image-pipeline.groovy b/docker-build-image-pipeline.groovy
index db448ea..b94928e 100644
--- a/docker-build-image-pipeline.groovy
+++ b/docker-build-image-pipeline.groovy
@@ -69,16 +69,20 @@
}
stage("upload to artifactory"){
if(common.validInputParam("ARTIFACTORY_URL") && common.validInputParam("ARTIFACTORY_NAMESPACE")) {
- def artifactoryServer = Artifactory.server("mcp-ci")
+ def artifactoryName = "mcp-ci";
+ def artifactoryServer = Artifactory.server(artifactoryName)
def shortImageName = IMAGE_NAME
if (IMAGE_NAME.contains("/")) {
shortImageName = IMAGE_NAME.tokenize("/")[1]
}
for (imageTag in imageTagsList) {
sh "docker tag ${IMAGE_NAME} ${ARTIFACTORY_URL}/mirantis/${ARTIFACTORY_NAMESPACE}/${shortImageName}:${imageTag}"
- artifactory.uploadImageToArtifactory(artifactoryServer, ARTIFACTORY_URL,
- "mirantis/${ARTIFACTORY_NAMESPACE}/${shortImageName}",
- imageTag, "docker-dev-local")
+ for(artifactoryRepo in ["docker-dev-local", "docker-prod-local"]){
+ common.infoMsg("Uploading image ${IMAGE_NAME} with tag ${imageTag} to artifactory ${artifactoryName} using repo ${artifactoryRepo}")
+ artifactory.uploadImageToArtifactory(artifactoryServer, ARTIFACTORY_URL,
+ "mirantis/${ARTIFACTORY_NAMESPACE}/${shortImageName}",
+ imageTag, artifactoryRepo)
+ }
}
}else{
common.warningMsg("ARTIFACTORY_URL not given, upload to artifactory skipped")
diff --git a/generate-cookiecutter-products.groovy b/generate-cookiecutter-products.groovy
index a2a4907..0a2888e 100644
--- a/generate-cookiecutter-products.groovy
+++ b/generate-cookiecutter-products.groovy
@@ -223,7 +223,7 @@
}
for (i in common.entries(smc)) {
- sh "sed -i \"s,export ${i[0]}=.*,export ${i[0]}=${i[1]},\" user_data.sh"
+ sh "sed -i 's,export ${i[0]}=.*,export ${i[0]}=${i[1]},' user_data.sh"
}
// create cfg config-drive
diff --git a/openstack-compute-upgrade.groovy b/openstack-compute-upgrade.groovy
index a59fc08..2984b55 100644
--- a/openstack-compute-upgrade.groovy
+++ b/openstack-compute-upgrade.groovy
@@ -7,6 +7,7 @@
* TARGET_SERVERS Salt compound target to match nodes to be updated [*, G@osfamily:debian].
* TARGET_SUBSET_TEST Number of nodes to list package updates, empty string means all targetted nodes.
* TARGET_SUBSET_LIVE Number of selected nodes to live apply selected package update.
+ * INTERACTIVE Ask interactive questions during pipeline run (bool).
*
**/
@@ -96,8 +97,10 @@
salt.runSaltProcessStep(pepperEnv, targetTestSubset, 'pkg.list_upgrades', [], null, true)
}
- stage('Confirm upgrade on sample nodes') {
+ if (INTERACTIVE.toBoolean()){
+ stage('Confirm upgrade on sample nodes') {
input message: "Please verify the list of packages that you want to be upgraded. Do you want to continue with upgrade?"
+ }
}
stage("Add new repos on sample nodes") {
@@ -136,8 +139,10 @@
}
}
- stage('Confirm upgrade on sample') {
+ if (INTERACTIVE.toBoolean()){
+ stage('Confirm upgrade on sample') {
input message: "Please verify if there are packages that it wants to downgrade. If so, execute apt-cache policy on them and verify if everything is fine. Do you want to continue with upgrade?"
+ }
}
command = "cmd.run"
@@ -180,10 +185,12 @@
}
}
- stage('Confirm upgrade on all targeted nodes') {
+ if (INTERACTIVE.toBoolean()){
+ stage('Confirm upgrade on all targeted nodes') {
timeout(time: 2, unit: 'HOURS') {
input message: "Verify that the upgraded sample nodes are working correctly. If so, do you want to approve live upgrade on ${targetLiveAll} nodes?"
}
+ }
}
stage("Add new repos on all targeted nodes") {
diff --git a/openstack-control-upgrade.groovy b/openstack-control-upgrade.groovy
index d306e34..89b5e77 100644
--- a/openstack-control-upgrade.groovy
+++ b/openstack-control-upgrade.groovy
@@ -9,6 +9,7 @@
* STAGE_ROLLBACK_UPGRADE Run rollback upgrade stage (bool)
* SKIP_VM_RELAUNCH Set to true if vms should not be recreated (bool)
* OPERATING_SYSTEM_RELEASE_UPGRADE Set to true if operating system of vms should be upgraded to newer release (bool)
+ * INTERACTIVE Ask interactive questions during pipeline run (bool).
*
**/
@@ -195,10 +196,10 @@
salt.cmdRun(pepperEnv, "${test_upgrade_node}*", '. /root/keystonercv3; openstack service list; openstack image list; openstack flavor list; openstack compute service list; openstack server list; openstack network list; openstack volume list; openstack orchestration service list')
- if (STAGE_TEST_UPGRADE.toBoolean() == true && STAGE_REAL_UPGRADE.toBoolean() == true) {
- stage('Ask for manual confirmation') {
- input message: "Do you want to continue with upgrade?"
- }
+ if (INTERACTIVE.toBoolean() && STAGE_TEST_UPGRADE.toBoolean() == true && STAGE_REAL_UPGRADE.toBoolean() == true) {
+ stage('Ask for manual confirmation') {
+ input message: "Do you want to continue with upgrade?"
+ }
}
}
@@ -303,8 +304,12 @@
stopServices(pepperEnv, proxy_node, proxy_general_target, 'prx')
stopServices(pepperEnv, control_node, control_general_target, 'ctl')
salt.printSaltCommandResult(out)
- if (out.toString().contains("dpkg returned an error code")) {
- input message: "Apt dist-upgrade failed, please fix it manually and then click on proceed. If unable to fix it, click on abort and run the rollback stage."
+ if (out.toString().contains("dpkg returned an error code")){
+ if (INTERACTIVE.toBoolean()) {
+ input message: "Apt dist-upgrade failed, please fix it manually and then click on proceed. If unable to fix it, click on abort and run the rollback stage."
+ } else {
+ error("Apt dist-upgrade failed. And interactive mode was disabled, failing...")
+ }
}
// run base states
try {
@@ -355,10 +360,14 @@
retryStateRun(pepperEnv, control_general_target, 'heat')
} catch (Exception e) {
errorOccured = true
- if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == false) {
- input message: "Some states that require syncdb failed. Please check the reason.Click proceed only if you want to restore database into it's pre-upgrade state. If you want restore production database and also the VMs into its pre-upgrade state please click on abort and run the rollback stage."
+ if (INTERACTIVE.toBoolean()){
+ if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == false) {
+ input message: "Some states that require syncdb failed. Please check the reason. Click proceed only if you want to restore database into it's pre-upgrade state. If you want restore production database and also the VMs into its pre-upgrade state please click on abort and run the rollback stage."
+ } else {
+ input message: "Some states that require syncdb failed. Please check the reason and click proceed only if you want to restore database into it's pre-upgrade state. Otherwise, click abort."
+ }
} else {
- input message: "Some states that require syncdb failed. Please check the reason and click proceed only if you want to restore database into it's pre-upgrade state. Otherwise, click abort."
+ error("Stage Real control upgrade failed. And interactive mode was disabled, failing...")
}
openstack.restoreGaleraDb(pepperEnv)
common.errorMsg("Stage Real control upgrade failed")
@@ -420,7 +429,9 @@
/*
if (OPERATING_SYSTEM_RELEASE_UPGRADE.toBoolean() == false) {
- input message: "Please verify if the control upgrade was successful! If so, by clicking proceed the original VMs disk images will be backed up and snapshot will be merged to the upgraded VMs which will finalize the upgrade procedure"
+ if (INTERACTIVE.toBoolean()){
+ input message: "Please verify if the control upgrade was successful! If so, by clicking proceed the original VMs disk images will be backed up and snapshot will be merged to the upgraded VMs which will finalize the upgrade procedure"
+ }
node_count = 1
for (t in proxy_target_hosts) {
def target = salt.stripDomainName(t)
@@ -445,8 +456,10 @@
virsh.liveSnapshotMerge(pepperEnv, nodeProvider, target, snapshotName)
node_count++
}
- input message: "Please scroll up and look for red highlighted messages containing 'virsh blockcommit' string.
- If there are any fix it manually. Otherwise click on proceed."
+ if (INTERACTIVE.toBoolean()){
+ input message: "Please scroll up and look for red highlighted messages containing 'virsh blockcommit' string.
+ If there are any fix it manually. Otherwise click on proceed."
+ }
}
*/
}
@@ -548,7 +561,7 @@
vcpRealUpgrade(pepperEnv)
}
- if (STAGE_REAL_UPGRADE.toBoolean() == true && STAGE_ROLLBACK_UPGRADE.toBoolean() == true) {
+ if (INTERACTIVE.toBoolean() && STAGE_REAL_UPGRADE.toBoolean() == true && STAGE_ROLLBACK_UPGRADE.toBoolean() == true) {
stage('Ask for manual confirmation') {
input message: "Please verify if the control upgrade was successful. If it did not succeed, in the worst scenario, you can click on proceed to continue with control-upgrade-rollback. Do you want to continue with the rollback?"
}
@@ -557,11 +570,13 @@
if (STAGE_ROLLBACK_UPGRADE.toBoolean() == true) {
stage('Rollback upgrade') {
- stage('Ask for manual confirmation') {
+ if (INTERACTIVE.toBoolean()){
+ stage('Ask for manual confirmation') {
input message: "Before rollback please check the documentation for reclass model changes. Do you really want to continue with the rollback?"
+ }
}
vcpRollback(pepperEnv)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/ovs-gateway-upgrade.groovy b/ovs-gateway-upgrade.groovy
index 8d131c8..87cf828 100644
--- a/ovs-gateway-upgrade.groovy
+++ b/ovs-gateway-upgrade.groovy
@@ -7,6 +7,7 @@
* TARGET_SERVERS Salt compound target to match nodes to be updated [*, G@osfamily:debian].
* TARGET_SUBSET_TEST Number of nodes to list package updates, empty string means all targetted nodes.
* TARGET_SUBSET_LIVE Number of selected nodes to live apply selected package update.
+ * INTERACTIVE Ask interactive questions during pipeline run (bool).
*
**/
@@ -63,8 +64,10 @@
salt.runSaltProcessStep(pepperEnv, targetTestSubset, 'pkg.list_upgrades', [], null, true)
}
- stage('Confirm upgrade on sample nodes') {
+ if (INTERACTIVE.toBoolean()){
+ stage('Confirm upgrade on sample nodes') {
input message: "Please verify the list of packages that you want to be upgraded. Do you want to continue with upgrade?"
+ }
}
stage("Add new repos on sample nodes") {
@@ -81,8 +84,10 @@
}
}
- stage('Confirm upgrade on sample') {
+ if (INTERACTIVE.toBoolean()){
+ stage('Confirm upgrade on sample') {
input message: "Please verify if there are packages that it wants to downgrade. If so, execute apt-cache policy on them and verify if everything is fine. Do you want to continue with upgrade?"
+ }
}
command = "cmd.run"
@@ -111,10 +116,12 @@
}
}
- stage('Confirm upgrade on all targeted nodes') {
+ if (INTERACTIVE.toBoolean()){
+ stage('Confirm upgrade on all targeted nodes') {
timeout(time: 2, unit: 'HOURS') {
- input message: "Verify that the upgraded sample nodes are working correctly. If so, do you want to approve live upgrade on ${targetLiveAll} nodes?"
+ input message: "Verify that the upgraded sample nodes are working correctly. If so, do you want to approve live upgrade on ${targetLiveAll} nodes?"
}
+ }
}
stage("Add new repos on all targeted nodes") {
diff --git a/tag-git-repos.groovy b/tag-git-repos.groovy
index 373e029..52344d1 100644
--- a/tag-git-repos.groovy
+++ b/tag-git-repos.groovy
@@ -15,25 +15,9 @@
def gitRepoAddTag(repoURL, repoName, tag, credentials, ref = "HEAD"){
git.checkoutGitRepository(repoName, repoURL, "master", credentials)
dir(repoName) {
- def checkTag = sh(script: "git tag -l ${tag}", returnStdout: true)
- if(checkTag == ""){
- sh "git tag -a ${tag} ${ref} -m \"Release of mcp version ${tag}\""
- }else{
- def currentTagRef = sh(script: "git rev-list -n 1 ${tag}", returnStdout: true)
- if(currentTagRef.equals(ref)){
- common.infoMsg("Tag is already on the right ref")
- return
- }
- else{
- sshagent([credentials]) {
- sh "git push --delete origin ${tag}"
- }
- sh "git tag --delete ${tag}"
- sh "git tag -a ${tag} ${ref} -m \"Release of mcp version ${tag}\""
- }
- }
+ sh "git tag -f -a ${tag} ${ref} -m \"Release of mcp version ${tag}\""
sshagent([credentials]) {
- sh "git push origin ${tag}"
+ sh "git push -f origin ${tag}:refs/tags/${tag}"
}
}
}
diff --git a/test-salt-formulas-pipeline.groovy b/test-salt-formulas-pipeline.groovy
index 3c75950..401628b 100644
--- a/test-salt-formulas-pipeline.groovy
+++ b/test-salt-formulas-pipeline.groovy
@@ -4,6 +4,8 @@
* DEFAULT_GIT_URL
* CREDENTIALS_ID
* KITCHEN_TESTS_PARALLEL
+ * RUN_TEST_IN_DOCKER If true, run test stage in docker
+ * SMOKE_TEST_DOCKER_IMG Docker image for run test (default "ubuntu:16.04")
*/
common = new com.mirantis.mk.Common()
def gerrit = new com.mirantis.mk.Gerrit()
@@ -108,7 +110,28 @@
saltVersion = "" // default value is empty string, means latest
}
withEnv(["SALT_VERSION=${saltVersion}"]) {
- sh("make clean && make test")
+ boolean run_test_in_docker = (env.RUN_TEST_IN_DOCKER ?: false).toBoolean()
+ if (run_test_in_docker) {
+ def dockerLib = new com.mirantis.mk.Docker()
+ def img = dockerLib.getImage(env.SMOKE_TEST_DOCKER_IMG, "ubuntu:16.04")
+ def workspace = common.getWorkspace()
+ img.inside("-u root:root -v ${workspace}/:/formula/") {
+ sh("""cd /etc/apt/ && echo > sources.list \
+ && echo "deb [arch=amd64] http://cz.archive.ubuntu.com/ubuntu xenial main restricted universe multiverse" >> sources.list \
+ && echo "deb [arch=amd64] http://cz.archive.ubuntu.com/ubuntu xenial-updates main restricted universe multiverse" >> sources.list \
+ && echo "deb [arch=amd64] http://cz.archive.ubuntu.com/ubuntu xenial-backports main restricted universe multiverse" >> sources.list \
+ && echo 'Acquire::Languages "none";' > apt.conf.d/docker-no-languages \
+ && echo 'Acquire::GzipIndexes "true"; Acquire::CompressionTypes::Order:: "gz";' > apt.conf.d/docker-gzip-indexes \
+ && echo 'APT::Get::Install-Recommends "false"; APT::Get::Install-Suggests "false";' > apt.conf.d/docker-recommends \
+ && apt-get update \
+ && apt-get install -y git-core wget curl apt-transport-https \
+ && apt-get install -y python-pip python3-pip python-virtualenv python3-virtualenv python-yaml autoconf build-essential""")
+ sh("cd /formula/ && make clean && make test")
+ }
+ } else {
+ common.warningMsg("Those tests should be always be run in clean env! Recommends to use docker env!")
+ sh("make clean && make test")
+ }
}
}
}
@@ -159,6 +182,8 @@
common.errorMsg("----------------KITCHEN LOG:---------------")
println readFile(".kitchen/logs/kitchen.log")
}
+ def slack = new com.mirantis.mcp.SlackNotification()
+ slack.jobResultNotification("success", "#test_reclass_notify")
common.sendNotification(currentBuild.result, "", ["slack"])
}
}
diff --git a/test-system-reclass-pipeline.groovy b/test-system-reclass-pipeline.groovy
index 7fc1181..fa16739 100644
--- a/test-system-reclass-pipeline.groovy
+++ b/test-system-reclass-pipeline.groovy
@@ -26,6 +26,7 @@
def checkouted = false
def merged = false
def systemRefspec = "HEAD"
+def formulasRevision = 'testing'
timeout(time: 12, unit: 'HOURS') {
node() {
try {
@@ -71,14 +72,17 @@
[$class: 'StringParameterValue', name: 'DEFAULT_GIT_URL', value: clusterGitUrl],
[$class: 'StringParameterValue', name: 'DEFAULT_GIT_REF', value: "HEAD"],
[$class: 'StringParameterValue', name: 'SYSTEM_GIT_URL', value: defaultGitUrl],
- [$class: 'StringParameterValue', name: 'SYSTEM_GIT_REF', value: systemRefspec]
+ [$class: 'StringParameterValue', name: 'SYSTEM_GIT_REF', value: systemRefspec],
+ [$class: 'StringParameterValue', name: 'FORMULAS_REVISION', value: formulasRevision],
]
}
}
branches["cookiecutter"] = {
build job: "test-mk-cookiecutter-templates", parameters: [
[$class: 'StringParameterValue', name: 'SYSTEM_GIT_URL', value: defaultGitUrl],
- [$class: 'StringParameterValue', name: 'SYSTEM_GIT_REF', value: systemRefspec]
+ [$class: 'StringParameterValue', name: 'SYSTEM_GIT_REF', value: systemRefspec],
+ [$class: 'StringParameterValue', name: 'DISTRIB_REVISION', value: formulasRevision]
+
]
}
parallel branches
diff --git a/upgrade-mcp-release.groovy b/upgrade-mcp-release.groovy
index fb8b0e6..0c5c971 100644
--- a/upgrade-mcp-release.groovy
+++ b/upgrade-mcp-release.groovy
@@ -6,25 +6,58 @@
* SALT_MASTER_URL Salt API server location
* SALT_MASTER_CREDENTIALS Credentials to the Salt API
* MCP_VERSION Version of MCP to upgrade to
+ * UPDATE_CLUSTER_MODEL Update MCP version parameter in cluster model
+ * UPDATE_PIPELINES Update pipeline repositories on Gerrit
* UPDATE_LOCAL_REPOS Update local repositories
*/
+import hudson.model.*
+
// Load shared libs
salt = new com.mirantis.mk.Salt()
common = new com.mirantis.mk.Common()
python = new com.mirantis.mk.Python()
+jenkinsUtils = new com.mirantis.mk.JenkinsUtils()
venvPepper = "venvPepper"
+def triggerMirrorJob(jobName){
+ params = jenkinsUtils.getJobParameters(jobName)
+ build job: jobName, parameters: [
+ [$class: 'StringParameterValue', name: 'BRANCHES', value: params.get("BRANCHES")],
+ [$class: 'StringParameterValue', name: 'CREDENTIALS_ID', value: params.get("CREDENTIALS_ID")],
+ [$class: 'StringParameterValue', name: 'SOURCE_URL', value: params.get("SOURCE_URL")],
+ [$class: 'StringParameterValue', name: 'TARGET_URL', value: params.get("TARGET_URL")]
+ ]
+}
+
timeout(time: 12, unit: 'HOURS') {
node("python") {
try {
python.setupPepperVirtualenv(venvPepper, SALT_MASTER_URL, SALT_MASTER_CREDENTIALS)
+ if(MCP_VERSION == ""){
+ error("You must specify MCP version")
+ }
+
stage("Update Reclass"){
- common.infoMsg("Updating reclass model")
- salt.cmdRun(venvPepper, "I@salt:master", 'cd /srv/salt/reclass && git pull -r && git submodule update', false)
- salt.cmdRun(venvPepper, 'I@salt:master', 'reclass-salt --top')
- salt.enforceState(venvPepper, "I@salt:master", 'reclass', true)
+ def cluster_name = salt.getPillar(venvPepper, 'I@salt:master', "_param:cluster_name").get("return")[0].values()[0]
+ if(UPDATE_CLUSTER_MODEL.toBoolean()){
+ try{
+ salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/ && git diff-index --quiet HEAD --")
+ }
+ catch(Exception ex){
+ error("You have uncommited changes in your Reclass cluster model repository. Please commit or reset them and rerun the pipeline.")
+ }
+ salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name && grep -r --exclude-dir=aptly -l 'apt_mk_version: .*' * | xargs sed -i 's/apt_mk_version: .*/apt_mk_version: \"$MCP_VERSION\"/g'")
+ }
+
+ try{
+ salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/system && git diff-index --quiet HEAD --")
+ }
+ catch(Exception ex){
+ error("You have unstaged changes in your Reclass system model repository. Please reset them and rerun the pipeline.")
+ }
+ salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/system && git checkout $MCP_VERSION")
}
if(UPDATE_LOCAL_REPOS.toBoolean()){
@@ -41,6 +74,8 @@
common.infoMsg("Aptly isn't running as Docker container. Going to use aptly user for executing aptly commands")
}
+ salt.cmdRun(venvPepper, 'I@salt:master', "cd /srv/salt/reclass/classes/cluster/$cluster_name/cicd/aptly && git checkout $MCP_VERSION")
+
if(runningOnDocker){
salt.cmdRun(venvPepper, 'I@aptly:server', "aptly mirror list --raw | grep -E '*' | xargs -n 1 aptly mirror drop -force", true, null, true)
}
@@ -69,17 +104,49 @@
}
}
- stage("Update APT repos"){
- common.infoMsg("Updating APT repositories")
- salt.enforceState(venvPepper, "I@linux:system", 'linux.system.repo', true)
- }
+ stage("Update Drivetrain"){
+ salt.cmdRun(venvPepper, 'I@salt:master', "sed -i -e 's/[^ ]*[^ ]/$MCP_VERSION/4' /etc/apt/sources.list.d/mcp_salt.list")
+ salt.cmdRun(venvPepper, 'I@salt:master', "apt-get -o Dir::Etc::sourcelist='/etc/apt/sources.list.d/mcp_salt.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update")
+ salt.cmdRun(venvPepper, 'I@salt:master', "apt-get install -y --allow-downgrades salt-formula-*")
+ salt.fullRefresh(venvPepper, 'I@salt:master')
- stage("Update formulas"){
- common.infoMsg("Updating salt formulas")
- salt.cmdRun(venvPepper, "I@salt:master", 'apt-get clean && apt-get update && apt-get install -y salt-formula-*')
+ try{
+ salt.enforceState(venvPepper, "I@salt:master", 'reclass', true)
+ }
+ catch(Exception ex){
+ error("Reclass fails rendering. Pay attention to your cluster model.")
+ }
- common.infoMsg("Running salt sync-all")
- salt.runSaltProcessStep(venvPepper, '*', 'saltutil.sync_all', [], null, true)
+ salt.fullRefresh(venvPepper, '*')
+
+ try{
+ salt.cmdRun(venvPepper, 'I@salt:master', "reclass-salt --top")
+ }
+ catch(Exception ex){
+ error("Reclass fails rendering. Pay attention to your cluster model.")
+ }
+
+ if(UPDATE_PIPELINES.toBoolean()){
+ triggerMirrorJob("git-mirror-downstream-mk-pipelines")
+ triggerMirrorJob("git-mirror-downstream-pipeline-library")
+ }
+
+ salt.enforceState(venvPepper, "I@jenkins:client", 'jenkins.client', true)
+
+ salt.cmdRun(venvPepper, "I@salt:master", "salt -C 'I@jenkins:client and I@docker:client' state.sls docker.client --async")
+
+ sleep(180)
+
+ common.infoMsg("Checking if Docker containers are up")
+
+ try{
+ common.retry(10, 30){
+ salt.cmdRun(venvPepper, 'I@jenkins:client and I@docker:client', "! docker service ls | tail -n +2 | grep -v -E '\\s([0-9])/\\1\\s'")
+ }
+ }
+ catch(Exception ex){
+ error("Docker containers for CI/CD services are having troubles with starting.")
+ }
}
}
catch (Throwable e) {
diff --git a/validate-cloud.groovy b/validate-cloud.groovy
index 5dd8008..7d3b2e2 100644
--- a/validate-cloud.groovy
+++ b/validate-cloud.groovy
@@ -15,7 +15,8 @@
* TEMPEST_VERSION Version of Tempest (tag, branch or commit)
* RUN_TEMPEST_TESTS If not false, run Tempest tests
* RUN_RALLY_TESTS If not false, run Rally tests
- * RUN_K8S_TESTS If not false, run Kubernetes tests
+ * K8S_RALLY If not false, run Kubernetes Rally tests
+ * RUN_K8S_TESTS If not false, run Kubernetes e2e/conformance tests
* RUN_SPT_TESTS If not false, run SPT tests
* SPT_SSH_USER The name of the user which should be used for ssh to nodes
* SPT_IMAGE The name of the image for SPT tests
@@ -25,6 +26,8 @@
* FLOATING_NETWORK The name of the external(floating) network
* RALLY_IMAGE The name of the image for Rally tests
* RALLY_FLAVOR The name of the flavor for Rally image
+ * RALLY_PLUGINS_REPO Git repository with Rally plugins
+ * RALLY_PLUGINS_BRANCH Git branch which will be used during the checkout
* RALLY_CONFIG_REPO Git repository with files for Rally
* RALLY_CONFIG_BRANCH Git branch which will be used during the checkout
* RALLY_SCENARIOS Path to file or directory with rally scenarios
@@ -35,6 +38,7 @@
* TEST_K8S_NODE Kubernetes node to run tests from
* GENERATE_REPORT If not false, run report generation command
* ACCUMULATE_RESULTS If true, results from the previous build will be used
+ * JOB_TIMEOUT Job timeout in hours
*
*/
@@ -45,7 +49,12 @@
def pepperEnv = "pepperEnv"
def artifacts_dir = 'validation_artifacts/'
-timeout(time: 12, unit: 'HOURS') {
+if (env.JOB_TIMEOUT == ''){
+ job_timeout = 12
+} else {
+ job_timeout = env.JOB_TIMEOUT.toInteger()
+}
+timeout(time: job_timeout, unit: 'HOURS') {
node() {
try{
stage('Setup virtualenv for Pepper') {
@@ -70,18 +79,21 @@
stage('Run Rally tests') {
if (RUN_RALLY_TESTS.toBoolean() == true) {
- def report_dir = '/root/qa_results'
- try {
- if(REPORT_DIR != ""){
- report_dir = REPORT_DIR
- }
- } catch (MissingPropertyException e) {
+ def report_dir = env.REPORT_DIR ?: '/root/qa_results'
+ def platform
+ def rally_variables
+ if (K8S_RALLY.toBoolean() == false) {
+ platform = 'openstack'
+ rally_variables = ["floating_network=${FLOATING_NETWORK}",
+ "rally_image=${RALLY_IMAGE}",
+ "rally_flavor=${RALLY_FLAVOR}",
+ "availability_zone=${AVAILABILITY_ZONE}"]
+ } else {
+ platform = 'k8s'
+ rally_variables = ["plugins_repo":"${RALLY_PLUGINS_REPO}",
+ "plugins_branch":"${RALLY_PLUGINS_BRANCH}"]
}
- def rally_variables = ["floating_network=${FLOATING_NETWORK}",
- "rally_image=${RALLY_IMAGE}",
- "rally_flavor=${RALLY_FLAVOR}",
- "availability_zone=${AVAILABILITY_ZONE}"]
- validate.runRallyTests(pepperEnv, TARGET_NODE, TEST_IMAGE, artifacts_dir, RALLY_CONFIG_REPO, RALLY_CONFIG_BRANCH, RALLY_SCENARIOS, RALLY_TASK_ARGS_FILE, rally_variables, report_dir)
+ validate.runRallyTests(pepperEnv, TARGET_NODE, TEST_IMAGE, platform, artifacts_dir, RALLY_CONFIG_REPO, RALLY_CONFIG_BRANCH, RALLY_SCENARIOS, RALLY_TASK_ARGS_FILE, rally_variables, report_dir)
} else {
common.infoMsg("Skipping Rally tests")
}
@@ -101,7 +113,7 @@
}
}
- stage('Run k8s bootstrap tests') {
+ stage('Run K8S bootstrap tests') {
if (RUN_K8S_TESTS.toBoolean() == true) {
def image = 'tomkukral/k8s-scripts'
def output_file = 'k8s-bootstrap-tests.txt'
@@ -115,7 +127,7 @@
}
}
- stage('Run k8s conformance e2e tests') {
+ stage('Run K8S conformance e2e tests') {
if (RUN_K8S_TESTS.toBoolean() == true) {
def image = TEST_K8S_CONFORMANCE_IMAGE
def output_file = 'report-k8s-e2e-tests.txt'
diff --git a/xtrabackup-restore-mysql-db.groovy b/xtrabackup-restore-mysql-db.groovy
index 60b8caf..da3d463 100644
--- a/xtrabackup-restore-mysql-db.groovy
+++ b/xtrabackup-restore-mysql-db.groovy
@@ -81,6 +81,12 @@
}
sleep(5)
salt.cmdRun(pepperEnv, 'I@galera:master', "su root -c 'salt-call mysql.status | grep -A1 wsrep_cluster_size'")
+
+ try {
+ salt.runSaltProcessStep(pepperEnv, 'I@galera:master or I@galera:slave', 'file.touch', ["/var/lib/mysql/.galera_bootstrap"], null, true)
+ } catch (Exception er) {
+ common.warningMsg('File is already present')
+ }
}
}
}