jenkins-pipeline实践 - tempest

properties([
    buildDiscarder(logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '60', numToKeepStr: '')),
    parameters([
        string(defaultValue: '', description: 'auth url', name: 'auth_url'),
        password(defaultValue: '', description: 'admin password', name: 'password'),
        string(defaultValue: 'identity image volume network compute', description: 'services', name: 'services'),
        string(defaultValue: '', description: 'testcase label.eg: smoke', name: 'label'),
    ]),
])
 
 
node('tempest') { timestamps{
    println(params)
    auth_url = params.get('auth_url')
    project_domain_name = 'Default'
    user_domain_name = 'Default'
    project_name = 'admin'
    username = 'admin'
    password = params.get('password')
 
    services = params.get('services').split()
    label = params.get('label')
 
    emailto = [
    ].join(',')
    date_s = sh(returnStdout: true, script: "date +%s").trim()
   
    tempest_version = '10'
    venv = "tempest-${tempest_version}"
    host = "${auth_url.split('://')[1].split('/')[0].split(':')[0]}"
    workspace = "${venv}-${host}"
   
    resultmap = [:]
   
    try {
        stage('prepare') {
            sh """
                yum install epel-release -y
                yum install python-pip -y
                yum install python-devel -y
                yum install gcc -y
                yum install jq -y
                pip install tox
            """
            dir(env.WORKSPACE) {
                withEnv(["venv=${venv}", "tempest_version=${tempest_version}"]) { sh '''
                    virtualenv --no-site-packages ${venv}
                    source ${venv}/bin/activate
   
                    pip install tempest==${tempest_version}  # Todo: 1 install from git; 2 plugins
                    pip install python-openstackclient
                    pip install junitxml
   
                    python_lib_dir=`python -c \'from distutils.sysconfig import get_python_lib; print(get_python_lib())\'`
                    cp -fu $python_lib_dir/tempest/lib/common/rest_client.py{,.bak}
                    cp -fu $python_lib_dir/tempest/cmd/cleanup_service.py{,.bak}
                    sed -i \'/def validate_response(.*):$/ a\\        return\' $python_lib_dir/tempest/lib/common/rest_client.py
                    sed  -i \'/def _get_network_id/,/return/s/if (net\\[\'\\\'\'\\([a-z_]*\\)\'\\\'\'\\] == \\([a-z_]*\\) and net\\[\'\\\'\'name\'\\\'\'\\] == net_name):/if (net.get(\'\\\'\'\\1\'\\\'\') == \\2 and net\\[\'\\\'\'name\'\\\'\'\\] == net_name):/\' $python_lib_dir/tempest/cmd/cleanup_service.py
                '''}
            }
        }
   
        withEnv(["PATH=${env.WORKSPACE}/${venv}/bin:${env.PATH}"]) {
            stage('init') { dir(env.WORKSPACE) {
                sh """
                rm -rf ${workspace}/{*,.[!.]*}
                mkdir -p ${workspace} && cd ${workspace} && tempest init
                mkdir -p output/${date_s}
                """
            }}
   
            stage('config') {
                def osc = "openstack --os-auth-url ${auth_url} --os-identity-api-version 3 --os-project-domain-name ${project_domain_name} --os-user-domain-name ${user_domain_name} --os-project-name ${project_name} --os-username ${username} --os-password ${password}"
 
                def public_network_name = 'provider'
                def public_network_id = sh(returnStdout: true, script: "${osc} network list -f json | jq '.[] | select(.Name==\"${public_network_name}\") | .ID' | head -n 1 | tr -d '\"'").trim()
 
                def fixed_network_name = 'tempest_tenant_net'
                def fixed_network_id = sh(returnStdout: true, script: "${osc} network list -f json | jq '.[] | select(.Name==\"${fixed_network_name}\") | .ID' | head -n 1 | tr -d '\"'").trim()
                if(! fixed_network_id) {
                    sh "${osc} network create --share --enable ${fixed_network_name}"
                    fixed_network_id = sh(returnStdout: true, script:"${osc} subnet create --network ${fixed_network_name} --dns-nameserver 8.8.4.4 --gateway 172.16.1.1 --subnet-range 172.16.1.0/24 ${fixed_network_name}_subnet -f value -c id").trim()
                }
 
                def public_router_name = 'tempest_router'
                def public_router_id = sh(returnStdout: true, script: "${osc} router list -f json | jq '.[] | select(.Name==\"${public_router_name}\") | .ID' | head -n 1 | tr -d '\"'").trim()
                if(! public_router_id) {
                    public_router_id = sh(returnStdout: true, script: "${osc} router create ${public_router_name} -f value -c id").trim()
                    sh "${osc} router set --external-gateway provider ${public_router_name}"
                }

                def image_id = sh(returnStdout: true, script: "${osc} image list -f json | jq '.[] | select(.Name==\"cirros\") | .ID' | head -n 1 | tr -d '\"'").trim()
                if(! image_id) {
                    image_id = sh(returnStdout: true, script: "${osc} image create cirros --file /opt/tempest/cirros-*.img --disk-format qcow2 --container-format bare --public -f value -c id").trim()
                }
   
                sh """
                cat <<EOF | tee ${workspace}/etc/tempest.conf
[DEFAULT]
debug = true
log_dir = logs
log_file = tempest.log
use_stderr = false
use_syslog = false
   
[oslo_concurrency]
lock_path = tempest_lock
   
[auth]
use_dynamic_credentials = true
default_credentials_domain_name = ${project_domain_name}
tempest_roles = user
admin_domain_scope = true
admin_domain_name = ${user_domain_name}
admin_project_name = ${project_name}
admin_tenant_name = ${project_name}
admin_username = ${username}
admin_password = ${password}
   
[identity]
auth_version = v3
uri_v3 = ${auth_url.split('/v')[0]}/v3
uri = ${auth_url.split('/v')[0]}/v2.0
   
[identity-feature-enabled]
api_v2 = true
security_compliance = true
   
[network]
public_network_id = ${public_network_id}
floating_network_name = ${public_network_name}
public_router_id = ${public_router_id}
  
[network-feature-enabled]
ipv6 = false
ipv6_subnet_attributes = false
api_extensions = all
port_security = true
floating_ips = true
   
[compute]
min_microversion = 2.1
max_microversion = 2.25
flavor_ref = 2
flavor_ref_alt = 3
image_ref = ${image_id}
image_ref_alt = ${image_id}
fixed_network_name = ${fixed_network_name}
   
[compute-feature-enabled]
min_microversion = 2.1
max_microversion = 2.25
nova_cert = false
personality = false
resize = false
swap_volume = true
vnc_console = true
   
[volume]
max_microversion = latest
   
[volume-feature-enabled]
api_v3 = false
backup = false
multi_backend = false
manage_volume = true
manage_snapshot = true
extend_attached_volume = false
  
[image-feature-enabled]
api_v1 = false
deactivate_image = true
   
[service_available]
cinder = true
neutron = true
glance = true
swift = false
nova = true
heat = true
ceilometer = false
aodh = false
horizon = false
sahara = false
ironic = false
trove = true
   
[validation]
run_validation = false
security_group = true
security_group_rules = true
connect_method = floating
image_ssh_user = cirros
image_ssh_password = gocubsgo
network_for_ssh = public
   
[scenario]
img_dir = /opt/tempest/
img_file = cirros-0.4.0-x86_64-disk.img
  
EOF"""
            }
   
            try {stage('run') {
                dir("${workspace}") {
                    // sh "tempest verify-config"
                    if(sh(returnStatus: true, script: "tempest cleanup --init-saved-state")){echo 'init-saved-state fail'}
                    sh """
                    stestr init
                    python_lib_dir=` python -c \'from distutils.sysconfig import get_python_lib; print(get_python_lib())\'`
                    cat <<EOF | tee .stestr.conf
[DEFAULT]
test_path=\${python_lib_dir}/tempest/test_discover
top_dir=\${python_lib_dir}/tempest
EOF
 
                    cat <<EOF | tee blacklist
tempest\\.api\\.compute\\.images\\.test_images_oneserver\\.ImagesOneServerTestJSON\\.test_create_image_specify_multibyte_character_image_name.*
tempest\\.api\\.compute\\.images\\.test_images_oneserver_negative\\.ImagesOneServerNegativeTestJSON\\.test_create_second_image_when_first_image_is_being_saved.*
tempest\\.api\\.compute\\.servers\\.test_delete_server\\.DeleteServersTestJSON\\.test_delete_server_while_in_shelved_state.*
tempest\\.api\\.compute\\.servers\\.test_delete_server\\.DeleteServersTestJSON.*
tempest\\.api\\.compute\\.servers\\.test_servers_negative\\.ServersNegativeTestJSON\\.test_delete_server_pass_id_exceeding_length_limit.*
tempest\\.api\\.compute\\.servers\\.test_server_actions\\.ServerActionsTestJSON\\.test_create_backup.*
tempest\\.api\\.compute\\.servers\\.test_server_actions\\.ServerActionsTestJSON\\.test_get_console_output_server_id_in_shutoff_status.*
tempest\\.api\\.compute\\.servers\\.test_server_actions\\.ServerActionsTestJSON\\.test_shelve_unshelve_server.*
tempest\\.api\\.compute\\.servers\\.test_server_rescue\\.ServerRescueTestJSON.*
tempest\\.api\\.compute\\.servers\\.test_servers_negative\\.ServersNegativeTestJSON\\.test_delete_server_pass_negative_id.*
tempest\\.api\\.compute\\.images\\.test_images_oneserver\\.ImagesOneServerTestJSON\\.test_create_delete_image.*
tempest\\.api\\.compute\\.images\\.test_images_oneserver_negative\\.ImagesOneServerNegativeTestJSON\\.test_delete_image_that_is_not_yet_active.*
tempest\\.api\\.compute\\.admin\\.test_aggregates_negative\\.AggregatesAdminNegativeTestJSON\\.test_aggregate_list_as_user.*
tempest\\.api\\.compute\\.admin\\.test_hypervisor_negative\\.HypervisorAdminNegativeTestJSON\\.test_get_hypervisor_list_details_with_non_admin_user.*
tempest\\.api\\.compute\\.admin\\.test_hypervisor_negative\\.HypervisorAdminNegativeTestJSON\\.test_get_hypervisor_uptime_with_non_admin_user.*
tempest\\.api\\.compute\\.admin\\.test_hypervisor_negative\\.HypervisorAdminNegativeTestJSON\\.test_search_hypervisor_with_non_admin_user.*
tempest\\.api\\.compute\\.admin\\.test_hypervisor_negative\\.HypervisorAdminNegativeTestJSON\\.test_show_hypervisor_with_non_admin_user.*
tempest\\.api\\.compute\\.admin\\.test_hypervisor_negative\\.HypervisorAdminNegativeTestJSON\\.test_get_hypervisor_list_with_non_admin_user.*
tempest\\.api\\.compute\\.admin\\.test_hypervisor_negative\\.HypervisorAdminNegativeTestJSON\\.test_get_hypervisor_stats_with_non_admin_user.*
tempest\\.api\\.compute\\.admin\\.test_hypervisor_negative\\.HypervisorAdminNegativeTestJSON\\.test_show_servers_with_non_admin_user.*
tempest\\.api\\.compute\\.images\\.test_images\\.ImagesTestJSON\\.test_delete_saving_image.*
tempest\\.api\\.compute\\.floating_ips\\.test_floating_ips_actions\\.FloatingIPsTestJSON.*
tempest\\.api\\.compute\\.floating_ips\\.test_list_floating_ips\\.FloatingIPDetailsTestJSON.*
tempest\\.api\\.compute\\.images\\.test_list_image_filters\\.ListImageFiltersTestJSON.*
tempest\\.api\\.compute\\.flavors\\.test_flavors\\.FlavorsV2TestJSON\\.test_list_flavors.*
tempest\\.api\\.network\\.admin\\.test_floating_ips_admin_actions\\.FloatingIPAdminTestJSON\\.test_create_list_show_floating_ip_with_tenant_id_by_admin.*
tempest\\.api\\.network\\.admin\\.test_floating_ips_admin_actions\\.FloatingIPAdminTestJSON.*
tempest\\.api\\.network\\.test_floating_ips\\.FloatingIPTestJSON\\.test_create_update_floatingip_with_port_multiple_ip_address.*
tempest\\.api\\.network\\.test_floating_ips\\.FloatingIPTestJSON.*
tempest\\.api\\.network\\.test_floating_ips_negative\\.FloatingIPNegativeTestJSON\\.test_associate_floatingip_port_ext_net_unreachable.*
tempest\\.api\\.network\\.test_routers\\.DvrRoutersTest\\.test_convert_centralized_router.*
tempest\\.api\\.network\\.test_routers_negative\\.DvrRoutersNegativeTest\\.test_router_create_tenant_distributed_returns_forbidden.*
tempest\\.api\\.network\\.admin\\.test_routers_dvr\\.RoutersTestDVR\\.test_centralized_router_update_to_dvr.*
tempest\\.api\\.network\\.test_floating_ips\\.FloatingIPTestJSON\\.test_floating_ip_update_different_router.*
tempest\\.api\\.network\\.test_floating_ips_negative\\.FloatingIPNegativeTestJSON\\.test_create_floatingip_with_port_ext_net_unreachable.*
tempest\\.api\\.volume\\.admin\\.test_volume_types\\.VolumeTypesV1Test\\.test_volume_crud_with_volume_type_and_extra_specs.*
tempest\\.api\\.volume\\.admin\\.test_volume_types\\.VolumeTypesV2Test\\.test_volume_crud_with_volume_type_and_extra_specs.*
EOF
                    """
                    def exitcode=sh(returnStatus: true, script: "stestr run --log-file ./output/${date_s}/result.log --subunit 'api\\.(${services.join("|")}).*\\[.*${label}.*\\]' --blacklist-file blacklist --concurrency 4 | tee ./output/${date_s}/subunit.out | subunit-trace")
                    _ = sh(returnStatus: true, script: "subunit2junitxml ./output/${date_s}/subunit.out -o ./output/${date_s}/result.xml")
                    _ = sh(returnStatus: true, script: "subunit2html ./output/${date_s}/subunit.out ./output/${date_s}/result.html")
                    _ = sh(returnStatus: true, script: "subunit-filter --error --failure --no-skip ./output/${date_s}/subunit.out | subunit-ls")
                    if(exitcode) {error 'FAIL'}
                }
            }} catch(Exception ex) {resultmap['run'] = false; echo ex.toString()}
        }
    } catch(Exception ex) {
        echo ex.toString()
        resultmap['ALL'] = false
    } finally {
        stage('report') {
            sh "cp -Rfu ${workspace}/{logs,output/${date_s}} ${WORKSPACE}"
            archiveArtifacts allowEmptyArchive: true, artifacts: "${date_s}/*, logs/*"
            junit allowEmptyResults: true, healthScaleFactor: 10.0, testDataPublishers: [[$class: 'AttachmentPublisher']], testResults: "${date_s}/*.xml"
   
            if(resultmap.any {entry -> entry.value == false}) {
                currentBuild.result = 'FAILURE'
                echo currentBuild.result
            }

            if(fileExists("${date_s}/result.html")){
                emailbody = "\${FILE, path=\"${date_s}/result.html\"}"
            }else{
                emailbody = '${SCRIPT, template="groovy-html.template"}'
            }

            emailext to: emailto, replyTo: '$DEFAULT_REPLYTO', subject: "\$DEFAULT_SUBJECT - ${host}-${label?:'full'}", body: emailbody, mimeType: 'text/html', attachmentsPattern: "${date_s}/*.html", attachLog: false
        }
   
        withEnv(["PATH=${env.WORKSPACE}/${venv}/bin:${env.PATH}"]) { stage('cleanup') {
            dir("${workspace}") {
                if(sh(returnStatus: true, script: "tempest cleanup")){echo 'cleanup fail'}
            }
            // cleanWs()
        }}
    }
    echo "END job."
}}
    原文作者:writeme
    原文地址: https://www.jianshu.com/p/c7a7963c099d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞