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."
}}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,376评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,126评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,966评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,432评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,519评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,792评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,933评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,701评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,143评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,488评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,626评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,292评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,896评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,494评论 2 348

推荐阅读更多精彩内容