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."
}}
网友评论