diff options
Diffstat (limited to 'functest')
66 files changed, 2445 insertions, 1359 deletions
diff --git a/functest/ci/add_proxy.sh b/functest/ci/add_proxy.sh index 082141073..9d7db22e4 100644 --- a/functest/ci/add_proxy.sh +++ b/functest/ci/add_proxy.sh @@ -1,8 +1,9 @@ -#!/bin/bash +#!/bin/sh set -e -pushd "${1:-/home/opnfv/functest/images}" > /dev/null +initdir=$(pwd) +cd "${1:-/home/opnfv/functest/images}" http_proxy_host=${http_proxy_host:-proxy} http_proxy_port=${http_proxy_port:-8080} @@ -89,7 +90,7 @@ for image in $images; do fi guestmount -a "${image}" -i --rw "${tmpdir}" add_proxy "${tmpdir}/etc/environment" - if [[ ${image} == "ubuntu"* ]]; then + if expr "$image" : 'ubuntu' ; then add_proxy_apt "${tmpdir}/etc/apt/apt.conf" add_proxy_juju_env "${tmpdir}/etc/juju-proxy.conf" add_proxy_juju_systemd "${tmpdir}/etc/juju-proxy-systemd.conf" @@ -133,5 +134,5 @@ else fi rmdir "${tmpdir}" -popd > /dev/null +cd initdir diff --git a/functest/ci/config_aarch64_patch.yaml b/functest/ci/config_aarch64_patch.yaml index c2164cd68..278265620 100644 --- a/functest/ci/config_aarch64_patch.yaml +++ b/functest/ci/config_aarch64_patch.yaml @@ -1,89 +1,99 @@ --- os: vmready1: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img vmready2: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img singlevm1: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img singlevm2: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img vping_ssh: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img vping_userdata: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img cinder_test: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img tempest_smoke: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - - neutron-tempest-plugin-api: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_horizon: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_neutron: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_cinder: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_keystone: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_heat: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: + /home/opnfv/functest/images/Fedora-Cloud-Base-30-1.2.aarch64.qcow2 + tempest_telemetry: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + rally_sanity: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img refstack_compute: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img refstack_object: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img refstack_platform: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - - patrole: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - - vmtp: - image: - /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-arm64-uefi1.img - - shaker: - image: /home/opnfv/functest/images/shaker-image-arm64.qcow2 - - neutron_trunk: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - - networking-bgpvpn: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - - networking-sfc: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - - barbican: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img tempest_full: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img tempest_scenario: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - image_alt: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - - rally_sanity: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_slow: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + patrole: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_barbican: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_octavia: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_neutron_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_cinder_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_keystone_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_heat_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: + /home/opnfv/functest/images/Fedora-Cloud-Base-30-1.2.aarch64.qcow2 + rally_sanity_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_full_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_scenario_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + tempest_slow_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + image_alt: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img rally_full: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img rally_jobs: - image: /home/opnfv/functest/images/cirros-0.4.0-aarch64-disk.img - - tempest: - use_custom_flavors: 'True' + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + rally_full_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img + rally_jobs_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-aarch64-disk.img diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml index d7a162f73..647301ab4 100644 --- a/functest/ci/config_functest.yaml +++ b/functest/ci/config_functest.yaml @@ -18,10 +18,10 @@ general: rally_inst: /root/.rally openstack: - image_name: Cirros-0.4.0 - image_name_alt: Cirros-0.4.0-1 - image_file_name: cirros-0.4.0-x86_64-disk.img - image_url: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img + image_name: Cirros-0.5.1 + image_name_alt: Cirros-0.5.1-1 + image_file_name: cirros-0.5.1-x86_64-disk.img + image_url: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.img image_user: cirros image_disk_format: qcow2 image_username: cirros diff --git a/functest/ci/config_patch.yaml b/functest/ci/config_patch.yaml index 05eb44276..d5335c3ab 100644 --- a/functest/ci/config_patch.yaml +++ b/functest/ci/config_patch.yaml @@ -4,7 +4,31 @@ gsma: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 - neutron-tempest-plugin-api: + tempest_horizon: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_neutron: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_cinder: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_keystone: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_heat: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_telemetry: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + rally_sanity: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 @@ -20,43 +44,59 @@ gsma: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 + tempest_full: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_scenario: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_slow: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 patrole: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 - vmtp: - flavor_ram: 2048 - flavor_vcpus: 1 - flavor_disk: 40 - shaker: - flavor_ram: 2048 - flavor_vcpus: 1 - flavor_disk: 40 - neutron_trunk: + tempest_barbican: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 - networking-bgpvpn: + tempest_octavia: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 - networking-sfc: + tempest_neutron_cntt: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 - barbican: + tempest_cinder_cntt: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 - tempest_full: + tempest_keystone_cntt: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 - tempest_scenario: + tempest_heat_cntt: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 - rally_sanity: + rally_sanity_cntt: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_full_cntt: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_scenario_cntt: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + tempest_slow_cntt: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 @@ -68,6 +108,22 @@ gsma: flavor_alt_ram: 2048 flavor_alt_vcpus: 1 flavor_alt_disk: 40 + vmtp: + flavor_ram: 2048 + flavor_vcpus: 1 + flavor_disk: 40 + shaker: + flavor_ram: 2048 + flavor_vcpus: 1 + flavor_disk: 40 + rally_full_cntt: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 + rally_jobs_cntt: + flavor_alt_ram: 2048 + flavor_alt_vcpus: 1 + flavor_alt_disk: 40 cloudify: flavor_ram: 4096 flavor_vcpus: 2 @@ -115,7 +171,19 @@ fdio: flavor_ram: 1024 tempest_smoke: flavor_ram: 1024 - neutron-tempest-plugin-api: + tempest_horizon: + flavor_ram: 1024 + tempest_neutron: + flavor_ram: 1024 + tempest_cinder: + flavor_ram: 1024 + tempest_keystone: + flavor_ram: 1024 + tempest_heat: + flavor_ram: 1024 + tempest_telemetry: + flavor_ram: 1024 + rally_sanity: flavor_ram: 1024 refstack_compute: flavor_ram: 1024 @@ -123,30 +191,46 @@ fdio: flavor_ram: 1024 refstack_platform: flavor_ram: 1024 + tempest_full: + flavor_ram: 1024 + tempest_scenario: + flavor_ram: 1024 + tempest_slow: + flavor_ram: 1024 patrole: flavor_ram: 1024 - vmtp: - flavor_ram: 2048 - shaker: + tempest_barbican: flavor_ram: 1024 - neutron_trunk: + tempest_octavia: flavor_ram: 1024 - networking-bgpvpn: + tempest_neutron_cntt: flavor_ram: 1024 - networking-sfc: + tempest_cinder_cntt: flavor_ram: 1024 - barbican: + tempest_keystone_cntt: flavor_ram: 1024 - tempest_full: + tempest_heat_cntt: flavor_ram: 1024 - tempest_scenario: + rally_sanity_cntt: flavor_ram: 1024 - rally_sanity: + tempest_full_cntt: + flavor_ram: 1024 + tempest_scenario_cntt: + flavor_ram: 1024 + tempest_slow_cntt: flavor_ram: 1024 rally_full: flavor_ram: 1024 rally_jobs: flavor_ram: 1024 + vmtp: + flavor_ram: 2048 + shaker: + flavor_ram: 1024 + rally_full_cntt: + flavor_ram: 1024 + rally_jobs_cntt: + flavor_ram: 1024 ovs: vmready1: @@ -165,7 +249,19 @@ ovs: flavor_ram: 1024 tempest_smoke: flavor_ram: 1024 - neutron-tempest-plugin-api: + tempest_horizon: + flavor_ram: 1024 + tempest_neutron: + flavor_ram: 1024 + tempest_cinder: + flavor_ram: 1024 + tempest_keystone: + flavor_ram: 1024 + tempest_heat: + flavor_ram: 1024 + tempest_telemetry: + flavor_ram: 1024 + rally_sanity: flavor_ram: 1024 refstack_compute: flavor_ram: 1024 @@ -173,128 +269,210 @@ ovs: flavor_ram: 1024 refstack_platform: flavor_ram: 1024 + tempest_full: + flavor_ram: 1024 + tempest_scenario: + flavor_ram: 1024 + tempest_slow: + flavor_ram: 1024 patrole: flavor_ram: 1024 - vmtp: - flavor_ram: 2048 - shaker: + tempest_barbican: flavor_ram: 1024 - neutron_trunk: + tempest_octavia: flavor_ram: 1024 - networking-bgpvpn: + tempest_neutron_cntt: flavor_ram: 1024 - networking-sfc: + tempest_cinder_cntt: flavor_ram: 1024 - barbican: + tempest_keystone_cntt: flavor_ram: 1024 - tempest_full: + tempest_heat_cntt: flavor_ram: 1024 - tempest_scenario: + rally_sanity_cntt: flavor_ram: 1024 - rally_sanity: + tempest_full_cntt: + flavor_ram: 1024 + tempest_scenario_cntt: + flavor_ram: 1024 + tempest_slow_cntt: flavor_ram: 1024 rally_full: flavor_ram: 1024 rally_jobs: flavor_ram: 1024 + vmtp: + flavor_ram: 2048 + shaker: + flavor_ram: 1024 + rally_full_cntt: + flavor_ram: 1024 + rally_jobs_cntt: + flavor_ram: 1024 vio: vmready1: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk vmready2: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk singlevm1: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk singlevm2: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk vping_ssh: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk vping_userdata: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk cinder_test: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk tempest_smoke: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + tempest_horizon: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + tempest_neutron: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk - neutron-tempest-plugin-api: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + tempest_cinder: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk + tempest_keystone: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + tempest_heat: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + image_alt: + /home/opnfv/functest/images/Fedora-Cloud-Base-30-1.2.x86_64.vmdk + image_alt_format: vmdk + tempest_telemetry: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + rally_sanity: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk refstack_compute: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk refstack_object: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk refstack_platform: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + tempest_full: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + tempest_scenario: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + tempest_slow: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk patrole: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk - vmtp: - image: - /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.vmdk + tempest_barbican: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - shaker: - image: /home/opnfv/functest/images/shaker-image.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + tempest_octavia: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - neutron_trunk: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk + tempest_neutron_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk - networking-bgpvpn: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + tempest_cinder_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk - networking-sfc: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + tempest_keystone_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk - barbican: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + tempest_heat_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: + /home/opnfv/functest/images/Fedora-Cloud-Base-30-1.2.x86_64.vmdk image_alt_format: vmdk - tempest_full: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + rally_sanity_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + tempest_full_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk - tempest_scenario: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + tempest_scenario_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk - image_alt: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_alt_format: vmdk - rally_sanity: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + tempest_slow_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk + image_alt: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_alt_format: vmdk rally_full: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk rally_jobs: - image: /home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.vmdk + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + vmtp: + image: + /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.vmdk + image_format: vmdk + shaker: + image: /home/opnfv/functest/images/shaker-image.vmdk + image_format: vmdk + rally_full_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk + image_format: vmdk + rally_jobs_cntt: + image: /home/opnfv/functest/images/cirros-0.5.1-x86_64-disk.vmdk image_format: vmdk cloudify: image: diff --git a/functest/ci/convert_images.sh b/functest/ci/convert_images.sh index d7ed3887b..2159d2a60 100644 --- a/functest/ci/convert_images.sh +++ b/functest/ci/convert_images.sh @@ -1,11 +1,13 @@ -#!/bin/bash +#!/bin/sh set -ex -pushd "${1:-/home/opnfv/functest/images}" +initdir=$(pwd) + +cd "${1:-/home/opnfv/functest/images}" for i in *.img *.qcow2; do qemu-img convert -f qcow2 -O vmdk "$i" "${i%.*}.vmdk" done -popd +cd $initdir diff --git a/functest/ci/download_images.sh b/functest/ci/download_images.sh index 9612f85b2..a56c02b60 100644 --- a/functest/ci/download_images.sh +++ b/functest/ci/download_images.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh set -ex @@ -6,13 +6,14 @@ wget_opts="-N --tries=1 --connect-timeout=30" [ -t 1 ] || wget_opts="${wget_opts} --progress=dot:giga" cat << EOF | wget ${wget_opts} -i - -P ${1:-/home/opnfv/functest/images} -http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img +http://download.cirros-cloud.net/0.6.1/cirros-0.6.1-x86_64-disk.img https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloudimg-amd64-disk1.img https://cloud-images.ubuntu.com/releases/16.04/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img -http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-aarch64-disk.img -https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloudimg-arm64-uefi1.img +https://cloud-images.ubuntu.com/releases/18.04/release/ubuntu-18.04-server-cloudimg-amd64.img +http://download.cirros-cloud.net/0.6.1/cirros-0.6.1-aarch64-disk.img http://repository.cloudifysource.org/cloudify/19.01.24/community-release/cloudify-docker-manager-community-19.01.24.tar http://testresults.opnfv.org/functest/vyos-1.1.8-amd64.qcow2 -http://testresults.opnfv.org/functest/shaker-image.qcow2 -http://testresults.opnfv.org/functest/shaker-image-arm64.qcow2 +http://testresults.opnfv.org/functest/shaker-image-1.3.4+stretch.qcow2 +https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/30/Cloud/x86_64/images/Fedora-Cloud-Base-30-1.2.x86_64.qcow2 +https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/30/Cloud/aarch64/images/Fedora-Cloud-Base-30-1.2.aarch64.qcow2 EOF diff --git a/functest/ci/logging.debug.ini b/functest/ci/logging.debug.ini index 764a4e206..c926a5055 100644 --- a/functest/ci/logging.debug.ini +++ b/functest/ci/logging.debug.ini @@ -95,7 +95,7 @@ args=(sys.stdout,) [handler_file] class=FileHandler -level=DEBUG +level=INFO formatter=standard args=("/home/opnfv/functest/results/functest.log",) diff --git a/functest/ci/logging.ini b/functest/ci/logging.ini index e2a440910..dde079493 100644 --- a/functest/ci/logging.ini +++ b/functest/ci/logging.ini @@ -101,7 +101,7 @@ args=(sys.stdout,) [handler_file] class=FileHandler -level=DEBUG +level=INFO formatter=standard args=("/home/opnfv/functest/results/functest.log",) diff --git a/functest/ci/rally_aarch64_patch.conf b/functest/ci/rally_aarch64_patch.conf index baeceac76..4ea0d7605 100644 --- a/functest/ci/rally_aarch64_patch.conf +++ b/functest/ci/rally_aarch64_patch.conf @@ -1,5 +1,5 @@ img_name_regex = ^TestVM$ -img_url = http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-aarch64-disk.img +img_url = http://download.cirros-cloud.net/0.5.1/cirros-0.5.1-aarch64-disk.img flavor_ref_ram = 256 flavor_ref_alt_ram = 256 heat_instance_type_ram = 256 diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml index 16f2910b2..acf5a7199 100644 --- a/functest/ci/testcases.yaml +++ b/functest/ci/testcases.yaml @@ -2,7 +2,6 @@ tiers: - name: healthcheck - order: 0 description: >- First tier to be executed to verify the basic operations in the VIM. @@ -28,6 +27,8 @@ tiers: It creates and configures all tenant network ressources required by advanced testcases (subnet, network and router). + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: tenantnetwork1 @@ -40,6 +41,8 @@ tiers: It creates new user/project before creating and configuring all tenant network ressources required by a testcase (subnet, network and router). + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: tenantnetwork2 @@ -163,14 +166,28 @@ tiers: option: - '--concurrency=4' + - + case_name: tempest_horizon + project_name: functest + criteria: 100 + blocking: false + description: >- + This test case runs the Tempest suite proposed by the + Horizon project. + dependencies: + - DASHBOARD_URL: '^(?!\s*$).+' + run: + name: tempest_common + args: + mode: '^tempest.scenario.test_dashboard_basic_ops.' + - name: smoke - order: 1 description: >- Set of basic Functional tests to validate the OPNFV scenarios. testcases: - - case_name: neutron-tempest-plugin-api + case_name: tempest_neutron project_name: functest criteria: 100 blocking: false @@ -187,6 +204,74 @@ tiers: - '--concurrency=4' - + case_name: tempest_cinder + project_name: functest + criteria: 100 + blocking: false + description: >- + This test case runs the Tempest suite proposed by the + Cinder project. + run: + name: tempest_common + args: + mode: "(?!.*test_incremental_backup)\ + (?!.*test_backup_crossproject_admin_negative)\ + (?!.*test_backup_crossproject_user_negative)\ + (^cinder_tempest_plugin.)" + option: + - '--concurrency=4' + + - + case_name: tempest_keystone + project_name: functest + criteria: 100 + blocking: false + description: >- + This test case runs the Tempest suite proposed by the + Keystone project. + run: + name: tempest_common + args: + mode: 'keystone_tempest_plugin.' + option: + - '--concurrency=4' + + - + case_name: tempest_heat + project_name: functest + criteria: 100 + blocking: false + description: >- + This test case runs the Tempest suite proposed by the + Heat project. + run: + name: tempest_heat + args: + mode: '^heat_tempest_plugin.tests' + option: + - '--concurrency=1' + + - + case_name: tempest_telemetry + project_name: functest + criteria: 100 + blocking: false + description: >- + This test case runs the Tempest suite proposed by the + Telemetry project. + run: + name: tempest_common + args: + mode: "(?!.*test_autoscaling)(?!.*test_live)\ + (^telemetry_tempest_plugin)" + services: + - aodh + - gnocchi + - panko + option: + - '--concurrency=4' + + - case_name: rally_sanity project_name: functest criteria: 100 @@ -206,10 +291,11 @@ tiers: project_name: functest criteria: 100 blocking: false - deny_skipping: true description: >- This test case runs a sub group of tests of the OpenStack Compute testcases. + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: refstack args: @@ -222,7 +308,6 @@ tiers: project_name: functest criteria: 100 blocking: false - deny_skipping: true description: >- This test case runs a sub group of tests of the OpenStack Object testcases. @@ -238,10 +323,11 @@ tiers: project_name: functest criteria: 100 blocking: false - deny_skipping: true description: >- This test case runs a sub group of tests of the OpenStack Platform testcases. + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: refstack args: @@ -284,87 +370,162 @@ tiers: - '--concurrency=1' - - case_name: patrole + case_name: tempest_slow project_name: functest criteria: 100 blocking: false description: >- - Test suite from Patrole project. + The list of test cases is generated by + Tempest automatically and depends on the parameters of + the OpenStack deployment. + https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L84 run: - name: patrole + name: tempest_common args: - role: 'admin' - includes: - - 'image' - - 'network' - excludes: - - 'network.test_flavors_rbac' - - 'network.test_network_ip_availability_rbac' - - 'test_networks_multiprovider_rbac' - - 'test_auto_allocated_topology_rbac' - - 'test_create_network_provider_segmentation_id' - - 'test_update_network_provider_physical_network' - - 'test_update_network_provider_segmentation_id' - - 'network.test_agents_rbac' - - 'test_list_metadef_namespaces' + mode: '(?=.*\[.*\bslow\b.*\])(^tempest\.)' + option: + - '--concurrency=1' - - case_name: neutron_trunk + case_name: patrole_admin project_name: functest criteria: 100 blocking: false description: >- - This test case runs the neutron trunk subtest of the - OpenStack Tempest suite. The list of test cases is - generated by Tempest having as input the relevant - testcase list file. + Test suite from Patrole project. run: - name: tempest_common + name: patrole args: - mode: 'neutron_tempest_plugin.(api|scenario).test_trunk' - neutron_extensions: - - trunk - - trunk-details + roles: 'admin' + mode: "(?!.*test_unmanage_snapshot_rbac)\ + (?!.*test_show_auto_allocated_topology)\ + (?!.*test_delete_auto_allocated_topology)\ + (?!.*test_create_network_provider_segmentation_id)\ + (?!.*compute.test_floating_ips_rbac)\ + (?!.*test_reset_network)\ + (?!.*test_create_image_from_volume_backed_server)\ + (?!.*test_network_ip_availability_rbac.NetworkIpAvailabilityExtRbacTest.test_get_network_ip_availabilities)\ + (?!.*test_policy_bandwidth_limit_rule_rbac)\ + (?!.*test_policy_minimum_bandwidth_rule_rbac)\ + (?!.*test_group_type_specs)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_create_group_type)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_delete_group_type)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_update_group_type)\ + (?!.*test_group_snapshots_rbac)\ + (?!.*test_groups_rbac)\ + (?!.*test_quota_classes_rbac)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_create_interface)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_delete_interface)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_show_interface)\ + (?!.*test_user_messages_rbac)\ + (?!.*test_volume_actions_rbac.VolumesActionsV310RbacTest)\ + (?!.*test_volume_actions_rbac.VolumesActionsV312RbacTest)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_delete_volume_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_list_volumes_details_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_show_volume_details_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_update_volume_image_metadata)\ + (?!.*test_volumes_backup_rbac.VolumesBackupsV318RbacTest)\ + (?!.*test_volumes_backup_rbac.VolumesBackupsV39RbacTest)\ + (?!.*test_volume_types_rbac)\ + (?=.*[.*\bslow\b.*])\ + (^patrole_tempest_plugin.tests.api.(compute|image|network|volume))" + option: + - '--concurrency=4' - - case_name: networking-bgpvpn + case_name: patrole_member project_name: functest criteria: 100 blocking: false description: >- - This test case runs OpenStack networking-bgpvpn Tempest - suite. The list of test cases is generated by Tempest - having as input the relevant regex. + Test suite from Patrole project. run: - name: tempest_common + name: patrole args: - mode: '^neutron_tempest_plugin.bgpvpn.api\.' - neutron_extensions: - - bgpvpn + roles: 'member' + mode: "(?!.*test_unmanage_snapshot_rbac)\ + (?!.*test_show_auto_allocated_topology)\ + (?!.*test_delete_auto_allocated_topology)\ + (?!.*test_create_network_provider_segmentation_id)\ + (?!.*compute.test_floating_ips_rbac)\ + (?!.*test_reset_network)\ + (?!.*test_create_image_from_volume_backed_server)\ + (?!.*test_network_ip_availability_rbac.NetworkIpAvailabilityExtRbacTest.test_get_network_ip_availabilities)\ + (?!.*test_policy_bandwidth_limit_rule_rbac)\ + (?!.*test_policy_minimum_bandwidth_rule_rbac)\ + (?!.*test_group_type_specs)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_create_group_type)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_delete_group_type)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_update_group_type)\ + (?!.*test_group_snapshots_rbac)\ + (?!.*test_groups_rbac)\ + (?!.*test_quota_classes_rbac)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_create_interface)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_delete_interface)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_show_interface)\ + (?!.*test_user_messages_rbac)\ + (?!.*test_volume_actions_rbac.VolumesActionsV310RbacTest)\ + (?!.*test_volume_actions_rbac.VolumesActionsV312RbacTest)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_delete_volume_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_list_volumes_details_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_show_volume_details_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_update_volume_image_metadata)\ + (?!.*test_volumes_backup_rbac.VolumesBackupsV318RbacTest)\ + (?!.*test_volumes_backup_rbac.VolumesBackupsV39RbacTest)\ + (?!.*test_volume_types_rbac)\ + (?=.*[.*\bslow\b.*])\ + (^patrole_tempest_plugin.tests.api.(compute|image|network|volume))" option: - '--concurrency=4' - - case_name: networking-sfc + case_name: patrole_reader project_name: functest criteria: 100 blocking: false description: >- - This test case runs OpenStack networking-sfc Tempest - suite. The list of test cases is generated by Tempest - having as input the relevant regex. + Test suite from Patrole project. run: - name: tempest_common + name: patrole args: - mode: - '^(?:neutron_tempest_plugin\.sfc\.tests\.api).*$' - neutron_extensions: - - sfc + roles: 'reader' + mode: "(?!.*test_unmanage_snapshot_rbac)\ + (?!.*test_show_auto_allocated_topology)\ + (?!.*test_delete_auto_allocated_topology)\ + (?!.*test_create_network_provider_segmentation_id)\ + (?!.*compute.test_floating_ips_rbac)\ + (?!.*test_reset_network)\ + (?!.*test_create_image_from_volume_backed_server)\ + (?!.*test_network_ip_availability_rbac.NetworkIpAvailabilityExtRbacTest.test_get_network_ip_availabilities)\ + (?!.*test_policy_bandwidth_limit_rule_rbac)\ + (?!.*test_policy_minimum_bandwidth_rule_rbac)\ + (?!.*test_group_type_specs)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_create_group_type)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_delete_group_type)\ + (?!.*test_groups_rbac.GroupTypesV3RbacTest.test_update_group_type)\ + (?!.*test_group_snapshots_rbac)\ + (?!.*test_groups_rbac)\ + (?!.*test_quota_classes_rbac)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_create_interface)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_delete_interface)\ + (?!.*test_server_misc_policy_actions_rbac.MiscPolicyActionsNetworkRbacTest.test_show_interface)\ + (?!.*test_user_messages_rbac)\ + (?!.*test_volume_actions_rbac.VolumesActionsV310RbacTest)\ + (?!.*test_volume_actions_rbac.VolumesActionsV312RbacTest)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_delete_volume_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_list_volumes_details_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_show_volume_details_image_metadata)\ + (?!.*test_volume_metadata_rbac.VolumeMetadataV3RbacTest.test_update_volume_image_metadata)\ + (?!.*test_volumes_backup_rbac.VolumesBackupsV318RbacTest)\ + (?!.*test_volumes_backup_rbac.VolumesBackupsV39RbacTest)\ + (?!.*test_volume_types_rbac)\ + (?=.*[.*\bslow\b.*])\ + (^patrole_tempest_plugin.tests.api.(compute|image|network|volume))" option: - - '--concurrency=0' + - '--concurrency=4' - - case_name: barbican + case_name: tempest_barbican project_name: functest criteria: 100 blocking: false @@ -378,10 +539,368 @@ tiers: '^barbican_tempest_plugin.((?!test_signed_image_upload_boot_failure).)*$' services: - barbican + option: + - '--concurrency=4' + + - + case_name: tempest_octavia + project_name: functest + criteria: 100 + blocking: false + description: >- + It leverages on the tempest plugin containing tests used to + verify the functionality of an octavia installation. + run: + name: tempest_common + args: + mode: "(?!.*api.v2.test_availability_zone)\ + (?!.*api.v2.test_availability_zone_profile)\ + (?!.*api.v2.test_member.MemberAPITest.test_member_ipv4_create)\ + (?!.*api.v2.test_member.MemberAPITest.test_member_ipv6_create)\ + (^octavia_tempest_plugin.tests.(api|scenario))" + services: + - octavia + option: + - '--concurrency=2' + + - + case_name: tempest_cyborg + project_name: functest + criteria: 100 + blocking: false + description: >- + It leverages on the tempest plugin containing tests used to + verify the functionality of a cyborg installation. + run: + name: tempest_common + args: + mode: '^cyborg_tempest_plugin' + services: + - cyborg + option: + - '--concurrency=4' + + - + name: smoke_cntt + description: >- + Set of basic Functional tests to validate the OPNFV scenarios. + testcases: + - + case_name: tempest_neutron_cntt + project_name: functest + criteria: 100 + blocking: false + deny_skipping: true + tests_count: 564 + description: >- + This test case runs the Tempest suite proposed by the + Neutron project. The list of test cases is generated by + Tempest automatically and depends on the parameters of + the OpenStack deployment. + run: + name: tempest_common + args: + mode: "(?!.*admin.test_agent_availability_zone)\ + (?!.*admin.test_dhcp_agent_scheduler)\ + (?!.*admin.test_l3_agent_scheduler)\ + (?!.*admin.test_logging)\ + (?!.*admin.test_logging_negative)\ + (?!.*admin.test_network_segment_range)\ + (?!.*admin.test_ports.PortTestCasesAdmin.test_regenerate_mac_address)\ + (?!.*admin.test_ports.PortTestCasesResourceRequest)\ + (?!.*admin.test_routers_dvr)\ + (?!.*admin.test_routers_flavors)\ + (?!.*admin.test_routers_ha)\ + (?!.*test_conntrack_helper)\ + (?!.*test_floating_ips.FloatingIPPoolTestJSON)\ + (?!.*test_floating_ips.FloatingIPTestJSON.test_create_update_floatingip_port_details)\ + (?!.*test_local_ip)\ + (?!.*test_metering_extensions)\ + (?!.*test_metering_negative)\ + (?!.*test_networks.NetworksSearchCriteriaTest.test_list_validation_filters)\ + (?!.*test_networks.NetworksTestAdmin.test_create_tenant_network_vxlan)\ + (?!.*test_networks.NetworksTestJSON.test_create_update_network_dns_domain)\ + (?!.*test_port_forwardings)\ + (?!.*test_ports.PortsTaggingOnCreation)\ + (?!.*test_ports.PortsTestJSON.test_create_port_with_propagate_uplink_status)\ + (?!.*test_ports.PortsTestJSON.test_create_port_without_propagate_uplink_status)\ + (?!.*test_ports.PortsTestJSON.test_create_update_port_with_dns_domain)\ + (?!.*test_ports.PortsTestJSON.test_create_update_port_with_dns_name)\ + (?!.*test_ports.PortsTestJSON.test_create_update_port_with_no_dns_name)\ + (?!.*test_qos.QosMinimumBandwidthRuleTestJSON)\ + (?!.*test_revisions.TestRevisions.test_update_dns_domain_bumps_revision)\ + (?!.*test_revisions.TestRevisions.test_update_router_extra_attributes_bumps_revision)\ + (?!.*test_router_interface_fip)\ + (?!.*test_routers.DvrRoutersTest)\ + (?!.*test_routers.HaRoutersTest)\ + (?!.*test_routers.RoutersIpV6Test.test_extra_routes_atomic)\ + (?!.*test_routers.RoutersTest.test_extra_routes_atomic)\ + (?!.*test_routers_negative.DvrRoutersNegativeTest)\ + (?!.*test_routers_negative.DvrRoutersNegativeTestExtended)\ + (?!.*test_routers_negative.HaRoutersNegativeTest)\ + (?!.*test_security_groups.RbacSharedSecurityGroupTest)\ + (?!.*test_subnetpool_prefix_ops)\ + (?!.*test_subnetpools.RbacSubnetPoolTest)\ + (?!.*test_subnetpools.SubnetPoolsSearchCriteriaTest.test_list_validation_filters)\ + (?!.*test_subnetpools_negative.SubnetPoolsNegativeTestJSON.test_tenant_create_subnetpool_associate_shared_address_scope)\ + (?!.*test_subnets.SubnetsSearchCriteriaTest.test_list_validation_filters)\ + (?!.*test_timestamp.TestTimeStamp.test_segment_with_timestamp)\ + (?!.*test_trunk.TrunkTestInheritJSONBase.test_add_subport)\ + (?!.*test_trunk.TrunkTestMtusJSON)\ + (?!.*test_trunk_negative.TrunkTestJSON.test_create_subport_invalid_inherit_network_segmentation_type)\ + (?!.*test_trunk_negative.TrunkTestMtusJSON)\ + (^neutron_tempest_plugin.api)" + option: + - '--concurrency=4' + + - + case_name: tempest_cinder_cntt + project_name: functest + criteria: 100 + blocking: false + deny_skipping: true + tests_count: 10 + description: >- + This test case runs the Tempest suite proposed by the + Cinder project. + run: + name: tempest_common + args: + mode: "(?!.*test_incremental_backup)\ + (?!.*test_consistencygroups)\ + (?!.*test_backup_crossproject_admin_negative)\ + (?!.*test_backup_crossproject_user_negative)\ + (?!.*test_volume_encrypted.TestEncryptedCinderVolumes)\ + (?!.*rbac)\ + (^cinder_tempest_plugin.)" + option: + - '--concurrency=4' + + - + case_name: tempest_keystone_cntt + project_name: functest + criteria: 100 + blocking: false + deny_skipping: true + tests_count: 27 + description: >- + This test case runs the Tempest suite proposed by the + Keystone project. + run: + name: tempest_common + args: + mode: "(?!.*api.identity.v3.test_oauth1_tokens)\ + (?!.*rbac)\ + (?!.*scenario.test_federated_authentication)\ + keystone_tempest_plugin." + option: + - '--concurrency=4' + + - + case_name: tempest_heat_cntt + project_name: functest + criteria: 100 + blocking: false + deny_skipping: true + tests_count: 124 + description: >- + This test case runs the Tempest suite proposed by the + Heat project. + run: + name: tempest_heat + args: + mode: "(?!.*functional.test_lbaasv2)\ + (?!.*functional.test_encryption_vol_type)\ + (?!.*functional.test_event_sinks)\ + (?!.*functional.test_software_config.ZaqarSignalTransportTest)\ + (?!.*functional.test_stack_events)\ + (?!.*functional.test_waitcondition)\ + (?!.*RemoteStackTest.test_stack_create_with_cloud_credential)\ + (?!.*scenario.test_aodh_alarm)\ + (?!.*tests.scenario.test_autoscaling_lb)\ + (?!.*scenario.test_autoscaling_lbv2)\ + (?!.*scenario.test_server_software_config)\ + (?!.*test_volumes.VolumeBackupRestoreIntegrationTest)\ + (?!.*scenario.test_octavia_lbaas)\ + (?!.*scenario.test_server_cfn_init)\ + ^heat_tempest_plugin.tests" + option: + - '--concurrency=1' + + - + case_name: rally_sanity_cntt + project_name: functest + criteria: 100 + blocking: false + description: >- + This test case runs a sub group of tests of the OpenStack + Rally suite in smoke mode. + run: + name: rally_sanity + args: + tests: + - 'authenticate' + - 'glance' + - 'cinder' + - 'heat' + - 'keystone' + - 'neutron' + - 'nova' + - 'quotas' + - 'swift' + + - + case_name: tempest_full_cntt + project_name: functest + criteria: 100 + blocking: false + deny_skipping: true + tests_count: 1271 + description: >- + The list of test cases is generated by + Tempest automatically and depends on the parameters of + the OpenStack deployment. + https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L83 + run: + name: tempest_common + args: + mode: "(?!.*admin.test_agents)(?!.*test_fixed_ips)\ + (?!.*test_fixed_ips_negative)\ + (?!.*test_auto_allocate_network)(?!.*test_floating_ips_bulk)\ + (?!.*test_flavors_microversions.FlavorsV255TestJSON)\ + (?!.*test_flavors_microversions.FlavorsV261TestJSON)\ + (?!.*test_live_migration.LiveAutoBlockMigrationV225Test.test_iscsi_volume)\ + (?!.*test_live_migration.LiveAutoBlockMigrationV225Test.test_live_block_migration)\ + (?!.*test_live_migration.LiveAutoBlockMigrationV225Test.test_live_block_migration_paused)\ + (?!.*test_live_migration.LiveAutoBlockMigrationV225Test.test_volume_backed_live_migration)\ + (?!.*test_live_migration.LiveMigrationTest.test_iscsi_volume)\ + (?!.*test_live_migration.LiveMigrationTest.test_live_block_migration)\ + (?!.*test_live_migration.LiveMigrationTest.test_live_block_migration_paused)\ + (?!.*test_live_migration.LiveMigrationTest.test_volume_backed_live_migration)\ + (?!.*test_live_migration.LiveMigrationRemoteConsolesV26Test)\ + (?!.*test_quotas.QuotasAdminTestV257)\ + (?!.*test_servers.ServersAdminTestJSON.test_reset_network_inject_network_info)\ + (?!.*certificates.test_certificates)\ + (?!.*test_quotas_negative.QuotasSecurityGroupAdminNegativeTest)\ + (?!.*test_novnc)(?!.*test_server_personality)\ + (?!.*test_servers.ServerShowV263Test.test_show_update_rebuild_list_server)\ + (?!.*test_servers_microversions.ServerShowV254Test)\ + (?!.*test_servers_microversions.ServerShowV257Test)\ + (?!.*test_servers_negative.ServersNegativeTestJSON.test_personality_file_contents_not_encoded)\ + (?!.*servers.test_virtual_interfaces)\ + (?!.*test_server_actions.ServerActionsTestJSON.test_change_server_password)\ + (?!.*test_server_actions.ServerActionsTestJSON.test_get_vnc_console)\ + (?!.*test_server_actions.ServerActionsTestJSON.test_reboot_server_soft)\ + (?!.*test_server_rescue.ServerBootFromVolumeStableRescueTest)\ + (?!.*test_server_rescue.ServerStableDeviceRescueTest)\ + (?!.*test_security_group_default_rules)\ + (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_security_group_create_with_duplicate_name)\ + (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_security_group_create_with_invalid_group_description)\ + (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_security_group_create_with_invalid_group_name)\ + (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_update_security_group_with_invalid_sg_des)\ + (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_update_security_group_with_invalid_sg_id)\ + (?!.*test_security_groups_negative.SecurityGroupsNegativeTestJSON.test_update_security_group_with_invalid_sg_name)\ + (?!.*test_create_server.ServersTestFqdnHostnames.test_create_server_with_fqdn_name)\ + (?!.*test_server_metadata.ServerMetadataTestJSON)\ + (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_delete_metadata_non_existent_server)\ + (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_metadata_items_limit)\ + (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_set_metadata_invalid_key)\ + (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_set_metadata_non_existent_server)\ + (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_set_server_metadata_blank_key)\ + (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_set_server_metadata_missing_metadata)\ + (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_update_metadata_non_existent_server)\ + (?!.*test_server_metadata_negative.ServerMetadataNegativeTestJSON.test_update_metadata_with_blank_key)\ + (?!.*test_list_server_filters.ListServerFiltersTestJSON.test_list_servers_filtered_by_ip_regex)\ + (?!.*compute.test_virtual_interfaces)(?!.*compute.test_virtual_interfaces_negative)\ + (?!.*compute.test_networks)\ + (?!.*test_attach_volume.AttachVolumeMultiAttach)\ + (?!.*identity.admin.v2)(?!.*identity.v2)\ + (?!.*identity.v3.test_access_rules)\ + (?!.*identity.v3.test_application_credentials.ApplicationCredentialsV3Test.test_create_application_credential_access_rules)\ + (?!.*image.v1)\ + (?!.*image.v2.admin.test_images.ImportCopyImagesTest)\ + (?!.*image.v2.test_images_negative.ImagesNegativeTest.test_create_image_reserved_property)\ + (?!.*image.v2.test_images_negative.ImagesNegativeTest.test_update_image_reserved_property)\ + (?!.*image.v2.test_images_negative.ImportImagesNegativeTest.test_image_web_download_import_with_bad_url)\ + (?!.*image.v2.test_images.ImportImagesTest)\ + (?!.*image.v2.test_images.MultiStoresImportImages)\ + (?!.*admin.test_dhcp_agent_scheduler)\ + (?!.*admin.test_routers_dvr)\ + (?!.*test_metering_extensions)(?!.*network.test_tags)\ + (?!.*test_routers_negative.DvrRoutersNegativeTest)\ + (?!.*test_routers.RoutersIpV6Test.test_create_router_set_gateway_with_fixed_ip)\ + (?!.*test_routers.RoutersTest.test_create_router_set_gateway_with_fixed_ip)\ + (?!.*test_object_services.ObjectTest.test_create_object_with_transfer_encoding)\ + (?!.*test_encrypted_volumes_extend)\ + (?!.*test_group_snapshots.GroupSnapshotsV319Test.test_reset_group_snapshot_status)\ + (?!.*test_multi_backend)\ + (?!.*test_volume_retype.VolumeRetypeWithMigrationTest)\ + (?!.*test_volume_delete_cascade.VolumesDeleteCascade.test_volume_from_snapshot_cascade_delete)\ + (?!.*test_volumes_backup.VolumesBackupsTest.test_volume_backup_create_get_detailed_list_restore_delete)\ + (?!.*test_volumes_negative.UpdateMultiattachVolumeNegativeTest.test_multiattach_rw_volume_update_failure)\ + (?!.*test_volumes_extend.VolumesExtendAttachedTest.test_extend_attached_volume)\ + (?!.*\\[.*\\bslow\\b.*\\])(^tempest.api)" + option: + - '--concurrency=4' + + - + case_name: tempest_scenario_cntt + project_name: functest + criteria: 100 + blocking: false + deny_skipping: true + tests_count: 13 + description: >- + The list of test cases is generated by + Tempest automatically and depends on the parameters of + the OpenStack deployment. + https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L84 + run: + name: tempest_scenario + args: + mode: "\ + (?!.*test_compute_unified_limits)\ + (?!.*test_minbw_allocation_placement)\ + (?!.*test_network_qos_placement)\ + (?!.*test_unified_limits.ImageQuotaTest.test_image_count_uploading_quota)\ + (?!.*test_unified_limits.ImageQuotaTest.test_image_stage_quota)\ + (?!.*test_volume_boot_pattern.TestVolumeBootPattern.test_boot_server_from_encrypted_volume_luks)\ + (?!.*\\[.*\\bslow\\b.*\\])(^tempest.scenario)" + option: + - '--concurrency=1' + + - + case_name: tempest_slow_cntt + project_name: functest + criteria: 100 + blocking: false + deny_skipping: true + tests_count: 43 + description: >- + The list of test cases is generated by + Tempest automatically and depends on the parameters of + the OpenStack deployment. + https://github.com/openstack/tempest/blob/18.0.0/tox.ini#L84 + run: + name: tempest_common + args: + mode: "(?!.*test_volume_swap)\ + (?!.*test_server_personality)\ + (?!.*test_server_rescue.ServerBootFromVolumeStableRescueTest)\ + (?!.*test_container_sync.ContainerSyncTest.test_container_synchronization)\ + (?!.*test_container_sync_middleware.ContainerSyncMiddlewareTest.test_container_synchronization)\ + (?!.*test_encrypted_cinder_volumes)\ + (?!.*test_minbw_allocation_placement)\ + (?!.*test_network_basic_ops.TestNetworkBasicOps.test_router_rescheduling)\ + (?!.*test_shelve_instance.TestShelveInstance.test_cold_migrate_unshelved_instance)\ + (?!.*test_volume_migrate_attached)\ + (?!.*test_network_advanced_server_ops.TestNetworkAdvancedServerOps.test_server_connectivity_cold_migration_revert)\ + (?=.*\\[.*\\bslow\\b.*\\])(^tempest.)" + option: + - '--concurrency=1' - name: benchmarking - order: 2 description: >- Run several OpenStack performance tools https://docs.openstack.org/performance-docs/latest/methodologies/tools.html @@ -409,6 +928,8 @@ tiers: description: >- This test case runs a group of Rally jobs used in OpenStack gating + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: rally_jobs args: @@ -425,7 +946,7 @@ tiers: perform ping connectivity, round trip time measurement (latency) and TCP/UDP throughput dependencies: - - POD_ARCH: '^(?!aarch64$)' + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: vmtp @@ -439,89 +960,55 @@ tiers: like iperf, iperf3 and netperf (with help of flent). Shaker is able to deploy OpenStack instances and networks in different topologies. + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: shaker - - name: features - order: 3 + name: benchmarking_cntt description: >- - Test suites from feature projects - integrated in functest + Run several OpenStack performance tools + https://docs.openstack.org/performance-docs/latest/methodologies/tools.html testcases: - - case_name: doctor-notification - project_name: doctor - enabled: false + case_name: rally_full_cntt + project_name: functest criteria: 100 blocking: false description: >- - Test suite from Doctor project. - dependencies: - - INSTALLER_TYPE: '(apex)|(fuel)|(daisy)' - - DEPLOY_SCENARIO: '^((?!fdio|nofeature).)*$' + This test case runs the full suite of scenarios of the + OpenStack Rally suite using several threads and iterations. run: - name: bashfeature + name: rally_full args: - cmd: 'doctor-test' + tests: + - 'authenticate' + - 'glance' + - 'cinder' + - 'heat' + - 'keystone' + - 'neutron' + - 'nova' + - 'quotas' + - 'swift' - - case_name: functest-odl-sfc - project_name: sfc - criteria: 100 - blocking: false - description: >- - Test suite for odl-sfc to test two chains with one SF and - one chain with two SFs - dependencies: - - DEPLOY_SCENARIO: 'odl.*sfc' - run: - name: functest-odl-sfc - - - - case_name: barometercollectd - project_name: barometer - enabled: false - criteria: 100 - blocking: false - description: >- - Test suite for the Barometer project. Separate tests verify - the proper configuration and basic functionality of all the - collectd plugins as described in the Project Release Plan - dependencies: - - DEPLOY_SCENARIO: 'bar' - run: - name: barometercollectd - - - - case_name: vgpu + case_name: rally_jobs_cntt project_name: functest criteria: 100 blocking: false description: >- - Test suite for the OpenStack vGPU feature - dependencies: - - DEPLOY_SCENARIO: 'vgpu' - run: - name: vgpu - - - - case_name: stor4nfv_os - project_name: stor4nfv - enabled: false - criteria: 100 - blocking: false - description: >- - This tests are necessary demonstrate conformance - of the OpenStack+Stor4NFV deployment. - dependencies: - - DEPLOY_SCENARIO: 'stor4nfv' + This test case runs a group of Rally jobs used in + OpenStack gating run: - name: stor4nfv_os + name: rally_jobs + args: + tests: + - 'neutron' - name: vnf - order: 4 description: >- Collection of VNF test cases. testcases: @@ -544,7 +1031,7 @@ tiers: Clearwater using the Cloudify orchestrator. It also runs some signaling traffic. dependencies: - - DEPLOY_SCENARIO: 'os-.*-nofeature-.*ha' + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: cloudify_ims @@ -557,6 +1044,8 @@ tiers: This test case deploys an OpenSource vIMS solution from Clearwater using the OpenStack Heat orchestrator. It also runs some signaling traffic. + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: heat_ims @@ -567,6 +1056,8 @@ tiers: blocking: false description: >- This test case is vRouter testing. + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: vyos_vrouter @@ -578,5 +1069,7 @@ tiers: description: >- vEPC validation with Juju as VNF manager and ABoT as test executor. + dependencies: + - NO_TENANT_NETWORK: '^(?![tT]rue$)' run: name: juju_epc diff --git a/functest/core/cloudify.py b/functest/core/cloudify.py index b5bd1b3c2..966d33645 100644 --- a/functest/core/cloudify.py +++ b/functest/core/cloudify.py @@ -29,7 +29,7 @@ class Cloudify(singlevm.SingleVm2): __logger = logging.getLogger(__name__) filename = ('/home/opnfv/functest/images/' - 'ubuntu-16.04-server-cloudimg-amd64-disk1.img') + 'ubuntu-18.04-server-cloudimg-amd64.img') flavor_ram = 4096 flavor_vcpus = 2 flavor_disk = 40 @@ -46,11 +46,11 @@ class Cloudify(singlevm.SingleVm2): """Initialize Cloudify testcase object.""" if "case_name" not in kwargs: kwargs["case_name"] = "cloudify" - super(Cloudify, self).__init__(**kwargs) + super().__init__(**kwargs) self.cfy_client = None def prepare(self): - super(Cloudify, self).prepare() + super().prepare() for port in self.ports: self.cloud.create_security_group_rule( self.sec.id, port_range_min=port, port_range_max=port, @@ -64,20 +64,19 @@ class Cloudify(singlevm.SingleVm2): scpc.put(self.cloudify_archive, remote_path=os.path.basename(self.cloudify_archive)) (_, stdout, stderr) = self.ssh.exec_command( - "sudo wget https://get.docker.com/ -O script.sh && " - "sudo chmod +x script.sh && " - "sudo ./script.sh && " - "sudo docker load -i ~/{} && " + "sudo apt-get update && " + "sudo apt-get install -y docker.io && " + "sudo docker load -i " + f"~/{os.path.basename(self.cloudify_archive)} && " "sudo docker run --name cfy_manager_local -d " "--restart unless-stopped -v /sys/fs/cgroup:/sys/fs/cgroup:ro " "--tmpfs /run --tmpfs /run/lock --security-opt seccomp:unconfined " - "--cap-add SYS_ADMIN --network=host {}".format( - os.path.basename(self.cloudify_archive), - self.cloudify_container)) - self.__logger.debug("output:\n%s", stdout.read()) - self.__logger.debug("error:\n%s", stderr.read()) + f"--cap-add SYS_ADMIN --network=host {self.cloudify_container}") + self.__logger.debug("output:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("error:\n%s", stderr.read().decode("utf-8")) self.cfy_client = CloudifyClient( - host=self.fip.floating_ip_address, + host=self.fip.floating_ip_address if self.fip else ( + self.sshvm.public_v4), username='admin', password='admin', tenant='default_tenant') self.__logger.info("Attemps running status of the Manager") secret_key = "foo" @@ -124,17 +123,17 @@ class Cloudify(singlevm.SingleVm2): "cfy_manager_local:/etc/cloudify/ && " "sudo docker exec cfy_manager_local " "chmod 444 /etc/cloudify/cloudify_ims.pem") - self.__logger.debug("output:\n%s", stdout.read()) - self.__logger.debug("error:\n%s", stderr.read()) + self.__logger.debug("output:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("error:\n%s", stderr.read().decode("utf-8")) def upload_cfy_plugins(self, yaml, wgn): """Upload Cloudify plugins""" (_, stdout, stderr) = self.ssh.exec_command( "sudo docker exec cfy_manager_local " - "cfy plugins upload -y {} {} && " - "sudo docker exec cfy_manager_local cfy status".format(yaml, wgn)) - self.__logger.debug("output:\n%s", stdout.read()) - self.__logger.debug("error:\n%s", stderr.read()) + f"cfy plugins upload -y {yaml} {wgn} && " + "sudo docker exec cfy_manager_local cfy status") + self.__logger.debug("output:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("error:\n%s", stderr.read().decode("utf-8")) def kill_existing_execution(self, dep_name): """kill existing execution""" @@ -188,9 +187,8 @@ def wait_for_execution(client, execution, logger, timeout=3600, ): if timeout is not None: if time.time() > deadline: raise RuntimeError( - 'execution of operation {0} for deployment {1} ' - 'timed out'.format(execution.workflow_id, - execution.deployment_id)) + 'execution of operation {execution.workflow_id} for ' + 'deployment {execution.deployment_id} timed out') # update the remaining timeout timeout = deadline - time.time() @@ -218,4 +216,4 @@ def get_execution_id(client, deployment_id): return execution raise RuntimeError('Failed to get create_deployment_environment ' 'workflow execution.' - 'Available executions: {0}'.format(executions)) + f'Available executions: {executions}') diff --git a/functest/core/singlevm.py b/functest/core/singlevm.py index dce6d819b..4bce516d3 100644 --- a/functest/core/singlevm.py +++ b/functest/core/singlevm.py @@ -39,7 +39,7 @@ class VmReady1(tenantnetwork.TenantNetwork1): # pylint: disable=too-many-instance-attributes __logger = logging.getLogger(__name__) - filename = '/home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img' + filename = '/home/opnfv/functest/images/cirros-0.6.1-x86_64-disk.img' image_format = 'qcow2' extra_properties = {} filename_alt = filename @@ -59,7 +59,7 @@ class VmReady1(tenantnetwork.TenantNetwork1): def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'vmready1' - super(VmReady1, self).__init__(**kwargs) + super().__init__(**kwargs) self.image = None self.flavor = None @@ -80,19 +80,18 @@ class VmReady1(tenantnetwork.TenantNetwork1): functest_utils.convert_ini_to_dict( env.get('IMAGE_PROPERTIES'))) extra_properties.update( - getattr(config.CONF, '{}_extra_properties'.format( - self.case_name), {})) + getattr(config.CONF, f'{self.case_name}_extra_properties', {})) image = self.cloud.create_image( - name if name else '{}-img_{}'.format(self.case_name, self.guid), + name if name else f'{self.case_name}-img_{self.guid}', filename=getattr( - config.CONF, '{}_image'.format(self.case_name), + config.CONF, f'{self.case_name}_image', self.filename), meta=extra_properties, disk_format=getattr( - config.CONF, '{}_image_format'.format(self.case_name), + config.CONF, f'{self.case_name}_image_format', self.image_format), visibility=getattr( - config.CONF, '{}_visibility'.format(self.case_name), + config.CONF, f'{self.case_name}_visibility', self.visibility), wait=True) self.__logger.debug("image: %s", image) @@ -115,20 +114,18 @@ class VmReady1(tenantnetwork.TenantNetwork1): functest_utils.convert_ini_to_dict( env.get('IMAGE_PROPERTIES'))) extra_alt_properties.update( - getattr(config.CONF, '{}_extra_alt_properties'.format( - self.case_name), {})) + getattr(config.CONF, f'{self.case_name}_extra_alt_properties', {})) image = self.cloud.create_image( - name if name else '{}-img_alt_{}'.format( - self.case_name, self.guid), + name if name else f'{self.case_name}-img_alt_{self.guid}', filename=getattr( - config.CONF, '{}_image_alt'.format(self.case_name), + config.CONF, f'{self.case_name}_image_alt', self.filename_alt), meta=extra_alt_properties, disk_format=getattr( - config.CONF, '{}_image_alt_format'.format(self.case_name), + config.CONF, f'{self.case_name}_image_alt_format', self.image_format), visibility=getattr( - config.CONF, '{}_visibility'.format(self.case_name), + config.CONF, f'{self.case_name}_visibility', self.visibility), wait=True) self.__logger.debug("image: %s", image) @@ -146,12 +143,12 @@ class VmReady1(tenantnetwork.TenantNetwork1): """ assert self.orig_cloud flavor = self.orig_cloud.create_flavor( - name if name else '{}-flavor_{}'.format(self.case_name, self.guid), - getattr(config.CONF, '{}_flavor_ram'.format(self.case_name), + name if name else f'{self.case_name}-flavor_{self.guid}', + getattr(config.CONF, f'{self.case_name}_flavor_ram', self.flavor_ram), - getattr(config.CONF, '{}_flavor_vcpus'.format(self.case_name), + getattr(config.CONF, f'{self.case_name}_flavor_vcpus', self.flavor_vcpus), - getattr(config.CONF, '{}_flavor_disk'.format(self.case_name), + getattr(config.CONF, f'{self.case_name}_flavor_disk', self.flavor_disk)) self.__logger.debug("flavor: %s", flavor) flavor_extra_specs = self.flavor_extra_specs.copy() @@ -161,7 +158,7 @@ class VmReady1(tenantnetwork.TenantNetwork1): env.get('FLAVOR_EXTRA_SPECS'))) flavor_extra_specs.update( getattr(config.CONF, - '{}_flavor_extra_specs'.format(self.case_name), {})) + f'{self.case_name}_flavor_extra_specs', {})) self.orig_cloud.set_flavor_specs(flavor.id, flavor_extra_specs) return flavor @@ -177,13 +174,12 @@ class VmReady1(tenantnetwork.TenantNetwork1): """ assert self.orig_cloud flavor = self.orig_cloud.create_flavor( - name if name else '{}-flavor_alt_{}'.format( - self.case_name, self.guid), - getattr(config.CONF, '{}_flavor_alt_ram'.format(self.case_name), + name if name else f'{self.case_name}-flavor_alt_{self.guid}', + getattr(config.CONF, f'{self.case_name}_flavor_alt_ram', self.flavor_alt_ram), - getattr(config.CONF, '{}_flavor_alt_vcpus'.format(self.case_name), + getattr(config.CONF, f'{self.case_name}_flavor_alt_vcpus', self.flavor_alt_vcpus), - getattr(config.CONF, '{}_flavor_alt_disk'.format(self.case_name), + getattr(config.CONF, f'{self.case_name}_flavor_alt_disk', self.flavor_alt_disk)) self.__logger.debug("flavor: %s", flavor) flavor_alt_extra_specs = self.flavor_alt_extra_specs.copy() @@ -193,7 +189,7 @@ class VmReady1(tenantnetwork.TenantNetwork1): env.get('FLAVOR_EXTRA_SPECS'))) flavor_alt_extra_specs.update( getattr(config.CONF, - '{}_flavor_alt_extra_specs'.format(self.case_name), {})) + f'{self.case_name}_flavor_alt_extra_specs', {})) self.orig_cloud.set_flavor_specs( flavor.id, flavor_alt_extra_specs) return flavor @@ -210,14 +206,16 @@ class VmReady1(tenantnetwork.TenantNetwork1): """ assert self.cloud vm1 = self.cloud.create_server( - name if name else '{}-vm_{}'.format(self.case_name, self.guid), + name if name else f'{self.case_name}-vm_{self.guid}', image=self.image.id, flavor=self.flavor.id, - auto_ip=False, network=self.network.id, + auto_ip=False, + network=self.network.id if self.network else env.get( + "EXTERNAL_NETWORK"), timeout=self.create_server_timeout, wait=True, **kwargs) self.__logger.debug("vm: %s", vm1) return vm1 - def check_regex_in_console(self, name, regex=' login: ', loop=1): + def check_regex_in_console(self, name, regex=' login: ', loop=6): """Wait for specific message in console Returns: True or False on errors @@ -237,6 +235,42 @@ class VmReady1(tenantnetwork.TenantNetwork1): self.__logger.error("cannot find regex '%s' in console", regex) return False + def clean_orphan_security_groups(self): + """Clean all security groups which are not owned by an existing tenant + + It lists all orphan security groups in use as debug to avoid + misunderstanding the testcase results (it could happen if cloud admin + removes accounts without cleaning the virtual machines) + """ + sec_groups = self.orig_cloud.list_security_groups() + for sec_group in sec_groups: + if not sec_group.tenant_id: + continue + if not self.orig_cloud.get_project(sec_group.tenant_id): + self.__logger.debug("Cleaning security group %s", sec_group.id) + try: + self.orig_cloud.delete_security_group(sec_group.id) + except Exception: # pylint: disable=broad-except + self.__logger.debug( + "Orphan security group %s in use", sec_group.id) + + def count_hypervisors(self): + """Count hypervisors.""" + if env.get('SKIP_DOWN_HYPERVISORS').lower() == 'false': + return len(self.orig_cloud.list_hypervisors()) + return self.count_active_hypervisors() + + def count_active_hypervisors(self): + """Count all hypervisors which are up.""" + compute_cnt = 0 + for hypervisor in self.orig_cloud.list_hypervisors(): + if hypervisor['state'] == 'up': + compute_cnt += 1 + else: + self.__logger.warning( + "%s is down", hypervisor['hypervisor_hostname']) + return compute_cnt + def run(self, **kwargs): """Boot the new VM @@ -251,7 +285,7 @@ class VmReady1(tenantnetwork.TenantNetwork1): status = testcase.TestCase.EX_RUN_ERROR try: assert self.cloud - assert super(VmReady1, self).run( + assert super().run( **kwargs) == testcase.TestCase.EX_OK self.image = self.publish_image() self.flavor = self.create_flavor() @@ -268,11 +302,13 @@ class VmReady1(tenantnetwork.TenantNetwork1): try: assert self.orig_cloud assert self.cloud - super(VmReady1, self).clean() + super().clean() if self.image: self.cloud.delete_image(self.image.id) if self.flavor: self.orig_cloud.delete_flavor(self.flavor.id) + if env.get('CLEAN_ORPHAN_SECURITY_GROUPS').lower() == 'true': + self.clean_orphan_security_groups() except Exception: # pylint: disable=broad-except self.__logger.exception("Cannot clean all resources") @@ -292,7 +328,7 @@ class VmReady2(VmReady1): def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'vmready2' - super(VmReady2, self).__init__(**kwargs) + super().__init__(**kwargs) try: assert self.orig_cloud self.project = tenantnetwork.NewProject( @@ -306,7 +342,7 @@ class VmReady2(VmReady1): def clean(self): try: - super(VmReady2, self).clean() + super().clean() assert self.project self.project.clean() except Exception: # pylint: disable=broad-except @@ -329,11 +365,13 @@ class SingleVm1(VmReady1): ssh_connect_timeout = 1 ssh_connect_loops = 6 create_floating_ip_timeout = 120 + check_console_loop = 6 + check_console_regex = ' login: ' def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'singlevm1' - super(SingleVm1, self).__init__(**kwargs) + super().__init__(**kwargs) self.sshvm = None self.sec = None self.fip = None @@ -351,14 +389,15 @@ class SingleVm1(VmReady1): """ assert self.cloud self.keypair = self.cloud.create_keypair( - '{}-kp_{}'.format(self.case_name, self.guid)) + f'{self.case_name}-kp_{self.guid}') self.__logger.debug("keypair: %s", self.keypair) self.__logger.debug("private_key:\n%s", self.keypair.private_key) - with open(self.key_filename, 'w') as private_key_file: + with open( + self.key_filename, 'w', encoding='utf-8') as private_key_file: private_key_file.write(self.keypair.private_key) self.sec = self.cloud.create_security_group( - '{}-sg_{}'.format(self.case_name, self.guid), - 'created by OPNFV Functest ({})'.format(self.case_name)) + f'{self.case_name}-sg_{self.guid}', + f'created by OPNFV Functest ({self.case_name})') self.cloud.create_security_group_rule( self.sec.id, port_range_min='22', port_range_max='22', protocol='tcp', direction='ingress') @@ -376,10 +415,12 @@ class SingleVm1(VmReady1): - None on error """ assert vm1 - fip = self.cloud.create_floating_ip( - network=self.ext_net.id, server=vm1, wait=True, - timeout=self.create_floating_ip_timeout) - self.__logger.debug("floating_ip: %s", fip) + fip = None + if env.get('NO_TENANT_NETWORK').lower() != 'true': + fip = self.cloud.create_floating_ip( + network=self.ext_net.id, server=vm1, wait=True, + timeout=self.create_floating_ip_timeout) + self.__logger.debug("floating_ip: %s", fip) ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy()) for loop in range(self.ssh_connect_loops): @@ -387,20 +428,20 @@ class SingleVm1(VmReady1): p_console = self.cloud.get_server_console(vm1) self.__logger.debug("vm console: \n%s", p_console) ssh.connect( - fip.floating_ip_address, + fip.floating_ip_address if fip else vm1.public_v4, username=getattr( config.CONF, - '{}_image_user'.format(self.case_name), self.username), + f'{self.case_name}_image_user', self.username), key_filename=self.key_filename, timeout=getattr( config.CONF, - '{}_vm_ssh_connect_timeout'.format(self.case_name), + f'{self.case_name}_vm_ssh_connect_timeout', self.ssh_connect_timeout)) break except Exception as exc: # pylint: disable=broad-except self.__logger.debug( "try %s: cannot connect to %s: %s", loop + 1, - fip.floating_ip_address, exc) + fip.floating_ip_address if fip else vm1.public_v4, exc) time.sleep(9) else: self.__logger.error( @@ -416,8 +457,8 @@ class SingleVm1(VmReady1): Returns: echo exit codes """ (_, stdout, stderr) = self.ssh.exec_command('echo Hello World') - self.__logger.debug("output:\n%s", stdout.read()) - self.__logger.debug("error:\n%s", stderr.read()) + self.__logger.debug("output:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("error:\n%s", stderr.read().decode("utf-8")) return stdout.channel.recv_exit_status() def run(self, **kwargs): @@ -436,16 +477,19 @@ class SingleVm1(VmReady1): status = testcase.TestCase.EX_RUN_ERROR try: assert self.cloud - assert super(SingleVm1, self).run( + assert super().run( **kwargs) == testcase.TestCase.EX_OK self.result = 0 self.prepare() self.sshvm = self.boot_vm( key_name=self.keypair.id, security_groups=[self.sec.id]) - (self.fip, self.ssh) = self.connect(self.sshvm) - if not self.execute(): - self.result = 100 - status = testcase.TestCase.EX_OK + if self.check_regex_in_console( + self.sshvm.name, regex=self.check_console_regex, + loop=self.check_console_loop): + (self.fip, self.ssh) = self.connect(self.sshvm) + if not self.execute(): + self.result = 100 + status = testcase.TestCase.EX_OK except Exception: # pylint: disable=broad-except self.__logger.exception('Cannot run %s', self.case_name) finally: @@ -464,7 +508,7 @@ class SingleVm1(VmReady1): self.cloud.delete_security_group(self.sec.id) if self.keypair: self.cloud.delete_keypair(self.keypair.name) - super(SingleVm1, self).clean() + super().clean() except Exception: # pylint: disable=broad-except self.__logger.exception("Cannot clean all resources") @@ -484,7 +528,7 @@ class SingleVm2(SingleVm1): def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'singlevm2' - super(SingleVm2, self).__init__(**kwargs) + super().__init__(**kwargs) try: assert self.orig_cloud self.project = tenantnetwork.NewProject( @@ -498,7 +542,7 @@ class SingleVm2(SingleVm1): def clean(self): try: - super(SingleVm2, self).clean() + super().clean() assert self.project self.project.clean() except Exception: # pylint: disable=broad-except diff --git a/functest/core/tenantnetwork.py b/functest/core/tenantnetwork.py index 604e49ae5..3670dbe8a 100644 --- a/functest/core/tenantnetwork.py +++ b/functest/core/tenantnetwork.py @@ -20,17 +20,17 @@ This classes could be reused by more complexed scenarios (Single VM) import logging import os -import random -import string import time import uuid import os_client_config import shade +from tempest.lib.common.utils import data_utils from xtesting.core import testcase from functest.utils import config from functest.utils import env +from functest.utils import functest_utils class NewProject(): @@ -55,19 +55,18 @@ class NewProject(): """Create projects/users""" assert self.orig_cloud assert self.case_name - self.password = ''.join(random.choice( - string.ascii_letters + string.digits) for _ in range(30)) + self.password = data_utils.rand_password().replace('%', '!') + self.__logger.debug("password: %s", self.password) self.domain = self.orig_cloud.get_domain( name_or_id=self.orig_cloud.auth.get( "project_domain_name", "Default")) self.project = self.orig_cloud.create_project( - name='{}-project_{}'.format(self.case_name[:18], self.guid), - description="Created by OPNFV Functest: {}".format( - self.case_name), + name=f'{self.case_name[:18]}-project_{self.guid}', + description=f"Created by OPNFV Functest: {self.case_name}", domain_id=self.domain.id) self.__logger.debug("project: %s", self.project) self.user = self.orig_cloud.create_user( - name='{}-user_{}'.format(self.case_name, self.guid), + name=f'{self.case_name}-user_{self.guid}', password=self.password, domain_id=self.domain.id) self.__logger.debug("user: %s", self.user) @@ -77,7 +76,7 @@ class NewProject(): elif self.orig_cloud.get_role(self.default_member.lower()): self.role_name = self.default_member.lower() else: - raise Exception("Cannot detect {}".format(self.default_member)) + raise Exception(f"Cannot detect {self.default_member}") except Exception: # pylint: disable=broad-except self.__logger.info("Creating default role %s", self.default_member) role = self.orig_cloud.create_role(self.default_member) @@ -146,27 +145,28 @@ class TenantNetwork1(testcase.TestCase): __logger = logging.getLogger(__name__) cidr = '192.168.120.0/24' shared_network = False - allow_no_fip = False def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'tenantnetwork1' - super(TenantNetwork1, self).__init__(**kwargs) - self.res_dir = os.path.join( - getattr(config.CONF, 'dir_results'), self.case_name) + super().__init__(**kwargs) + self.dir_results = os.path.join(getattr(config.CONF, 'dir_results')) + self.res_dir = os.path.join(self.dir_results, self.case_name) + self.output_log_name = 'functest.log' + self.output_debug_log_name = 'functest.debug.log' + self.ext_net = None try: cloud_config = os_client_config.get_config() self.cloud = self.orig_cloud = shade.OpenStackCloud( cloud_config=cloud_config) except Exception: # pylint: disable=broad-except self.cloud = self.orig_cloud = None - self.ext_net = None self.__logger.exception("Cannot connect to Cloud") - try: - self.ext_net = self.get_external_network(self.cloud) - except Exception: # pylint: disable=broad-except - self.ext_net = None - self.__logger.exception("Cannot get the external network") + if env.get('NO_TENANT_NETWORK').lower() != 'true': + try: + self.ext_net = self.get_external_network(self.cloud) + except Exception: # pylint: disable=broad-except + self.__logger.exception("Cannot get the external network") self.guid = str(uuid.uuid4()) self.network = None self.subnet = None @@ -203,7 +203,7 @@ class TenantNetwork1(testcase.TestCase): @staticmethod def get_public_auth_url(cloud): """Get Keystone public endpoint""" - keystone_id = cloud.search_services('keystone')[0].id + keystone_id = functest_utils.search_services(cloud, 'keystone')[0].id endpoint = cloud.search_endpoints( filters={'interface': 'public', 'service_id': keystone_id})[0].url @@ -218,18 +218,18 @@ class TenantNetwork1(testcase.TestCase): Raises: expection on error """ assert self.cloud - if not self.allow_no_fip: + if env.get('NO_TENANT_NETWORK').lower() != 'true': assert self.ext_net provider = {} - if hasattr(config.CONF, '{}_network_type'.format(self.case_name)): + if hasattr(config.CONF, f'{self.case_name}_network_type'): provider["network_type"] = getattr( - config.CONF, '{}_network_type'.format(self.case_name)) - if hasattr(config.CONF, '{}_physical_network'.format(self.case_name)): + config.CONF, f'{self.case_name}_network_type') + if hasattr(config.CONF, f'{self.case_name}_physical_network'): provider["physical_network"] = getattr( - config.CONF, '{}_physical_network'.format(self.case_name)) - if hasattr(config.CONF, '{}_segmentation_id'.format(self.case_name)): + config.CONF, f'{self.case_name}_physical_network') + if hasattr(config.CONF, f'{self.case_name}_segmentation_id'): provider["segmentation_id"] = getattr( - config.CONF, '{}_segmentation_id'.format(self.case_name)) + config.CONF, f'{self.case_name}_segmentation_id') domain = self.orig_cloud.get_domain( name_or_id=self.orig_cloud.auth.get( "project_domain_name", "Default")) @@ -237,23 +237,23 @@ class TenantNetwork1(testcase.TestCase): self.cloud.auth['project_name'], domain_id=domain.id) self.network = self.orig_cloud.create_network( - '{}-net_{}'.format(self.case_name, self.guid), + f'{self.case_name}-net_{self.guid}', provider=provider, project_id=project.id, shared=self.shared_network) self.__logger.debug("network: %s", self.network) self.subnet = self.cloud.create_subnet( self.network.id, - subnet_name='{}-subnet_{}'.format(self.case_name, self.guid), + subnet_name=f'{self.case_name}-subnet_{self.guid}', cidr=getattr( - config.CONF, '{}_private_subnet_cidr'.format(self.case_name), + config.CONF, f'{self.case_name}_private_subnet_cidr', self.cidr), enable_dhcp=True, dns_nameservers=[env.get('NAMESERVER')]) self.__logger.debug("subnet: %s", self.subnet) self.router = self.cloud.create_router( - name='{}-router_{}'.format(self.case_name, self.guid), + name=f'{self.case_name}-router_{self.guid}', ext_gateway_net_id=self.ext_net.id if self.ext_net else None) self.__logger.debug("router: %s", self.router) self.cloud.add_router_interface(self.router, subnet_id=self.subnet.id) @@ -263,7 +263,8 @@ class TenantNetwork1(testcase.TestCase): try: assert self.cloud self.start_time = time.time() - self.create_network_resources() + if env.get('NO_TENANT_NETWORK').lower() != 'true': + self.create_network_resources() self.result = 100 status = testcase.TestCase.EX_OK except Exception: # pylint: disable=broad-except @@ -304,7 +305,7 @@ class TenantNetwork2(TenantNetwork1): def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'tenantnetwork2' - super(TenantNetwork2, self).__init__(**kwargs) + super().__init__(**kwargs) try: assert self.cloud self.project = NewProject( @@ -318,7 +319,7 @@ class TenantNetwork2(TenantNetwork1): def clean(self): try: - super(TenantNetwork2, self).clean() + super().clean() assert self.project self.project.clean() except Exception: # pylint: disable=broad-except diff --git a/functest/opnfv_tests/openstack/api/connection_check.py b/functest/opnfv_tests/openstack/api/connection_check.py index 48d06211b..eaf9767c0 100644 --- a/functest/opnfv_tests/openstack/api/connection_check.py +++ b/functest/opnfv_tests/openstack/api/connection_check.py @@ -16,15 +16,27 @@ import os_client_config import shade from xtesting.core import testcase +from functest.utils import env +from functest.utils import functest_utils + class ConnectionCheck(testcase.TestCase): """Perform simplest queries""" __logger = logging.getLogger(__name__) + func_list = [ + "get_network_extensions", "list_aggregates", "list_domains", + "list_endpoints", "list_floating_ip_pools", "list_floating_ips", + "list_hypervisors", "list_keypairs", "list_networks", "list_ports", + "list_role_assignments", "list_roles", "list_routers", "list_servers", + "list_subnets"] + def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'connection_check' - super(ConnectionCheck, self).__init__(**kwargs) + super().__init__(**kwargs) + self.output_log_name = 'functest.log' + self.output_debug_log_name = 'functest.debug.log' try: cloud_config = os_client_config.get_config() self.cloud = shade.OpenStackCloud(cloud_config=cloud_config) @@ -38,19 +50,20 @@ class ConnectionCheck(testcase.TestCase): try: assert self.cloud self.start_time = time.time() - for func in ["get_network_extensions", - "list_aggregates", "list_domains", "list_endpoints", - "list_floating_ip_pools", "list_floating_ips", - "list_hypervisors", "list_keypairs", "list_networks", - "list_ports", "list_role_assignments", "list_roles", - "list_routers", "list_servers", "list_services", - "list_subnets"]: + self.__logger.debug( + "list_services: %s", functest_utils.list_services(self.cloud)) + if env.get('NO_TENANT_NETWORK').lower() == 'true': + self.func_list.remove("list_floating_ip_pools") + self.func_list.remove("list_floating_ips") + self.func_list.remove("list_routers") + for func in self.func_list: self.__logger.debug( "%s: %s", func, getattr(self.cloud, func)()) data = self.cloud._network_client.get("/service-providers.json") self.__logger.debug( "list_service_providers: %s", self.cloud._get_and_munchify('service_providers', data)) + functest_utils.get_openstack_version(self.cloud) self.result = 100 status = testcase.TestCase.EX_OK except Exception: # pylint: disable=broad-except diff --git a/functest/opnfv_tests/openstack/barbican/barbican.py b/functest/opnfv_tests/openstack/barbican/barbican.py index 7b1bb24f7..706304bbf 100644 --- a/functest/opnfv_tests/openstack/barbican/barbican.py +++ b/functest/opnfv_tests/openstack/barbican/barbican.py @@ -9,8 +9,6 @@ # pylint: disable=missing-docstring -import logging - from six.moves import configparser from functest.opnfv_tests.openstack.tempest import tempest @@ -18,10 +16,8 @@ from functest.opnfv_tests.openstack.tempest import tempest class Barbican(tempest.TempestCommon): - __logger = logging.getLogger(__name__) - def configure(self, **kwargs): - super(Barbican, self).configure(**kwargs) + super().configure(**kwargs) rconfig = configparser.RawConfigParser() rconfig.read(self.conf_file) if not rconfig.has_section('auth'): @@ -36,6 +32,6 @@ class Barbican(tempest.TempestCommon): if not rconfig.has_section('image-feature-enabled'): rconfig.add_section('image-feature-enabled') rconfig.set('image-feature-enabled', 'api_v1', False) - with open(self.conf_file, 'w') as config_file: + with open(self.conf_file, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) self.backup_tempest_config(self.conf_file, self.res_dir) diff --git a/functest/opnfv_tests/openstack/cinder/cinder_test.py b/functest/opnfv_tests/openstack/cinder/cinder_test.py index bbed9a64f..7d8c0a0bd 100644 --- a/functest/opnfv_tests/openstack/cinder/cinder_test.py +++ b/functest/opnfv_tests/openstack/cinder/cinder_test.py @@ -35,7 +35,7 @@ class CinderCheck(singlevm.SingleVm2): """Initialize testcase.""" if "case_name" not in kwargs: kwargs["case_name"] = "cinder_test" - super(CinderCheck, self).__init__(**kwargs) + super().__init__(**kwargs) self.logger = logging.getLogger(__name__) self.vm2 = None self.fip2 = None @@ -52,14 +52,14 @@ class CinderCheck(singlevm.SingleVm2): return self._write_data() or self._read_data() def prepare(self): - super(CinderCheck, self).prepare() + super().prepare() self.vm2 = self.boot_vm( - '{}-vm2_{}'.format(self.case_name, self.guid), + f'{self.case_name}-vm2_{self.guid}', key_name=self.keypair.id, security_groups=[self.sec.id]) (self.fip2, self.ssh2) = self.connect(self.vm2) self.volume = self.cloud.create_volume( - name='{}-volume_{}'.format(self.case_name, self.guid), size='2', + name=f'{self.case_name}-volume_{self.guid}', size='2', timeout=self.volume_timeout, wait=True) def _write_data(self): @@ -76,9 +76,11 @@ class CinderCheck(singlevm.SingleVm2): return testcase.TestCase.EX_RUN_ERROR self.logger.debug("ssh: %s", self.ssh) (_, stdout, stderr) = self.ssh.exec_command( - "sh ~/write_data.sh {}".format(env.get('VOLUME_DEVICE_NAME'))) - self.logger.debug("volume_write stdout: %s", stdout.read()) - self.logger.debug("volume_write stderr: %s", stderr.read()) + f"sh ~/write_data.sh {env.get('VOLUME_DEVICE_NAME')}") + self.logger.debug( + "volume_write stdout: %s", stdout.read().decode("utf-8")) + self.logger.debug( + "volume_write stderr: %s", stderr.read().decode("utf-8")) # Detach volume from VM 1 self.logger.info("Detach volume from VM 1") self.cloud.detach_volume( @@ -102,9 +104,11 @@ class CinderCheck(singlevm.SingleVm2): return testcase.TestCase.EX_RUN_ERROR self.logger.debug("ssh: %s", self.ssh2) (_, stdout, stderr) = self.ssh2.exec_command( - "sh ~/read_data.sh {}".format(env.get('VOLUME_DEVICE_NAME'))) - self.logger.debug("read volume stdout: %s", stdout.read()) - self.logger.debug("read volume stderr: %s", stderr.read()) + f"sh ~/read_data.sh {env.get('VOLUME_DEVICE_NAME')}") + self.logger.debug( + "read volume stdout: %s", stdout.read().decode("utf-8")) + self.logger.debug( + "read volume stderr: %s", stderr.read().decode("utf-8")) self.logger.info("Detach volume from VM 2") self.cloud.detach_volume( self.vm2, self.volume, timeout=self.volume_timeout) @@ -120,4 +124,4 @@ class CinderCheck(singlevm.SingleVm2): self.cloud.delete_floating_ip(self.fip2.id) if self.volume: self.cloud.delete_volume(self.volume.id) - super(CinderCheck, self).clean() + super().clean() diff --git a/functest/opnfv_tests/openstack/cinder/write_data.sh b/functest/opnfv_tests/openstack/cinder/write_data.sh index 6689309b9..16845ba31 100644 --- a/functest/opnfv_tests/openstack/cinder/write_data.sh +++ b/functest/opnfv_tests/openstack/cinder/write_data.sh @@ -15,7 +15,7 @@ echo "VOL_DEV_NAME: $VOL_DEV_NAME" echo "$(lsblk -l -o NAME)" if [ ! -z $(lsblk -l -o NAME | grep $VOL_DEV_NAME) ]; then - sudo /usr/sbin/mkfs.ext4 -F /dev/$VOL_DEV_NAME + sudo mkfs.ext4 -F /dev/$VOL_DEV_NAME sudo mount /dev/$VOL_DEV_NAME $DEST sudo touch $DEST/new_data if [ -f $DEST/new_data ]; then diff --git a/functest/opnfv_tests/openstack/patrole/patrole.py b/functest/opnfv_tests/openstack/patrole/patrole.py index 9bd877b60..88c42f269 100644 --- a/functest/opnfv_tests/openstack/patrole/patrole.py +++ b/functest/opnfv_tests/openstack/patrole/patrole.py @@ -9,8 +9,6 @@ # pylint: disable=missing-docstring -import logging - from six.moves import configparser from functest.opnfv_tests.openstack.tempest import tempest @@ -18,23 +16,13 @@ from functest.opnfv_tests.openstack.tempest import tempest class Patrole(tempest.TempestCommon): - __logger = logging.getLogger(__name__) - def configure(self, **kwargs): - super(Patrole, self).configure(**kwargs) + super().configure(**kwargs) rconfig = configparser.RawConfigParser() rconfig.read(self.conf_file) - rconfig.add_section('rbac') - rconfig.set('rbac', 'enable_rbac', True) - rconfig.set('rbac', 'rbac_test_role', kwargs.get('role', 'admin')) - with open(self.conf_file, 'w') as config_file: + if not rconfig.has_section('rbac'): + rconfig.add_section('rbac') + rconfig.set('rbac', 'rbac_test_roles', kwargs.get('roles', 'admin')) + with open(self.conf_file, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) self.backup_tempest_config(self.conf_file, self.res_dir) - - def run(self, **kwargs): - for exclude in kwargs.get('excludes', []): - kwargs['mode'] = "{}(?!.*{})".format( - kwargs.get('mode', ''), exclude) - kwargs['mode'] = '{}(?=patrole_tempest_plugin.tests.api.({}))'.format( - kwargs['mode'], '|'.join(kwargs.get('includes', []))) - return super(Patrole, self).run(**kwargs) diff --git a/functest/opnfv_tests/openstack/rally/blacklist.yaml b/functest/opnfv_tests/openstack/rally/blacklist.yaml index 628a418ad..e16b83ba6 100644 --- a/functest/opnfv_tests/openstack/rally/blacklist.yaml +++ b/functest/opnfv_tests/openstack/rally/blacklist.yaml @@ -1,13 +1,5 @@ --- scenario: - - - scenarios: - - '^os-' # all scenarios - tests: - # Following test occasionally fails due to race condition issue on - # quota manipulation in nova. - # Ref: https://bugs.launchpad.net/nova/+bug/1552622 - - 'Quotas.nova_update_and_delete' functionality: - @@ -32,7 +24,17 @@ functionality: functions: - no_floating_ip tests: + - HeatStacks.create_and_delete_stack + - NovaServers.boot_and_associate_floating_ip + - NovaServers.boot_server_and_list_interfaces - NovaServers.boot_server_associate_and_dissociate_floating_ip - NeutronNetworks.create_and_delete_floating_ips - NeutronNetworks.create_and_list_floating_ips - NeutronNetworks.associate_and_dissociate_floating_ips + - VMTasks.dd_load_test + - NeutronNetworks.create_and_delete_routers + - NeutronNetworks.create_and_list_routers + - NeutronNetworks.create_and_show_routers + - NeutronNetworks.create_and_update_routers + - NeutronNetworks.set_and_clear_router_gateway + - Quotas.neutron_update diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py index 22b508afa..3d897e25d 100644 --- a/functest/opnfv_tests/openstack/rally/rally.py +++ b/functest/opnfv_tests/openstack/rally/rally.py @@ -25,6 +25,7 @@ import time import pkg_resources import prettytable from ruamel.yaml import YAML +import six from six.moves import configparser from xtesting.core import testcase import yaml @@ -32,6 +33,7 @@ import yaml from functest.core import singlevm from functest.utils import config from functest.utils import env +from functest.utils import functest_utils LOGGER = logging.getLogger(__name__) @@ -41,7 +43,8 @@ class RallyBase(singlevm.VmReady2): # pylint: disable=too-many-instance-attributes, too-many-public-methods stests = ['authenticate', 'glance', 'cinder', 'gnocchi', 'heat', - 'keystone', 'neutron', 'nova', 'quotas', 'swift', 'barbican'] + 'keystone', 'neutron', 'nova', 'quotas', 'swift', 'barbican', + 'vm'] rally_conf_path = "/etc/rally/rally.conf" rally_aar4_patch_path = pkg_resources.resource_filename( @@ -66,11 +69,12 @@ class RallyBase(singlevm.VmReady2): visibility = 'public' shared_network = True - allow_no_fip = True + task_timeout = 3600 + username = 'cirros' def __init__(self, **kwargs): """Initialize RallyBase object.""" - super(RallyBase, self).__init__(**kwargs) + super().__init__(**kwargs) assert self.orig_cloud assert self.project if self.orig_cloud.get_role("admin"): @@ -92,7 +96,6 @@ class RallyBase(singlevm.VmReady2): self.smoke = None self.start_time = None self.result = None - self.details = None self.compute_cnt = 0 self.flavor_alt = None self.tests = [] @@ -119,6 +122,7 @@ class RallyBase(singlevm.VmReady2): task_args['volume_version'] = self.volume_version task_args['volume_service_type'] = self.volume_service_type task_args['block_migration'] = env.get("BLOCK_MIGRATION").lower() + task_args['username'] = self.username if self.ext_net: task_args['floating_network'] = str(self.ext_net.name) @@ -128,13 +132,20 @@ class RallyBase(singlevm.VmReady2): if self.network: task_args['netid'] = str(self.network.id) else: - task_args['netid'] = '' + LOGGER.warning( + 'No tenant network created. ' + 'Trying EXTERNAL_NETWORK as a fallback') + if env.get("EXTERNAL_NETWORK"): + network = self.cloud.get_network(env.get("EXTERNAL_NETWORK")) + task_args['netid'] = str(network.id) if network else '' + else: + task_args['netid'] = '' return task_args def _prepare_test_list(self, test_name): """Build the list of test cases to be executed.""" - test_yaml_file_name = 'opnfv-{}.yaml'.format(test_name) + test_yaml_file_name = f'opnfv-{test_name}.yaml' scenario_file_name = os.path.join(self.rally_scenario_dir, test_yaml_file_name) @@ -143,8 +154,8 @@ class RallyBase(singlevm.VmReady2): test_yaml_file_name) if not os.path.exists(scenario_file_name): - raise Exception("The scenario '%s' does not exist." - % scenario_file_name) + raise Exception( + f"The scenario '{scenario_file_name}' does not exist.") LOGGER.debug('Scenario fetched from : %s', scenario_file_name) test_file_name = os.path.join(self.temp_dir, test_yaml_file_name) @@ -163,14 +174,15 @@ class RallyBase(singlevm.VmReady2): cmd = ("rally deployment list | awk '/" + getattr(config.CONF, 'rally_deployment_name') + "/ {print $2}'") - proc = subprocess.Popen(cmd, shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - deployment_uuid = proc.stdout.readline().rstrip() + with subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) as proc: + deployment_uuid = proc.stdout.readline().rstrip() return deployment_uuid.decode("utf-8") @staticmethod def create_rally_deployment(environ=None): + # pylint: disable=unexpected-keyword-arg """Create new rally deployment""" # set the architecture to default pod_arch = env.get("POD_ARCH") @@ -178,7 +190,9 @@ class RallyBase(singlevm.VmReady2): if pod_arch and pod_arch in arch_filter: LOGGER.info("Apply aarch64 specific to rally config...") - with open(RallyBase.rally_aar4_patch_path, "r") as pfile: + with open( + RallyBase.rally_aar4_patch_path, "r", + encoding='utf-8') as pfile: rally_patch_conf = pfile.read() for line in fileinput.input(RallyBase.rally_conf_path): @@ -216,7 +230,7 @@ class RallyBase(singlevm.VmReady2): rconfig.add_section('openstack') rconfig.set( 'openstack', 'keystone_default_role', env.get("NEW_USER_ROLE")) - with open(rally_conf, 'w') as config_file: + with open(rally_conf, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) @staticmethod @@ -227,24 +241,21 @@ class RallyBase(singlevm.VmReady2): rconfig.read(rally_conf) if rconfig.has_option('openstack', 'keystone_default_role'): rconfig.remove_option('openstack', 'keystone_default_role') - with open(rally_conf, 'w') as config_file: + with open(rally_conf, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) @staticmethod - def get_task_id(cmd_raw): + def get_task_id(tag): """ Get task id from command rally result. - :param cmd_raw: + :param tag: :return: task_id as string """ - taskid_re = re.compile('^Task +(.*): started$') - for line in cmd_raw.splitlines(True): - line = line.strip() - match = taskid_re.match(line.decode("utf-8")) - if match: - return match.group(1) - return None + cmd = ["rally", "task", "list", "--tag", tag, "--uuids-only"] + output = subprocess.check_output(cmd).decode("utf-8").rstrip() + LOGGER.info("%s: %s", " ".join(cmd), output) + return output @staticmethod def task_succeed(json_raw): @@ -282,7 +293,9 @@ class RallyBase(singlevm.VmReady2): """Exclude scenario.""" black_tests = [] try: - with open(RallyBase.blacklist_file, 'r') as black_list_file: + with open( + RallyBase.blacklist_file, 'r', + encoding='utf-8') as black_list_file: black_list_yaml = yaml.safe_load(black_list_file) deploy_scenario = env.get('DEPLOY_SCENARIO') @@ -326,7 +339,9 @@ class RallyBase(singlevm.VmReady2): func_list = [] try: - with open(RallyBase.blacklist_file, 'r') as black_list_file: + with open( + RallyBase.blacklist_file, 'r', + encoding='utf-8') as black_list_file: black_list_yaml = yaml.safe_load(black_list_file) if env.get('BLOCK_MIGRATION').lower() == 'true': @@ -353,31 +368,25 @@ class RallyBase(singlevm.VmReady2): def apply_blacklist(self, case_file_name, result_file_name): """Apply blacklist.""" LOGGER.debug("Applying blacklist...") - cases_file = open(case_file_name, 'r') - result_file = open(result_file_name, 'w') - - black_tests = list(set(self.excl_func() + - self.excl_scenario())) - - if black_tests: - LOGGER.debug("Blacklisted tests: %s", str(black_tests)) - - include = True - for cases_line in cases_file: - if include: - for black_tests_line in black_tests: - if re.search(black_tests_line, - cases_line.strip().rstrip(':')): - include = False - break + with open(case_file_name, 'r', encoding='utf-8') as cases_file, open( + result_file_name, 'w', encoding='utf-8') as result_file: + black_tests = list(set(self.excl_func() + self.excl_scenario())) + if black_tests: + LOGGER.debug("Blacklisted tests: %s", str(black_tests)) + + include = True + for cases_line in cases_file: + if include: + for black_tests_line in black_tests: + if re.search(black_tests_line, + cases_line.strip().rstrip(':')): + include = False + break + else: + result_file.write(str(cases_line)) else: - result_file.write(str(cases_line)) - else: - if cases_line.isspace(): - include = True - - cases_file.close() - result_file.close() + if cases_line.isspace(): + include = True @staticmethod def file_is_empty(file_name): @@ -405,7 +414,7 @@ class RallyBase(singlevm.VmReady2): LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) # save report as JSON - report_json_name = '{}.json'.format(test_name) + report_json_name = f'{test_name}.json' report_json_dir = os.path.join(self.results_dir, report_json_name) cmd = (["rally", "task", "report", "--json", "--uuid", task_id, "--out", report_json_dir]) @@ -413,7 +422,8 @@ class RallyBase(singlevm.VmReady2): output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) LOGGER.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - json_results = open(report_json_dir).read() + with open(report_json_dir, encoding='utf-8') as json_file: + json_results = json_file.read() self._append_summary(json_results, test_name) # parse JSON operation result @@ -426,15 +436,17 @@ class RallyBase(singlevm.VmReady2): """Run a task.""" LOGGER.info('Starting test scenario "%s" ...', test_name) LOGGER.debug('running command: %s', self.run_cmd) - proc = subprocess.Popen(self.run_cmd, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - output = proc.communicate()[0] - - task_id = self.get_task_id(output) + if six.PY3: + subprocess.call( + self.run_cmd, timeout=self.task_timeout, + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + else: + with open(os.devnull, 'wb') as devnull: + subprocess.call(self.run_cmd, stdout=devnull, stderr=devnull) + task_id = self.get_task_id(test_name) LOGGER.debug('task_id : %s', task_id) - if task_id is None: + if not task_id: LOGGER.error("Failed to retrieve task_id") - LOGGER.error("Result:\n%s", output.decode("utf-8")) raise Exception("Failed to retrieve task id") self._save_results(test_name, task_id) @@ -486,7 +498,7 @@ class RallyBase(singlevm.VmReady2): if test in self.stests: self.tests.append(test) else: - raise Exception("Test name '%s' is invalid" % test) + raise Exception(f"Test name '{test}' is invalid") if not os.path.exists(self.task_dir): os.makedirs(self.task_dir) @@ -494,27 +506,25 @@ class RallyBase(singlevm.VmReady2): task = os.path.join(self.rally_dir, 'task.yaml') if not os.path.exists(task): LOGGER.error("Task file '%s' does not exist.", task) - raise Exception("Task file '{}' does not exist.". - format(task)) + raise Exception(f"Task file '{task}' does not exist.") self.task_file = os.path.join(self.task_dir, 'task.yaml') shutil.copyfile(task, self.task_file) task_macro = os.path.join(self.rally_dir, 'macro') if not os.path.exists(task_macro): LOGGER.error("Task macro dir '%s' does not exist.", task_macro) - raise Exception("Task macro dir '{}' does not exist.". - format(task_macro)) + raise Exception(f"Task macro dir '{task_macro}' does not exist.") macro_dir = os.path.join(self.task_dir, 'macro') if os.path.exists(macro_dir): shutil.rmtree(macro_dir) shutil.copytree(task_macro, macro_dir) self.update_keystone_default_role() - self.compute_cnt = len(self.cloud.list_hypervisors()) + self.compute_cnt = self.count_hypervisors() self.network_extensions = self.cloud.get_network_extensions() self.flavor_alt = self.create_flavor_alt() self.services = [service.name for service in - self.cloud.list_services()] + functest_utils.list_services(self.cloud)] LOGGER.debug("flavor: %s", self.flavor_alt) @@ -524,7 +534,8 @@ class RallyBase(singlevm.VmReady2): if self.file_is_empty(file_name): LOGGER.info('No tests for scenario "%s"', test_name) return False - self.run_cmd = (["rally", "task", "start", "--abort-on-sla-failure", + self.run_cmd = (["rally", "task", "start", "--tag", test_name, + "--abort-on-sla-failure", "--task", self.task_file, "--task-args", str(self.build_task_args(test_name))]) return True @@ -563,7 +574,7 @@ class RallyBase(singlevm.VmReady2): success_avg = 100 * item['nb_success'] / item['nb_tests'] except ZeroDivisionError: success_avg = 0 - success_str = str("{:0.2f}".format(success_avg)) + '%' + success_str = f"{success_avg:0.2f}%" duration_str = time.strftime("%H:%M:%S", time.gmtime(item['overall_duration'])) res_table.add_row([item['test_name'], duration_str, @@ -581,7 +592,7 @@ class RallyBase(singlevm.VmReady2): self.result = 100 * total_nb_success / total_nb_tests except ZeroDivisionError: self.result = 100 - success_rate = "{:0.2f}".format(self.result) + success_rate = f"{self.result:0.2f}" success_rate_str = str(success_rate) + '%' res_table.add_row(["", "", "", ""]) res_table.add_row(["TOTAL:", total_duration_str, total_nb_tests, @@ -591,10 +602,10 @@ class RallyBase(singlevm.VmReady2): LOGGER.info("Rally '%s' success_rate is %s%% in %s/%s modules", self.case_name, success_rate, nb_modules, len(self.summary)) - payload.append({'summary': {'duration': total_duration, - 'nb tests': total_nb_tests, - 'nb success': success_rate}}) - self.details = payload + self.details['summary'] = {'duration': total_duration, + 'nb tests': total_nb_tests, + 'nb success': success_rate} + self.details["modules"] = payload @staticmethod def export_task(file_name, export_type="html"): @@ -636,7 +647,7 @@ class RallyBase(singlevm.VmReady2): self.clean_rally_logs() if self.flavor_alt: self.orig_cloud.delete_flavor(self.flavor_alt.id) - super(RallyBase, self).clean() + super().clean() def is_successful(self): """The overall result of the test.""" @@ -644,7 +655,7 @@ class RallyBase(singlevm.VmReady2): if item['task_status'] is False: return testcase.TestCase.EX_TESTCASE_FAILED - return super(RallyBase, self).is_successful() + return super().is_successful() @staticmethod def update_rally_logs(res_dir, rally_conf='/etc/rally/rally.conf'): @@ -657,7 +668,7 @@ class RallyBase(singlevm.VmReady2): rconfig.set('DEFAULT', 'use_stderr', False) rconfig.set('DEFAULT', 'log-file', 'rally.log') rconfig.set('DEFAULT', 'log_dir', res_dir) - with open(rally_conf, 'w') as config_file: + with open(rally_conf, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) @staticmethod @@ -673,14 +684,14 @@ class RallyBase(singlevm.VmReady2): rconfig.remove_option('DEFAULT', 'log-file') if rconfig.has_option('DEFAULT', 'log_dir'): rconfig.remove_option('DEFAULT', 'log_dir') - with open(rally_conf, 'w') as config_file: + with open(rally_conf, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) def run(self, **kwargs): """Run testcase.""" self.start_time = time.time() try: - assert super(RallyBase, self).run( + assert super().run( **kwargs) == testcase.TestCase.EX_OK self.update_rally_logs(self.res_dir) self.create_rally_deployment(environ=self.project.get_environ()) @@ -688,9 +699,9 @@ class RallyBase(singlevm.VmReady2): self.run_tests(**kwargs) self._generate_report() self.export_task( - "{}/{}.html".format(self.results_dir, self.case_name)) + f"{self.results_dir}/{self.case_name}.html") self.export_task( - "{}/{}.xml".format(self.results_dir, self.case_name), + f"{self.results_dir}/{self.case_name}.xml", export_type="junit-xml") res = testcase.TestCase.EX_OK except Exception: # pylint: disable=broad-except @@ -708,7 +719,7 @@ class RallySanity(RallyBase): """Initialize RallySanity object.""" if "case_name" not in kwargs: kwargs["case_name"] = "rally_sanity" - super(RallySanity, self).__init__(**kwargs) + super().__init__(**kwargs) self.smoke = True self.scenario_dir = os.path.join(self.rally_scenario_dir, 'sanity') @@ -716,11 +727,13 @@ class RallySanity(RallyBase): class RallyFull(RallyBase): """Rally full testcase implementation.""" + task_timeout = 7200 + def __init__(self, **kwargs): """Initialize RallyFull object.""" if "case_name" not in kwargs: kwargs["case_name"] = "rally_full" - super(RallyFull, self).__init__(**kwargs) + super().__init__(**kwargs) self.smoke = False self.scenario_dir = os.path.join(self.rally_scenario_dir, 'full') @@ -729,26 +742,27 @@ class RallyJobs(RallyBase): """Rally OpenStack CI testcase implementation.""" stests = ["neutron"] + task_timeout = 7200 def __init__(self, **kwargs): """Initialize RallyJobs object.""" if "case_name" not in kwargs: kwargs["case_name"] = "rally_jobs" - super(RallyJobs, self).__init__(**kwargs) + super().__init__(**kwargs) self.task_file = os.path.join(self.rally_dir, 'rally_jobs.yaml') self.task_yaml = None def prepare_run(self, **kwargs): """Create resources needed by test scenarios.""" - super(RallyJobs, self).prepare_run(**kwargs) - with open(os.path.join(self.rally_dir, - 'rally_jobs.yaml'), 'r') as task_file: + super().prepare_run(**kwargs) + with open( + os.path.join(self.rally_dir, 'rally_jobs.yaml'), + 'r', encoding='utf-8') as task_file: self.task_yaml = yaml.safe_load(task_file) for task in self.task_yaml: if task not in self.tests: - raise Exception("Test '%s' not in '%s'" % - (task, self.tests)) + raise Exception(f"Test '{task}' not in '{self.tests}'") def apply_blacklist(self, case_file_name, result_file_name): # pylint: disable=too-many-branches @@ -760,7 +774,7 @@ class RallyJobs(RallyBase): LOGGER.debug("Blacklisted tests: %s", str(black_tests)) template = YAML(typ='jinja2') - with open(case_file_name, 'r') as fname: + with open(case_file_name, 'r', encoding='utf-8') as fname: cases = template.load(fname) if cases.get("version", 1) == 1: # scenarios in dictionary @@ -790,7 +804,7 @@ class RallyJobs(RallyBase): cases['subtasks'].pop(sind) break - with open(result_file_name, 'w') as fname: + with open(result_file_name, 'w', encoding='utf-8') as fname: template.dump(cases, fname) def build_task_args(self, test_name): @@ -804,40 +818,21 @@ class RallyJobs(RallyBase): task_args['flavor_name'] = str(self.flavor.name) return task_args - @staticmethod - def _remove_plugins_extra(): - inst_dir = getattr(config.CONF, 'dir_rally_inst') - try: - shutil.rmtree(os.path.join(inst_dir, 'plugins')) - shutil.rmtree(os.path.join(inst_dir, 'extra')) - except Exception: # pylint: disable=broad-except - pass - def prepare_task(self, test_name): """Prepare resources for test run.""" - self._remove_plugins_extra() jobs_dir = os.path.join( getattr(config.CONF, 'dir_rally_data'), test_name, 'rally-jobs') - inst_dir = getattr(config.CONF, 'dir_rally_inst') - shutil.copytree(os.path.join(jobs_dir, 'plugins'), - os.path.join(inst_dir, 'plugins')) - shutil.copytree(os.path.join(jobs_dir, 'extra'), - os.path.join(inst_dir, 'extra')) - task_name = self.task_yaml.get(test_name).get("task") task = os.path.join(jobs_dir, task_name) if not os.path.exists(task): - raise Exception("The scenario '%s' does not exist." % task) + raise Exception(f"The scenario '{task}' does not exist.") LOGGER.debug('Scenario fetched from : %s', task) if not os.path.exists(self.temp_dir): os.makedirs(self.temp_dir) task_file_name = os.path.join(self.temp_dir, task_name) self.apply_blacklist(task, task_file_name) - self.run_cmd = (["rally", "task", "start", "--task", task_file_name, + self.run_cmd = (["rally", "task", "start", "--tag", test_name, + "--task", task_file_name, "--task-args", str(self.build_task_args(test_name))]) return True - - def clean(self): - self._remove_plugins_extra() - super(RallyJobs, self).clean() diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml index 4b3c22ebd..7abeeac68 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml +++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-cinder.yaml @@ -348,20 +348,6 @@ sla: {{ no_failures_sla() }} - CinderVolumeTypes.create_and_update_volume_type: - - - args: - description: "test" - update_description: "test update" - context: - {{ user_context(tenants_amount, users_amount, use_existing_users) }} - api_versions: - {{ volume_service(version=volume_version, service_type=volume_service_type) }} - runner: - {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} - sla: - {{ no_failures_sla() }} - CinderVolumeTypes.create_volume_type_and_encryption_type: - args: @@ -378,16 +364,3 @@ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} sla: {{ no_failures_sla() }} - - CinderVolumeTypes.create_volume_type_add_and_list_type_access: - - - args: - description: "rally tests creating types" - context: - {{ user_context(tenants_amount, users_amount, use_existing_users) }} - api_versions: - {{ volume_service(version=volume_version, service_type=volume_service_type) }} - runner: - {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} - sla: - {{ no_failures_sla() }} diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml index dfc1fc156..993b83ff7 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml +++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-glance.yaml @@ -36,8 +36,9 @@ flavor: name: {{ flavor_name }} number_instances: 2 - nics: - - net-id: {{ netid }} + boot_server_kwargs: + nics: + - net-id: {{ netid }} context: {{ user_context(tenants_amount, users_amount, use_existing_users) }} quotas: diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml index b8b1b9b6b..b2248d499 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml +++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-neutron.yaml @@ -150,8 +150,6 @@ subnets_per_network: 1 context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - router: {} quotas: neutron: network: -1 diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml index 8ef5b6cdc..210591f9b 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml +++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-nova.yaml @@ -39,9 +39,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova() }} @@ -59,9 +56,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova() }} @@ -80,9 +74,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova() }} @@ -104,9 +95,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova() }} @@ -124,9 +112,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova() }} @@ -216,7 +201,7 @@ - args: {{ vm_params(image_name, flavor_name) }} - size: 10 + size: 1 block_migration: {{ block_migration }} boot_server_kwargs: nics: @@ -251,14 +236,11 @@ - args: {{ vm_params(image_name, flavor_name) }} - server_kwargs: + boot_server_kwargs: nics: - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova(keypairs=true) }} @@ -277,9 +259,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_volumes() }} {{ unlimited_neutron() }} @@ -301,9 +280,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova() }} @@ -395,8 +371,7 @@ - args: {{ vm_params(image_name, flavor_name) }} - create_floating_ip_args: - ext_network: {{ floating_network }} + floating_network: {{ floating_network }} nics: - net-id: {{ netid }} context: @@ -412,8 +387,7 @@ - args: {{ vm_params(image_name, flavor_name) }} - create_floating_ip_args: - ext_network: {{ floating_network }} + floating_network: {{ floating_network }} nics: - net-id: {{ netid }} context: diff --git a/functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml b/functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml index 3f0cf0840..dcb007c50 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml +++ b/functest/opnfv_tests/openstack/rally/scenario/opnfv-quotas.yaml @@ -35,17 +35,6 @@ sla: {{ no_failures_sla() }} - Quotas.nova_update_and_delete: - - - args: - max_quota: 1024 - context: - {{ user_context(tenants_amount, users_amount, use_existing_users) }} - runner: - {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} - sla: - {{ no_failures_sla() }} - Quotas.nova_update: - args: diff --git a/functest/opnfv_tests/openstack/rally/scenario/opnfv-swift.yaml b/functest/opnfv_tests/openstack/rally/scenario/opnfv-swift.yaml index ccbe7bed3..66d7cd24d 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/opnfv-swift.yaml +++ b/functest/opnfv_tests/openstack/rally/scenario/opnfv-swift.yaml @@ -4,7 +4,7 @@ objects_per_container: 2 object_size: 5120 runner: - {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} + {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }} context: {{ user_context(tenants_amount, users_amount, use_existing_users) }} roles: @@ -15,7 +15,7 @@ SwiftObjects.list_objects_in_containers: - runner: - {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} + {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }} context: {{ user_context(tenants_amount, users_amount, use_existing_users) }} roles: @@ -33,7 +33,7 @@ objects_per_container: 5 object_size: 1024 runner: - {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} + {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }} context: {{ user_context(tenants_amount, users_amount, use_existing_users) }} roles: @@ -47,7 +47,7 @@ objects_per_container: 5 object_size: 102400 runner: - {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} + {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }} context: {{ user_context(tenants_amount, users_amount, use_existing_users) }} roles: @@ -58,13 +58,13 @@ SwiftObjects.list_and_download_objects_in_containers: - runner: - {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }} + {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }} context: {{ user_context(tenants_amount, users_amount, use_existing_users) }} roles: - "admin" swift_objects: - containers_per_tenant: 2 + containers_per_tenant: 1 objects_per_container: 5 object_size: 10240 sla: diff --git a/functest/opnfv_tests/openstack/rally/scenario/opnfv-vm.yaml b/functest/opnfv_tests/openstack/rally/scenario/opnfv-vm.yaml new file mode 100644 index 000000000..3aa8ac8e5 --- /dev/null +++ b/functest/opnfv_tests/openstack/rally/scenario/opnfv-vm.yaml @@ -0,0 +1,19 @@ + VMTasks.dd_load_test: + - + args: + flavor: + name: {{ flavor_name }} + image: + name: {{ image_name }} + nics: + - net-id: {{ netid }} + floating_network: {{ floating_network }} + force_delete: false + username: {{ username }} + runner: + {{ constant_runner(concurrency=1, times=iterations, is_smoke=smoke) }} + context: + {{ user_context(tenants_amount, users_amount, use_existing_users) }} + network: {} + sla: + {{ no_failures_sla() }} diff --git a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml index 1b61762f9..279e81439 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml +++ b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-glance.yaml @@ -36,8 +36,9 @@ flavor: name: {{ flavor_name }} number_instances: 2 - nics: - - net-id: {{ netid }} + boot_server_kwargs: + nics: + - net-id: {{ netid }} context: {{ user_context(tenants_amount, users_amount, use_existing_users) }} quotas: diff --git a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml index 935f3841a..1fbfccb5a 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml +++ b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-nova.yaml @@ -15,7 +15,7 @@ - args: {{ vm_params(image_name, flavor_name) }} - size: 10 + size: 1 block_migration: {{ block_migration }} boot_server_kwargs: nics: @@ -50,14 +50,11 @@ - args: {{ vm_params(image_name, flavor_name) }} - server_kwargs: + boot_server_kwargs: nics: - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova(keypairs=true) }} @@ -76,9 +73,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_volumes() }} {{ unlimited_neutron() }} @@ -100,9 +94,6 @@ - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} - network: - networks_per_tenant: 1 - start_cidr: "100.1.0.0/25" quotas: {{ unlimited_neutron() }} {{ unlimited_nova() }} @@ -128,7 +119,8 @@ - args: {{ vm_params(image_name, flavor_name) }} - auto_assign_nic: true + nics: + - net-id: {{ netid }} context: {% call user_context(tenants_amount, users_amount, use_existing_users) %} network: {} @@ -142,8 +134,7 @@ - args: {{ vm_params(image_name, flavor_name) }} - create_floating_ip_args: - ext_network: {{ floating_network }} + floating_network: {{ floating_network }} nics: - net-id: {{ netid }} context: diff --git a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template index 35b107838..75afb2dbe 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template +++ b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template @@ -7,7 +7,7 @@ parameters: default: public image: type: string - default: cirros-0.4.0-x86_64-uec + default: cirros-0.6.1-x86_64-uec flavor: type: string default: m1.tiny diff --git a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template index 5c9a86b79..9a0f1aa72 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template +++ b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template @@ -4,7 +4,7 @@ parameters: # set all correct defaults for parameters before launch test image: type: string - default: cirros-0.4.0-x86_64-uec + default: cirros-0.5.1-x86_64-uec flavor: type: string default: m1.tiny diff --git a/functest/opnfv_tests/openstack/rally/task.yaml b/functest/opnfv_tests/openstack/rally/task.yaml index 2581765b1..649c04557 100644 --- a/functest/opnfv_tests/openstack/rally/task.yaml +++ b/functest/opnfv_tests/openstack/rally/task.yaml @@ -50,3 +50,7 @@ {% if "barbican" in service_list %} {%- include "var/opnfv-barbican.yaml"-%} {% endif %} + +{% if "vm" in service_list %} +{%- include "var/opnfv-vm.yaml"-%} +{% endif %} diff --git a/functest/opnfv_tests/openstack/refstack/refstack.py b/functest/opnfv_tests/openstack/refstack/refstack.py index faf183f76..87932020b 100644 --- a/functest/opnfv_tests/openstack/refstack/refstack.py +++ b/functest/opnfv_tests/openstack/refstack/refstack.py @@ -26,12 +26,11 @@ class Refstack(tempest.TempestCommon): def _extract_refstack_data(self, refstack_list): yaml_data = "" - with open(refstack_list) as def_file: + with open(refstack_list, encoding='utf-8') as def_file: for line in def_file: try: grp = re.search(r'^([^\[]*)(\[.*\])\n*$', line) - yaml_data = "{}\n{}: {}".format( - yaml_data, grp.group(1), grp.group(2)) + yaml_data = f"{yaml_data}\n{grp.group(1)}: {grp.group(2)}" except Exception: # pylint: disable=broad-except self.__logger.warning("Cannot parse %s", line) return yaml.full_load(yaml_data) @@ -53,8 +52,7 @@ class Refstack(tempest.TempestCommon): for line in output.splitlines(): try: grp = re.search(r'^([^\[]*)(\[.*\])\n*$', line.decode("utf-8")) - yaml_data2 = "{}\n{}: {}".format( - yaml_data2, grp.group(1), grp.group(2)) + yaml_data2 = f"{yaml_data2}\n{grp.group(1)}: {grp.group(2)}" except Exception: # pylint: disable=broad-except self.__logger.warning("Cannot parse %s. skipping it", line) return yaml.full_load(yaml_data2) @@ -62,11 +60,11 @@ class Refstack(tempest.TempestCommon): def generate_test_list(self, **kwargs): refstack_list = os.path.join( getattr(config.CONF, 'dir_refstack_data'), - "{}.txt".format(kwargs.get('target', 'compute'))) + f"{kwargs.get('target', 'compute')}.txt") self.backup_tempest_config(self.conf_file, '/etc') refstack_data = self._extract_refstack_data(refstack_list) tempest_data = self._extract_tempest_data() - with open(self.list, 'w') as ref_file: + with open(self.list, 'w', encoding='utf-8') as ref_file: for key in refstack_data.keys(): try: for data in tempest_data[key]: @@ -75,9 +73,9 @@ class Refstack(tempest.TempestCommon): else: self.__logger.info("%s: ids differ. skipping it", key) continue - ref_file.write("{}{}\n".format( - key, str(tempest_data[key]).replace( - "'", "").replace(", ", ","))) + value = str(tempest_data[key]).replace( + "'", "").replace(", ", ",") + ref_file.write(f"{key}{value}\n") except Exception: # pylint: disable=broad-except self.__logger.info("%s: not found. skipping it", key) continue diff --git a/functest/opnfv_tests/openstack/shaker/shaker.py b/functest/opnfv_tests/openstack/shaker/shaker.py index fd31ea689..275cc3077 100644 --- a/functest/opnfv_tests/openstack/shaker/shaker.py +++ b/functest/opnfv_tests/openstack/shaker/shaker.py @@ -19,6 +19,7 @@ and list of tests to execute. import logging import os +import json import scp from functest.core import singlevm @@ -31,29 +32,32 @@ class Shaker(singlevm.SingleVm2): __logger = logging.getLogger(__name__) - filename = '/home/opnfv/functest/images/shaker-image.qcow2' + filename = '/home/opnfv/functest/images/shaker-image-1.3.4+stretch.qcow2' flavor_ram = 512 flavor_vcpus = 1 flavor_disk = 3 - username = 'ubuntu' + username = 'debian' port = 9000 ssh_connect_loops = 12 create_server_timeout = 300 + check_console_loop = 12 shaker_timeout = '3600' quota_instances = -1 + quota_cores = -1 + check_console_loop = 12 def __init__(self, **kwargs): - super(Shaker, self).__init__(**kwargs) + super().__init__(**kwargs) self.role = None def check_requirements(self): - if len(self.orig_cloud.list_hypervisors()) < 2: + if self.count_hypervisors() < 2: self.__logger.warning("Shaker requires at least 2 hypervisors") self.is_skipped = True self.project.clean() def prepare(self): - super(Shaker, self).prepare() + super().prepare() self.cloud.create_security_group_rule( self.sec.id, port_range_min=self.port, port_range_max=self.port, protocol='tcp', direction='ingress') @@ -85,38 +89,37 @@ class Shaker(singlevm.SingleVm2): domain=self.project.domain.id) self.orig_cloud.set_compute_quotas( self.project.project.name, - instances=self.quota_instances) + instances=self.quota_instances, + cores=self.quota_cores) scpc = scp.SCPClient(self.ssh.get_transport()) scpc.put('/home/opnfv/functest/conf/env_file', remote_path='~/') if os.environ.get('OS_CACERT'): scpc.put(os.environ.get('OS_CACERT'), remote_path='~/os_cacert') + opt = 'export OS_CACERT=~/os_cacert && ' if os.environ.get( + 'OS_CACERT') else '' (_, stdout, stderr) = self.ssh.exec_command( 'source ~/env_file && ' 'export OS_INTERFACE=public && ' - 'export OS_AUTH_URL={} && ' - 'export OS_USERNAME={} && ' - 'export OS_PROJECT_NAME={} && ' - 'export OS_PROJECT_ID={} && ' + f'export OS_AUTH_URL={endpoint} && ' + f'export OS_USERNAME={self.project.user.name} && ' + f'export OS_PROJECT_NAME={self.project.project.name} && ' + f'export OS_PROJECT_ID={self.project.project.id} && ' 'unset OS_TENANT_NAME && ' 'unset OS_TENANT_ID && ' 'unset OS_ENDPOINT_TYPE && ' - 'export OS_PASSWORD={} && ' - '{}' + f'export OS_PASSWORD="{self.project.password}" && ' + f'{opt}' 'env && ' - 'timeout {} shaker --image-name {} --flavor-name {} ' - '--server-endpoint {}:9000 --external-net {} --dns-nameservers {} ' + f'timeout {self.shaker_timeout} shaker --debug ' + f'--image-name {self.image.name} --flavor-name {self.flavor.name} ' + f'--server-endpoint {self.fip.floating_ip_address}:9000 ' + f'--external-net {self.ext_net.id} ' + f"--dns-nameservers {env.get('NAMESERVER')} " '--scenario openstack/full_l2,' 'openstack/full_l3_east_west,' 'openstack/full_l3_north_south,' 'openstack/perf_l3_north_south ' - '--report report.html --output report.json'.format( - endpoint, self.project.user.name, self.project.project.name, - self.project.project.id, self.project.password, - 'export OS_CACERT=~/os_cacert && ' if os.environ.get( - 'OS_CACERT') else '', - self.shaker_timeout, self.image.name, self.flavor.name, - self.fip.floating_ip_address, self.ext_net.id, - env.get('NAMESERVER'))) + '--report report.html --output report.json') self.__logger.info("output:\n%s", stdout.read().decode("utf-8")) self.__logger.info("error:\n%s", stderr.read().decode("utf-8")) if not os.path.exists(self.res_dir): @@ -127,9 +130,18 @@ class Shaker(singlevm.SingleVm2): except scp.SCPException: self.__logger.exception("cannot get report files") return 1 + with open( + os.path.join(self.res_dir, 'report.json'), + encoding='utf-8') as json_file: + data = json.load(json_file) + for value in data["records"].values(): + if value["status"] != "ok": + self.__logger.error( + "%s failed\n%s", value["scenario"], value["stderr"]) + return 1 return stdout.channel.recv_exit_status() def clean(self): - super(Shaker, self).clean() + super().clean() if self.role: self.orig_cloud.delete_role(self.role.id) diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml index 8d7d6eca9..43a77fa3c 100644 --- a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml +++ b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml @@ -4,10 +4,16 @@ - os-ovn-nofeature-ha - os-ovn-nofeature-noha tests: - - neutron_tempest_plugin.api.admin.test_agent_management - neutron_tempest_plugin.api.admin.test_dhcp_agent_scheduler - - patrole_tempest_plugin.tests.api.network.test_agents_rbac + - neutron_tempest_plugin.api.admin.test_ports.PortTestCasesResourceRequest.test_port_resource_request + - neutron_tempest_plugin.api.admin.test_ports.PortTestCasesResourceRequest.test_port_resource_request_empty + - neutron_tempest_plugin.api.admin.test_ports.PortTestCasesResourceRequest.test_port_resource_request_inherited_policy + - neutron_tempest_plugin.api.admin.test_ports.PortTestCasesResourceRequest.test_port_resource_request_no_provider_net_conflict + - neutron_tempest_plugin.api.test_ports.PortsTestJSON.test_create_update_port_with_dns_name + - patrole_tempest_plugin.tests.api.network.test_availability_zones_rbac.AvailabilityZoneExtRbacTest.test_list_availability_zone_rbac + - patrole_tempest_plugin.tests.api.network.test_agents_rbac.DHCPAgentSchedulersRbacTest.test_add_dhcp_agent_to_network + - patrole_tempest_plugin.tests.api.network.test_agents_rbac.DHCPAgentSchedulersRbacTest.test_delete_network_from_dhcp_agent + - patrole_tempest_plugin.tests.api.network.test_agents_rbac.DHCPAgentSchedulersRbacTest.test_list_networks_hosted_by_one_dhcp_agent - patrole_tempest_plugin.tests.api.network.test_networks_rbac.NetworksRbacTest.test_create_network_provider_network_type - patrole_tempest_plugin.tests.api.network.test_networks_rbac.NetworksRbacTest.test_create_network_provider_segmentation_id - - tempest.api.network.admin.test_agent_management - tempest.api.network.admin.test_dhcp_agent_scheduler diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml b/functest/opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml new file mode 100644 index 000000000..e53b577b2 --- /dev/null +++ b/functest/opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml @@ -0,0 +1,15 @@ +--- +- + scenarios: + - os-* + tests: + - neutron_tempest_plugin.api.admin.test_floating_ips_admin_actions.FloatingIPAdminTestJSON.test_associate_floating_ip_with_port_from_another_project + - neutron_tempest_plugin.api.admin.test_quotas.QuotasTest.test_detail_quotas + - neutron_tempest_plugin.api.admin.test_quotas.QuotasTest.test_quotas + - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_floatingip_when_quotas_is_full + - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_network_when_quotas_is_full + - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_port_when_quotas_is_full + - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_router_when_quotas_is_full + - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_security_group_rule_when_quotas_is_full + - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_security_group_when_quotas_is_full + - neutron_tempest_plugin.api.admin.test_quotas_negative.QuotasAdminNegativeTestJSON.test_create_subnet_when_quotas_is_full diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml b/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml index 06c77efd9..0ee4ab613 100644 --- a/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml +++ b/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml @@ -1,26 +1,104 @@ --- compute: + min_microversion: '2.44' max_microversion: latest compute-feature-enabled: - shelve: false - vnc_console: false - cold_migration: false - block_migration_for_live_migration: true + attach_encrypted_volume: false + block_migration_for_live_migration: false + block_migrate_cinder_iscsi: false + change_password: false + cold_migration: true + config_drive: true + console_output: true + disk_config: true + enable_instance_password: true + hostname_fqdn_sanitization: true + interface_attach: true + live_migration: true + live_migrate_back_and_forth: false + metadata_service: true + pause: true + personality: false + rdp_console: false + rescue: true + resize: true + scheduler_available_filters: "AvailabilityZoneFilter,ComputeFilter,\ + ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,\ + ServerGroupAffinityFilter,SameHostFilter,DifferentHostFilter" + serial_console: false + shelve: true + snapshot: true + spice_console: false + suspend: true + swap_volume: false + vnc_console: true + volume_backed_live_migration: false + volume_multiattach: false identity: + auth_version: v3 user_unique_last_password_count: 2 user_lockout_duration: 10 user_lockout_failure_attempts: 2 identity-feature-enabled: + trust: true api_v2: false api_v2_admin: false security_compliance: true + federation: false + external_idp: false + project_tags: true + application_credentials: true + access_rules: true image-feature-enabled: api_v2: true api_v1: false + import_image: false +network-feature-enabled: + port_admin_state_change: true + port_security: true placement: max_microversion: latest +validation: + image_ssh_user: cirros + ssh_timeout: 196 + ip_version_for_ssh: 4 + run_validation: true volume: max_microversion: latest - storage_protocol: iSCSI + storage_protocol: ceph + manage_volume_ref: source-name,volume-%s + manage_snapshot_ref: source-name,snapshot-%s volume-feature-enabled: + multi_backend: false backup: true + snapshot: true + clone: true + manage_snapshot: true + manage_volume: true + extend_attached_volume: true + extend_attached_encrypted_volume: false + consistency_group: false + volume_revert: true +load_balancer: + test_with_ipv6: false +neutron_plugin_options: + agent_availability_zone: nova + available_type_drivers: flat,geneve,vlan,gre,local,vxlan + provider_vlans: public, + create_shared_resources: true +object-storage-feature-enabled: + discoverable_apis: "account_quotas,formpost,bulk_upload,bulk_delete,\ + tempurl,crossdomain,container_quotas,staticweb,account_quotas,slo" + object_versioning: true + discoverability: true + tempurl_digest_hashlib: sha1 +heat_plugin: + skip_functional_test_list: EncryptionVolTypeTest + skip_scenario_test_list: "AodhAlarmTest,SoftwareConfigIntegrationTest,\ + VolumeBackupRestoreIntegrationTest,CfnInitIntegrationTest,\ + LoadBalancerTest" + auth_version: 3 +heat_features_enabled: + multi_cloud: false +rbac: + enable_rbac: true diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf_ovn.yaml b/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf_ovn.yaml new file mode 100644 index 000000000..6b09d8e5a --- /dev/null +++ b/functest/opnfv_tests/openstack/tempest/custom_tests/tempest_conf_ovn.yaml @@ -0,0 +1,104 @@ +--- +compute: + min_microversion: '2.44' + max_microversion: latest +compute-feature-enabled: + attach_encrypted_volume: false + block_migration_for_live_migration: false + block_migrate_cinder_iscsi: false + change_password: false + cold_migration: true + config_drive: true + console_output: true + disk_config: true + enable_instance_password: true + hostname_fqdn_sanitization: true + interface_attach: true + live_migration: true + live_migrate_back_and_forth: false + metadata_service: true + pause: true + personality: false + rdp_console: false + rescue: true + resize: true + scheduler_available_filters: "AvailabilityZoneFilter,ComputeFilter,\ + ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,\ + ServerGroupAffinityFilter,SameHostFilter,DifferentHostFilter" + serial_console: false + shelve: true + snapshot: true + spice_console: false + suspend: true + swap_volume: false + vnc_console: true + volume_backed_live_migration: false + volume_multiattach: false +identity: + auth_version: v3 + user_unique_last_password_count: 2 + user_lockout_duration: 10 + user_lockout_failure_attempts: 2 +identity-feature-enabled: + trust: true + api_v2: false + api_v2_admin: false + security_compliance: true + federation: false + external_idp: false + project_tags: true + application_credentials: true + access_rules: true +image-feature-enabled: + api_v2: true + api_v1: false + import_image: false +network-feature-enabled: + port_admin_state_change: true + port_security: true +placement: + max_microversion: latest +validation: + image_ssh_user: cirros + ssh_timeout: 196 + ip_version_for_ssh: 4 + run_validation: true +volume: + max_microversion: latest + storage_protocol: ceph + manage_volume_ref: source-name,volume-%s + manage_snapshot_ref: source-name,snapshot-%s +volume-feature-enabled: + multi_backend: false + backup: true + snapshot: true + clone: true + manage_snapshot: true + manage_volume: true + extend_attached_volume: true + extend_attached_encrypted_volume: false + consistency_group: false + volume_revert: true +load_balancer: + test_with_ipv6: false +neutron_plugin_options: + agent_availability_zone: nova + available_type_drivers: flat,geneve,vlan,local + provider_vlans: public, + create_shared_resources: true +object-storage-feature-enabled: + discoverable_apis: "account_quotas,formpost,bulk_upload,bulk_delete,\ + tempurl,crossdomain,container_quotas,staticweb,account_quotas,slo" + object_versioning: true + discoverability: true + tempurl_digest_hashlib: sha1 +heat_plugin: + skip_functional_test_list: EncryptionVolTypeTest + skip_scenario_test_list: "AodhAlarmTest,SoftwareConfigIntegrationTest,\ + VolumeBackupRestoreIntegrationTest,CfnInitIntegrationTest,\ + LoadBalancerTest" + auth_version: 3 +heat_features_enabled: + multi_cloud: false +rbac: + enable_rbac: true diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py index be86cee86..7233ffd60 100644 --- a/functest/opnfv_tests/openstack/tempest/tempest.py +++ b/functest/opnfv_tests/openstack/tempest/tempest.py @@ -39,7 +39,7 @@ class TempestCommon(singlevm.VmReady2): """TempestCommon testcases implementation class.""" visibility = 'public' - filename_alt = '/home/opnfv/functest/images/cirros-0.4.0-x86_64-disk.img' + filename_alt = '/home/opnfv/functest/images/cirros-0.6.1-x86_64-disk.img' shared_network = True tempest_conf_yaml = pkg_resources.resource_filename( 'functest', @@ -50,11 +50,14 @@ class TempestCommon(singlevm.VmReady2): tempest_blacklist = pkg_resources.resource_filename( 'functest', 'opnfv_tests/openstack/tempest/custom_tests/blacklist.yaml') + tempest_public_blacklist = pkg_resources.resource_filename( + 'functest', + 'opnfv_tests/openstack/tempest/custom_tests/public_blacklist.yaml') def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'tempest' - super(TempestCommon, self).__init__(**kwargs) + super().__init__(**kwargs) assert self.orig_cloud assert self.cloud assert self.project @@ -95,6 +98,7 @@ class TempestCommon(singlevm.VmReady2): except Exception: # pylint: disable=broad-except pass self.deny_skipping = kwargs.get("deny_skipping", False) + self.tests_count = kwargs.get("tests_count", 0) def check_services(self): """Check the mandatory services.""" @@ -124,7 +128,7 @@ class TempestCommon(singlevm.VmReady2): @staticmethod def read_file(filename): """Read file and return content as a stripped list.""" - with open(filename) as src: + with open(filename, encoding='utf-8') as src: return [line.strip() for line in src.readlines()] @staticmethod @@ -138,22 +142,22 @@ class TempestCommon(singlevm.VmReady2): } cmd = ["rally", "verify", "show", "--uuid", verif_id] LOGGER.info("Showing result for a verification: '%s'.", cmd) - proc = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - for line in proc.stdout: - LOGGER.info(line.decode("utf-8").rstrip()) - new_line = line.decode("utf-8").replace(' ', '').split('|') - if 'Tests' in new_line: - break - if 'Testscount' in new_line: - result['num_tests'] = int(new_line[2]) - elif 'Success' in new_line: - result['num_success'] = int(new_line[2]) - elif 'Skipped' in new_line: - result['num_skipped'] = int(new_line[2]) - elif 'Failures' in new_line: - result['num_failures'] = int(new_line[2]) + with subprocess.Popen( + cmd, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) as proc: + for line in proc.stdout: + LOGGER.info(line.decode("utf-8").rstrip()) + new_line = line.decode("utf-8").replace(' ', '').split('|') + if 'Tests' in new_line: + break + if 'Testscount' in new_line: + result['num_tests'] = int(new_line[2]) + elif 'Success' in new_line: + result['num_success'] = int(new_line[2]) + elif 'Skipped' in new_line: + result['num_skipped'] = int(new_line[2]) + elif 'Failures' in new_line: + result['num_failures'] = int(new_line[2]) return result @staticmethod @@ -195,10 +199,10 @@ class TempestCommon(singlevm.VmReady2): cmd = ("rally verify list-verifiers | awk '/" + getattr(config.CONF, 'tempest_verifier_name') + "/ {print $2}'") - proc = subprocess.Popen(cmd, shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - verifier_uuid = proc.stdout.readline().rstrip() + with subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL) as proc: + verifier_uuid = proc.stdout.readline().rstrip() return verifier_uuid.decode("utf-8") @staticmethod @@ -208,7 +212,7 @@ class TempestCommon(singlevm.VmReady2): """ return os.path.join(getattr(config.CONF, 'dir_rally_inst'), 'verification', - 'verifier-{}'.format(verifier_id), + f'verifier-{verifier_id}', 'repo') @staticmethod @@ -218,13 +222,13 @@ class TempestCommon(singlevm.VmReady2): """ return os.path.join(getattr(config.CONF, 'dir_rally_inst'), 'verification', - 'verifier-{}'.format(verifier_id), - 'for-deployment-{}'.format(deployment_id)) + f'verifier-{verifier_id}', + f'for-deployment-{deployment_id}') @staticmethod def update_tempest_conf_file(conf_file, rconfig): """Update defined paramters into tempest config file""" - with open(TempestCommon.tempest_conf_yaml) as yfile: + with open(TempestCommon.tempest_conf_yaml, encoding='utf-8') as yfile: conf_yaml = yaml.safe_load(yfile) if conf_yaml: sections = rconfig.sections() @@ -235,7 +239,7 @@ class TempestCommon(singlevm.VmReady2): for key, value in sub_conf.items(): rconfig.set(section, key, value) - with open(conf_file, 'w') as config_file: + with open(conf_file, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) @staticmethod @@ -266,27 +270,8 @@ class TempestCommon(singlevm.VmReady2): # enable multinode tests rconfig.set('compute', 'min_compute_nodes', compute_cnt) rconfig.set('compute-feature-enabled', 'live_migration', True) - filters = ['RetryFilter', 'AvailabilityZoneFilter', 'ComputeFilter', - 'ComputeCapabilitiesFilter', 'ImagePropertiesFilter', - 'ServerGroupAntiAffinityFilter', - 'ServerGroupAffinityFilter'] - rconfig.set( - 'compute-feature-enabled', 'scheduler_available_filters', - functest_utils.convert_list_to_ini(filters)) if os.environ.get('OS_REGION_NAME'): rconfig.set('identity', 'region', os.environ.get('OS_REGION_NAME')) - if env.get("NEW_USER_ROLE").lower() != "member": - rconfig.set( - 'auth', 'tempest_roles', - functest_utils.convert_list_to_ini([env.get("NEW_USER_ROLE")])) - if not json.loads(env.get("USE_DYNAMIC_CREDENTIALS").lower()): - rconfig.set('auth', 'use_dynamic_credentials', False) - account_file = os.path.join( - getattr(config.CONF, 'dir_functest_data'), 'accounts.yaml') - assert os.path.exists( - account_file), "{} doesn't exist".format(account_file) - rconfig.set('auth', 'test_accounts_file', account_file) - rconfig.set('identity', 'auth_version', 'v3') rconfig.set('identity', 'admin_role', admin_role_name) rconfig.set('identity', 'default_domain_id', domain_id) if not rconfig.has_section('network'): @@ -339,51 +324,49 @@ class TempestCommon(singlevm.VmReady2): shutil.copyfile( self.tempest_custom, self.list) else: - raise Exception("Tempest test list file %s NOT found." - % self.tempest_custom) + raise Exception( + f"Tempest test list file {self.tempest_custom} NOT found.") else: testr_mode = kwargs.get( 'mode', r'^tempest\.(api|scenario).*\[.*\bsmoke\b.*\]$') - cmd = "(cd {0}; stestr list '{1}' >{2} 2>/dev/null)".format( - self.verifier_repo_dir, testr_mode, self.list) + cmd = (f"(cd {self.verifier_repo_dir}; " + f"stestr list '{testr_mode}' > {self.list} 2>/dev/null)") output = subprocess.check_output(cmd, shell=True) LOGGER.info("%s\n%s", cmd, output.decode("utf-8")) os.remove('/etc/tempest.conf') - def apply_tempest_blacklist(self): + def apply_tempest_blacklist(self, black_list): """Exclude blacklisted test cases.""" LOGGER.debug("Applying tempest blacklist...") if os.path.exists(self.raw_list): os.remove(self.raw_list) os.rename(self.list, self.raw_list) cases_file = self.read_file(self.raw_list) - result_file = open(self.list, 'w') - black_tests = [] - try: - deploy_scenario = env.get('DEPLOY_SCENARIO') - if bool(deploy_scenario): - # if DEPLOY_SCENARIO is set we read the file - black_list_file = open(self.tempest_blacklist) - black_list_yaml = yaml.safe_load(black_list_file) - black_list_file.close() - for item in black_list_yaml: - scenarios = item['scenarios'] - if deploy_scenario in scenarios: - tests = item['tests'] - for test in tests: - black_tests.append(test) - break - except Exception: # pylint: disable=broad-except + with open(self.list, 'w', encoding='utf-8') as result_file: black_tests = [] - LOGGER.debug("Tempest blacklist file does not exist.") + try: + deploy_scenario = env.get('DEPLOY_SCENARIO') + if bool(deploy_scenario): + # if DEPLOY_SCENARIO is set we read the file + with open(black_list, encoding='utf-8') as black_list_file: + black_list_yaml = yaml.safe_load(black_list_file) + black_list_file.close() + for item in black_list_yaml: + scenarios = item['scenarios'] + in_it = rally.RallyBase.in_iterable_re + if in_it(deploy_scenario, scenarios): + tests = item['tests'] + black_tests.extend(tests) + except Exception: # pylint: disable=broad-except + black_tests = [] + LOGGER.debug("Tempest blacklist file does not exist.") - for cases_line in cases_file: - for black_tests_line in black_tests: - if black_tests_line in cases_line: - break - else: - result_file.write(str(cases_line) + '\n') - result_file.close() + for cases_line in cases_file: + for black_tests_line in black_tests: + if re.search(black_tests_line, cases_line): + break + else: + result_file.write(str(cases_line) + '\n') def run_verifier_tests(self, **kwargs): """Execute tempest test cases.""" @@ -392,33 +375,31 @@ class TempestCommon(singlevm.VmReady2): cmd.extend(kwargs.get('option', [])) LOGGER.info("Starting Tempest test suite: '%s'.", cmd) - f_stdout = open( - os.path.join(self.res_dir, "tempest.log"), 'w+') - - proc = subprocess.Popen( - cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - bufsize=1) - - with proc.stdout: - for line in iter(proc.stdout.readline, b''): - if re.search(r"\} tempest\.", line.decode("utf-8")): - LOGGER.info(line.rstrip()) - elif re.search(r'(?=\(UUID=(.*)\))', line.decode("utf-8")): - self.verification_id = re.search( - r'(?=\(UUID=(.*)\))', line.decode("utf-8")).group(1) - f_stdout.write(line.decode("utf-8")) - proc.wait() - f_stdout.close() + with open( + os.path.join(self.res_dir, "tempest.log"), 'w+', + encoding='utf-8') as f_stdout: + with subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + bufsize=1) as proc: + with proc.stdout: + for line in iter(proc.stdout.readline, b''): + if re.search(r"\} tempest\.", line.decode("utf-8")): + LOGGER.info(line.rstrip()) + elif re.search(r'(?=\(UUID=(.*)\))', + line.decode("utf-8")): + self.verification_id = re.search( + r'(?=\(UUID=(.*)\))', + line.decode("utf-8")).group(1) + f_stdout.write(line.decode("utf-8")) + proc.wait() if self.verification_id is None: raise Exception('Verification UUID not found') LOGGER.info('Verification UUID: %s', self.verification_id) shutil.copy( - "{}/tempest.log".format(self.deployment_dir), - "{}/tempest.debug.log".format(self.res_dir)) + f"{self.deployment_dir}/tempest.log", + f"{self.res_dir}/tempest.debug.log") def parse_verifier_result(self): """Parse and save test results.""" @@ -435,8 +416,8 @@ class TempestCommon(singlevm.VmReady2): LOGGER.error("No test has been executed") return - with open(os.path.join(self.res_dir, - "rally.log"), 'r') as logfile: + with open(os.path.join(self.res_dir, "rally.log"), + 'r', encoding='utf-8') as logfile: output = logfile.read() success_testcases = [] @@ -471,9 +452,8 @@ class TempestCommon(singlevm.VmReady2): rconfig.read(rally_conf) if not rconfig.has_section('openstack'): rconfig.add_section('openstack') - rconfig.set('openstack', 'img_name_regex', '^{}$'.format( - self.image.name)) - with open(rally_conf, 'w') as config_file: + rconfig.set('openstack', 'img_name_regex', f'^{self.image.name}$') + with open(rally_conf, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) def update_default_role(self, rally_conf='/etc/rally/rally.conf'): @@ -486,7 +466,7 @@ class TempestCommon(singlevm.VmReady2): if not rconfig.has_section('openstack'): rconfig.add_section('openstack') rconfig.set('openstack', 'swift_operator_role', role.name) - with open(rally_conf, 'w') as config_file: + with open(rally_conf, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) @staticmethod @@ -498,18 +478,51 @@ class TempestCommon(singlevm.VmReady2): rconfig.remove_option('openstack', 'img_name_regex') if rconfig.has_option('openstack', 'swift_operator_role'): rconfig.remove_option('openstack', 'swift_operator_role') - with open(rally_conf, 'w') as config_file: + with open(rally_conf, 'w', encoding='utf-8') as config_file: + rconfig.write(config_file) + + def update_auth_section(self): + """Update auth section in tempest.conf""" + rconfig = configparser.RawConfigParser() + rconfig.read(self.conf_file) + if not rconfig.has_section("auth"): + rconfig.add_section("auth") + if env.get("NEW_USER_ROLE").lower() != "member": + tempest_roles = [] + if rconfig.has_option("auth", "tempest_roles"): + tempest_roles = functest_utils.convert_ini_to_list( + rconfig.get("auth", "tempest_roles")) + rconfig.set( + 'auth', 'tempest_roles', + functest_utils.convert_list_to_ini( + [env.get("NEW_USER_ROLE")] + tempest_roles)) + if not json.loads(env.get("USE_DYNAMIC_CREDENTIALS").lower()): + rconfig.set('auth', 'use_dynamic_credentials', False) + account_file = os.path.join( + getattr(config.CONF, 'dir_functest_data'), 'accounts.yaml') + assert os.path.exists( + account_file), f"{account_file} doesn't exist" + rconfig.set('auth', 'test_accounts_file', account_file) + if env.get('NO_TENANT_NETWORK').lower() == 'true': + rconfig.set('auth', 'create_isolated_networks', False) + with open(self.conf_file, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) def update_network_section(self): """Update network section in tempest.conf""" rconfig = configparser.RawConfigParser() rconfig.read(self.conf_file) - if not rconfig.has_section('network'): - rconfig.add_section('network') - rconfig.set('network', 'public_network_id', self.ext_net.id) - rconfig.set('network', 'floating_network_name', self.ext_net.name) - with open(self.conf_file, 'w') as config_file: + if self.ext_net: + if not rconfig.has_section('network'): + rconfig.add_section('network') + rconfig.set('network', 'public_network_id', self.ext_net.id) + rconfig.set('network', 'floating_network_name', self.ext_net.name) + rconfig.set('network-feature-enabled', 'floating_ips', True) + else: + if not rconfig.has_section('network-feature-enabled'): + rconfig.add_section('network-feature-enabled') + rconfig.set('network-feature-enabled', 'floating_ips', False) + with open(self.conf_file, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) def update_compute_section(self): @@ -518,8 +531,25 @@ class TempestCommon(singlevm.VmReady2): rconfig.read(self.conf_file) if not rconfig.has_section('compute'): rconfig.add_section('compute') - rconfig.set('compute', 'fixed_network_name', self.network.name) - with open(self.conf_file, 'w') as config_file: + rconfig.set( + 'compute', 'fixed_network_name', + self.network.name if self.network else env.get("EXTERNAL_NETWORK")) + with open(self.conf_file, 'w', encoding='utf-8') as config_file: + rconfig.write(config_file) + + def update_validation_section(self): + """Update validation section in tempest.conf""" + rconfig = configparser.RawConfigParser() + rconfig.read(self.conf_file) + if not rconfig.has_section('validation'): + rconfig.add_section('validation') + rconfig.set( + 'validation', 'connect_method', + 'floating' if self.ext_net else 'fixed') + rconfig.set( + 'validation', 'network_for_ssh', + self.network.name if self.network else env.get("EXTERNAL_NETWORK")) + with open(self.conf_file, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) def update_scenario_section(self): @@ -527,13 +557,12 @@ class TempestCommon(singlevm.VmReady2): rconfig = configparser.RawConfigParser() rconfig.read(self.conf_file) filename = getattr( - config.CONF, '{}_image'.format(self.case_name), self.filename) + config.CONF, f'{self.case_name}_image', self.filename) if not rconfig.has_section('scenario'): rconfig.add_section('scenario') - rconfig.set('scenario', 'img_file', os.path.basename(filename)) - rconfig.set('scenario', 'img_dir', os.path.dirname(filename)) + rconfig.set('scenario', 'img_file', filename) rconfig.set('scenario', 'img_disk_format', getattr( - config.CONF, '{}_image_format'.format(self.case_name), + config.CONF, f'{self.case_name}_image_format', self.image_format)) extra_properties = self.extra_properties.copy() if env.get('IMAGE_PROPERTIES'): @@ -541,12 +570,24 @@ class TempestCommon(singlevm.VmReady2): functest_utils.convert_ini_to_dict( env.get('IMAGE_PROPERTIES'))) extra_properties.update( - getattr(config.CONF, '{}_extra_properties'.format( - self.case_name), {})) + getattr(config.CONF, f'{self.case_name}_extra_properties', {})) rconfig.set( 'scenario', 'img_properties', functest_utils.convert_dict_to_ini(extra_properties)) - with open(self.conf_file, 'w') as config_file: + with open(self.conf_file, 'w', encoding='utf-8') as config_file: + rconfig.write(config_file) + + def update_dashboard_section(self): + """Update dashboard section in tempest.conf""" + rconfig = configparser.RawConfigParser() + rconfig.read(self.conf_file) + if env.get('DASHBOARD_URL'): + if not rconfig.has_section('dashboard'): + rconfig.add_section('dashboard') + rconfig.set('dashboard', 'dashboard_url', env.get('DASHBOARD_URL')) + else: + rconfig.set('service_available', 'horizon', False) + with open(self.conf_file, 'w', encoding='utf-8') as config_file: rconfig.write(config_file) def configure(self, **kwargs): # pylint: disable=unused-argument @@ -568,8 +609,8 @@ class TempestCommon(singlevm.VmReady2): self.deployment_dir = self.get_verifier_deployment_dir( self.verifier_id, self.deployment_id) - compute_cnt = len(self.orig_cloud.list_hypervisors()) - + compute_cnt = self.count_hypervisors() if self.count_hypervisors( + ) <= 10 else 10 self.image_alt = self.publish_image_alt() self.flavor_alt = self.create_flavor_alt() LOGGER.debug("flavor: %s", self.flavor_alt) @@ -586,15 +627,18 @@ class TempestCommon(singlevm.VmReady2): flavor_alt_id=self.flavor_alt.id, admin_role_name=self.role_name, cidr=self.cidr, domain_id=self.project.domain.id) + self.update_auth_section() self.update_network_section() self.update_compute_section() + self.update_validation_section() self.update_scenario_section() + self.update_dashboard_section() self.backup_tempest_config(self.conf_file, self.res_dir) def run(self, **kwargs): self.start_time = time.time() try: - assert super(TempestCommon, self).run( + assert super().run( **kwargs) == testcase.TestCase.EX_OK if not os.path.exists(self.res_dir): os.makedirs(self.res_dir) @@ -604,7 +648,10 @@ class TempestCommon(singlevm.VmReady2): shutil.copy("/etc/rally/rally.conf", self.res_dir) self.configure(**kwargs) self.generate_test_list(**kwargs) - self.apply_tempest_blacklist() + self.apply_tempest_blacklist(TempestCommon.tempest_blacklist) + if env.get('PUBLIC_ENDPOINT_ONLY').lower() == 'true': + self.apply_tempest_blacklist( + TempestCommon.tempest_public_blacklist) self.run_verifier_tests(**kwargs) self.parse_verifier_result() rally.RallyBase.verify_report( @@ -631,11 +678,97 @@ class TempestCommon(singlevm.VmReady2): self.cloud.delete_image(self.image_alt) if self.flavor_alt: self.orig_cloud.delete_flavor(self.flavor_alt.id) - super(TempestCommon, self).clean() + super().clean() def is_successful(self): """The overall result of the test.""" skips = self.details.get("skipped_number", 0) if skips > 0 and self.deny_skipping: return testcase.TestCase.EX_TESTCASE_FAILED - return super(TempestCommon, self).is_successful() + if self.tests_count and ( + self.details.get("tests_number", 0) != self.tests_count): + return testcase.TestCase.EX_TESTCASE_FAILED + return super().is_successful() + + +class TempestHeat(TempestCommon): + """Tempest Heat testcase implementation class.""" + + filename_alt = ('/home/opnfv/functest/images/' + 'Fedora-Cloud-Base-30-1.2.x86_64.qcow2') + flavor_alt_ram = 512 + flavor_alt_vcpus = 1 + flavor_alt_disk = 4 + + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.user2 = self.orig_cloud.create_user( + name=f'{self.case_name}-user2_{self.project.guid}', + password=self.project.password, + domain_id=self.project.domain.id) + self.orig_cloud.grant_role( + self.role_name, user=self.user2.id, + project=self.project.project.id, domain=self.project.domain.id) + if not self.orig_cloud.get_role("heat_stack_owner"): + self.role = self.orig_cloud.create_role("heat_stack_owner") + self.orig_cloud.grant_role( + "heat_stack_owner", user=self.user2.id, + project=self.project.project.id, + domain=self.project.domain.id) + + def configure(self, **kwargs): + assert self.user2 + super().configure(**kwargs) + rconfig = configparser.RawConfigParser() + rconfig.read(self.conf_file) + if not rconfig.has_section('heat_plugin'): + rconfig.add_section('heat_plugin') + # It fails if region and domain ids are unset + rconfig.set( + 'heat_plugin', 'region', + os.environ.get('OS_REGION_NAME', 'RegionOne')) + rconfig.set('heat_plugin', 'auth_url', os.environ["OS_AUTH_URL"]) + rconfig.set('heat_plugin', 'project_domain_id', self.project.domain.id) + rconfig.set('heat_plugin', 'user_domain_id', self.project.domain.id) + rconfig.set( + 'heat_plugin', 'project_domain_name', self.project.domain.name) + rconfig.set( + 'heat_plugin', 'user_domain_name', self.project.domain.name) + rconfig.set('heat_plugin', 'username', self.user2.name) + rconfig.set('heat_plugin', 'password', self.project.password) + rconfig.set('heat_plugin', 'project_name', self.project.project.name) + rconfig.set('heat_plugin', 'admin_username', self.project.user.name) + rconfig.set('heat_plugin', 'admin_password', self.project.password) + rconfig.set( + 'heat_plugin', 'admin_project_name', self.project.project.name) + rconfig.set('heat_plugin', 'image_ref', self.image_alt.id) + rconfig.set('heat_plugin', 'instance_type', self.flavor_alt.id) + rconfig.set('heat_plugin', 'minimal_image_ref', self.image.id) + rconfig.set('heat_plugin', 'minimal_instance_type', self.flavor.id) + if self.ext_net: + rconfig.set( + 'heat_plugin', 'floating_network_name', self.ext_net.name) + if self.network: + rconfig.set('heat_plugin', 'fixed_network_name', self.network.name) + rconfig.set('heat_plugin', 'fixed_subnet_name', self.subnet.name) + rconfig.set('heat_plugin', 'network_for_ssh', self.network.name) + else: + LOGGER.warning( + 'No tenant network created. ' + 'Trying EXTERNAL_NETWORK as a fallback') + rconfig.set( + 'heat_plugin', 'fixed_network_name', + env.get("EXTERNAL_NETWORK")) + rconfig.set( + 'heat_plugin', 'network_for_ssh', env.get("EXTERNAL_NETWORK")) + with open(self.conf_file, 'w', encoding='utf-8') as config_file: + rconfig.write(config_file) + self.backup_tempest_config(self.conf_file, self.res_dir) + + def clean(self): + """ + Cleanup all OpenStack objects. Should be called on completion. + """ + super().clean() + if self.user2: + self.orig_cloud.delete_user(self.user2.id) diff --git a/functest/opnfv_tests/openstack/vgpu/__init__.py b/functest/opnfv_tests/openstack/vgpu/__init__.py deleted file mode 100644 index e69de29bb..000000000 --- a/functest/opnfv_tests/openstack/vgpu/__init__.py +++ /dev/null diff --git a/functest/opnfv_tests/openstack/vgpu/vgpu.py b/functest/opnfv_tests/openstack/vgpu/vgpu.py deleted file mode 100644 index c8180a45c..000000000 --- a/functest/opnfv_tests/openstack/vgpu/vgpu.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2018 Kontron and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 - -"""vGPU testcase implementation.""" - -from __future__ import division - -import logging - -from functest.core import singlevm - - -class VGPU(singlevm.SingleVm2): - """OpenStack vGPU Test Case.""" - - __logger = logging.getLogger(__name__) - - filename = ('/home/opnfv/functest/images/' - 'ubuntu-16.04-server-cloudimg-amd64-disk1.img') - flavor_ram = 4096 - flavor_vcpus = 2 - flavor_disk = 40 - flavor_extra_specs = {'resources:VGPU': '1'} - username = 'ubuntu' - ssh_connect_loops = 12 - create_server_timeout = 300 - - def __init__(self, **kwargs): - """Initialize vGPU testcase object.""" - if "case_name" not in kwargs: - kwargs["case_name"] = "vgpu" - super(VGPU, self).__init__(**kwargs) - - def execute(self): - """ - Test if the vGPU exist. - """ - (_, stdout, stderr) = self.ssh.exec_command('lspci') - lspci_output = stdout.read() - self.__logger.debug("output:\n%s", stdout.read()) - self.__logger.debug("error:\n%s", stderr.read()) - if ('VGA compatible controller: Intel' in lspci_output or - 'VGA compatible controller: Nvidia' in lspci_output): - self.__logger.info("The VM have a vGPU") - return 0 - self.__logger.error("The VM haven't any vGPU") - return 1 diff --git a/functest/opnfv_tests/openstack/vmtp/vmtp.py b/functest/opnfv_tests/openstack/vmtp/vmtp.py index c146d60ad..9833cc72a 100644 --- a/functest/opnfv_tests/openstack/vmtp/vmtp.py +++ b/functest/opnfv_tests/openstack/vmtp/vmtp.py @@ -33,6 +33,7 @@ from xtesting.core import testcase from functest.core import singlevm from functest.utils import env +from functest.utils import functest_utils class Vmtp(singlevm.VmReady2): @@ -50,17 +51,18 @@ class Vmtp(singlevm.VmReady2): flavor_vcpus = 1 flavor_disk = 0 create_server_timeout = 300 + ssh_retry_timeout = 240 def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = 'vmtp' - super(Vmtp, self).__init__(**kwargs) - self.config = "{}/vmtp.conf".format(self.res_dir) + super().__init__(**kwargs) + self.config = f"{self.res_dir}/vmtp.conf" (_, self.privkey_filename) = tempfile.mkstemp() (_, self.pubkey_filename) = tempfile.mkstemp() def check_requirements(self): - if len(self.orig_cloud.list_hypervisors()) < 2: + if self.count_hypervisors() < 2: self.__logger.warning("Vmtp requires at least 2 hypervisors") self.is_skipped = True self.project.clean() @@ -75,7 +77,7 @@ class Vmtp(singlevm.VmReady2): assert self.cloud assert self.ext_net self.router = self.cloud.create_router( - name='{}-router_{}'.format(self.case_name, self.guid), + name=f'{self.case_name}-router_{self.guid}', ext_gateway_net_id=self.ext_net.id) self.__logger.debug("router: %s", self.router) @@ -85,13 +87,13 @@ class Vmtp(singlevm.VmReady2): Raises: Exception on error """ assert self.cloud - name = "vmtp_{}".format(self.guid) + name = f"vmtp_{self.guid}" self.__logger.info("Creating keypair with name: '%s'", name) keypair = self.cloud.create_keypair(name) self.__logger.debug("keypair: %s", keypair) - with open(self.privkey_filename, 'w') as key_file: + with open(self.privkey_filename, 'w', encoding='utf-8') as key_file: key_file.write(keypair.private_key) - with open(self.pubkey_filename, 'w') as key_file: + with open(self.pubkey_filename, 'w', encoding='utf-8') as key_file: key_file.write(keypair.public_key) self.cloud.delete_keypair(keypair.id) @@ -106,7 +108,7 @@ class Vmtp(singlevm.VmReady2): cmd = ['vmtp', '-sc'] output = subprocess.check_output(cmd).decode("utf-8") self.__logger.info("%s\n%s", " ".join(cmd), output) - with open(self.config, "w+") as conf: + with open(self.config, "w+", encoding='utf-8') as conf: vmtp_conf = yaml.full_load(output) vmtp_conf["private_key_file"] = self.privkey_filename vmtp_conf["public_key_file"] = self.pubkey_filename @@ -114,17 +116,18 @@ class Vmtp(singlevm.VmReady2): vmtp_conf["router_name"] = str(self.router.name) vmtp_conf["flavor_type"] = str(self.flavor.name) vmtp_conf["internal_network_name"] = [ - "pns-internal-net_{}".format(self.guid), - "pns-internal-net2_{}".format(self.guid)] - vmtp_conf["vm_name_client"] = "TestClient_{}".format(self.guid) - vmtp_conf["vm_name_server"] = "TestServer_{}".format(self.guid) - vmtp_conf["security_group_name"] = "pns-security{}".format( - self.guid) + f"pns-internal-net_{self.guid}", + f"pns-internal-net2_{self.guid}"] + vmtp_conf["vm_name_client"] = f"TestClient_{self.guid}" + vmtp_conf["vm_name_server"] = f"TestServer_{self.guid}" + vmtp_conf["security_group_name"] = f"pns-security{self.guid}" vmtp_conf["dns_nameservers"] = [env.get('NAMESERVER')] vmtp_conf["generic_retry_count"] = self.create_server_timeout // 2 + vmtp_conf["ssh_retry_count"] = self.ssh_retry_timeout // 2 conf.write(yaml.dump(vmtp_conf)) def run_vmtp(self): + # pylint: disable=unexpected-keyword-arg """Run Vmtp and generate charts Raises: Exception on error @@ -135,25 +138,34 @@ class Vmtp(singlevm.VmReady2): OS_USERNAME=self.project.user.name, OS_PROJECT_NAME=self.project.project.name, OS_PROJECT_ID=self.project.project.id, + OS_PROJECT_DOMAIN_NAME=self.project.domain.name, + OS_USER_DOMAIN_NAME=self.project.domain.name, OS_PASSWORD=self.project.password) if not new_env["OS_AUTH_URL"].endswith(('v3', 'v3/')): - new_env["OS_AUTH_URL"] = "{}/v3".format(new_env["OS_AUTH_URL"]) + new_env["OS_AUTH_URL"] = f'{new_env["OS_AUTH_URL"]}/v3' try: del new_env['OS_TENANT_NAME'] del new_env['OS_TENANT_ID'] except Exception: # pylint: disable=broad-except pass - cmd = ['vmtp', '-d', '--json', '{}/vmtp.json'.format(self.res_dir), + cmd = ['vmtp', '-d', '--json', f'{self.res_dir}/vmtp.json', '-c', self.config] + if env.get("VMTP_HYPERVISORS"): + hypervisors = functest_utils.convert_ini_to_list( + env.get("VMTP_HYPERVISORS")) + for hypervisor in hypervisors: + cmd.extend(["--hypervisor", hypervisor]) + self.__logger.debug("cmd: %s", cmd) output = subprocess.check_output( cmd, stderr=subprocess.STDOUT, env=new_env).decode("utf-8") self.__logger.info("%s\n%s", " ".join(cmd), output) - cmd = ['vmtp_genchart', '-c', '{}/vmtp.html'.format(self.res_dir), - '{}/vmtp.json'.format(self.res_dir)] + cmd = ['vmtp_genchart', '-c', f'{self.res_dir}/vmtp.html', + f'{self.res_dir}/vmtp.json'] output = subprocess.check_output( cmd, stderr=subprocess.STDOUT).decode("utf-8") self.__logger.info("%s\n%s", " ".join(cmd), output) - with open('{}/vmtp.json'.format(self.res_dir), 'r') as res_file: + with open(f'{self.res_dir}/vmtp.json', 'r', + encoding='utf-8') as res_file: self.details = json.load(res_file) def run(self, **kwargs): @@ -161,7 +173,7 @@ class Vmtp(singlevm.VmReady2): status = testcase.TestCase.EX_RUN_ERROR try: assert self.cloud - assert super(Vmtp, self).run(**kwargs) == self.EX_OK + assert super().run(**kwargs) == self.EX_OK status = testcase.TestCase.EX_RUN_ERROR if self.orig_cloud.get_role("admin"): role_name = "admin" @@ -192,10 +204,10 @@ class Vmtp(singlevm.VmReady2): def clean(self): try: assert self.cloud - super(Vmtp, self).clean() + super().clean() os.remove(self.privkey_filename) os.remove(self.pubkey_filename) - self.cloud.delete_network("pns-internal-net_{}".format(self.guid)) - self.cloud.delete_network("pns-internal-net2_{}".format(self.guid)) + self.cloud.delete_network(f"pns-internal-net_{self.guid}") + self.cloud.delete_network(f"pns-internal-net2_{self.guid}") except Exception: # pylint: disable=broad-except pass diff --git a/functest/opnfv_tests/openstack/vping/vping_ssh.py b/functest/opnfv_tests/openstack/vping/vping_ssh.py index 6420013a0..ad64348c4 100644 --- a/functest/opnfv_tests/openstack/vping/vping_ssh.py +++ b/functest/opnfv_tests/openstack/vping/vping_ssh.py @@ -29,13 +29,13 @@ class VPingSSH(singlevm.SingleVm2): """Initialize testcase.""" if "case_name" not in kwargs: kwargs["case_name"] = "vping_ssh" - super(VPingSSH, self).__init__(**kwargs) + super().__init__(**kwargs) self.vm2 = None def prepare(self): - super(VPingSSH, self).prepare() + super().prepare() self.vm2 = self.boot_vm( - '{}-vm2_{}'.format(self.case_name, self.guid), + f'{self.case_name}-vm2_{self.guid}', security_groups=[self.sec.id]) def execute(self): @@ -44,12 +44,13 @@ class VPingSSH(singlevm.SingleVm2): Returns: ping exit codes """ assert self.ssh - (_, stdout, stderr) = self.ssh.exec_command( - 'ping -c 1 {}'.format( - self.vm2.private_v4 or self.vm2.addresses[ - self.network.name][0].addr)) - self.__logger.info("output:\n%s", stdout.read()) - self.__logger.info("error:\n%s", stderr.read()) + if not self.check_regex_in_console(self.vm2.name): + return 1 + ip4 = self.vm2.private_v4 or self.vm2.addresses[ + self.network.name][0].addr + (_, stdout, stderr) = self.ssh.exec_command(f'ping -c 1 {ip4}') + self.__logger.info("output:\n%s", stdout.read().decode("utf-8")) + self.__logger.info("error:\n%s", stderr.read().decode("utf-8")) return stdout.channel.recv_exit_status() def clean(self): @@ -58,4 +59,4 @@ class VPingSSH(singlevm.SingleVm2): self.cloud.delete_server( self.vm2, wait=True, timeout=getattr(config.CONF, 'vping_vm_delete_timeout')) - super(VPingSSH, self).clean() + super().clean() diff --git a/functest/opnfv_tests/openstack/vping/vping_userdata.py b/functest/opnfv_tests/openstack/vping/vping_userdata.py index 225c167d5..8a8f26f37 100644 --- a/functest/opnfv_tests/openstack/vping/vping_userdata.py +++ b/functest/opnfv_tests/openstack/vping/vping_userdata.py @@ -26,7 +26,7 @@ class VPingUserdata(singlevm.VmReady2): def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = "vping_userdata" - super(VPingUserdata, self).__init__(**kwargs) + super().__init__(**kwargs) self.logger = logging.getLogger(__name__) self.vm1 = None self.vm2 = None @@ -39,12 +39,12 @@ class VPingUserdata(singlevm.VmReady2): """ try: assert self.cloud - assert super(VPingUserdata, self).run( + assert super().run( **kwargs) == testcase.TestCase.EX_OK self.result = 0 self.vm1 = self.boot_vm() self.vm2 = self.boot_vm( - '{}-vm2_{}'.format(self.case_name, self.guid), + f'{self.case_name}-vm2_{self.guid}', userdata=self._get_userdata()) result = self._do_vping() @@ -79,13 +79,13 @@ class VPingUserdata(singlevm.VmReady2): self.logger.info("vPing detected!") exit_code = testcase.TestCase.EX_OK break - elif "failed to read iid from metadata" in p_console or tries > 5: + if "failed to read iid from metadata" in p_console or tries > 5: self.logger.info("Failed to read iid from metadata") break - elif sec == getattr(config.CONF, 'vping_ping_timeout'): + if sec == getattr(config.CONF, 'vping_ping_timeout'): self.logger.info("Timeout reached.") break - elif sec % 10 == 0: + if sec % 10 == 0: if "request failed" in p_console: self.logger.debug( "It seems userdata is not supported in nova boot. " @@ -104,13 +104,15 @@ class VPingUserdata(singlevm.VmReady2): """ Returns the post VM creation script to be added into the VM's userdata :param test_ip: the IP value to substitute into the script - :return: the bash script contents + :return: the shell script contents """ + ip4 = self.vm1.private_v4 or self.vm1.addresses[ + self.network.name][0].addr if self.vm1.private_v4 or self.vm1.addresses[ self.network.name][0].addr: return ("#!/bin/sh\n\n" "while true; do\n" - " ping -c 1 %s 2>&1 >/dev/null\n" + f" ping -c 1 {ip4} 2>&1 >/dev/null\n" " RES=$?\n" " if [ \"Z$RES\" = \"Z0\" ] ; then\n" " echo 'vPing OK'\n" @@ -119,9 +121,7 @@ class VPingUserdata(singlevm.VmReady2): " echo 'vPing KO'\n" " fi\n" " sleep 1\n" - "done\n" % str( - self.vm1.private_v4 or self.vm1.addresses[ - self.network.name][0].addr)) + "done\n") return None def clean(self): @@ -134,4 +134,4 @@ class VPingUserdata(singlevm.VmReady2): self.cloud.delete_server( self.vm2, wait=True, timeout=getattr(config.CONF, 'vping_vm_delete_timeout')) - super(VPingUserdata, self).clean() + super().clean() diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py index b54f0f54b..72c38ce2c 100644 --- a/functest/opnfv_tests/sdn/odl/odl.py +++ b/functest/opnfv_tests/sdn/odl/odl.py @@ -49,7 +49,7 @@ class ODLTests(robotframework.RobotFramework): __logger = logging.getLogger(__name__) def __init__(self, **kwargs): - super(ODLTests, self).__init__(**kwargs) + super().__init__(**kwargs) self.res_dir = os.path.join( getattr(config.CONF, 'dir_results'), 'odl') self.xml_file = os.path.join(self.res_dir, 'output.xml') @@ -66,10 +66,10 @@ class ODLTests(robotframework.RobotFramework): try: for line in fileinput.input(cls.odl_variables_file, inplace=True): - print(re.sub("@{AUTH}.*", - "@{{AUTH}} {} {}".format( - odlusername, odlpassword), - line.rstrip())) + print(re.sub( + "@{AUTH}.*", + f"@{{AUTH}} {odlusername} {odlpassword}", + line.rstrip())) return True except Exception: # pylint: disable=broad-except cls.__logger.exception("Cannot set ODL creds:") @@ -111,9 +111,8 @@ class ODLTests(robotframework.RobotFramework): odlusername = kwargs['odlusername'] odlpassword = kwargs['odlpassword'] osauthurl = kwargs['osauthurl'] - keystoneurl = "{}://{}".format( - urllib.parse.urlparse(osauthurl).scheme, - urllib.parse.urlparse(osauthurl).netloc) + keystoneurl = (f"{urllib.parse.urlparse(osauthurl).scheme}://" + f"{urllib.parse.urlparse(osauthurl).netloc}") variable = ['KEYSTONEURL:' + keystoneurl, 'NEUTRONURL:' + kwargs['neutronurl'], 'OS_AUTH_URL:"' + osauthurl + '"', @@ -135,7 +134,7 @@ class ODLTests(robotframework.RobotFramework): else: if not self.set_robotframework_vars(odlusername, odlpassword): return self.EX_RUN_ERROR - return super(ODLTests, self).run(variable=variable, suites=suites) + return super().run(variable=variable, suites=suites) def run(self, **kwargs): """Run suites in OPNFV environment diff --git a/functest/opnfv_tests/vnf/epc/juju_epc.py b/functest/opnfv_tests/vnf/epc/juju_epc.py index b2dbabdb4..1cf240b80 100644 --- a/functest/opnfv_tests/vnf/epc/juju_epc.py +++ b/functest/opnfv_tests/vnf/epc/juju_epc.py @@ -14,11 +14,11 @@ import os import time import json import re -import subprocess import sys from copy import deepcopy import pkg_resources +import scp from functest.core import singlevm from functest.utils import config @@ -42,7 +42,7 @@ CREDS_TEMPLATE2 = """credentials: default-credential: abot-epc abot-epc: auth-type: userpass - password: {pass} + password: '{pass}' project-domain-name: {project_domain_n} tenant-name: {tenant_n}""" @@ -51,14 +51,14 @@ CREDS_TEMPLATE = """credentials: default-credential: abot-epc abot-epc: auth-type: userpass - password: {pass} + password: '{pass}' project-domain-name: {project_domain_n} tenant-name: {tenant_n} user-domain-name: {user_domain_n} username: {user_n}""" -class JujuEpc(singlevm.VmReady2): +class JujuEpc(singlevm.SingleVm2): # pylint:disable=too-many-instance-attributes """Abot EPC deployed with JUJU Orchestrator Case""" @@ -74,26 +74,25 @@ class JujuEpc(singlevm.VmReady2): flavor_ram = 2048 flavor_vcpus = 1 flavor_disk = 10 - flavor_alt_ram = 4096 flavor_alt_vcpus = 1 flavor_alt_disk = 10 - + username = 'ubuntu' juju_timeout = '4800' def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = "juju_epc" - super(JujuEpc, self).__init__(**kwargs) + super().__init__(**kwargs) # Retrieve the configuration self.case_dir = pkg_resources.resource_filename( 'functest', 'opnfv_tests/vnf/epc') try: self.config = getattr( - config.CONF, 'vnf_{}_config'.format(self.case_name)) - except Exception: - raise Exception("VNF config file not found") + config.CONF, f'vnf_{self.case_name}_config') + except Exception as exc: + raise Exception("VNF config file not found") from exc self.config_file = os.path.join(self.case_dir, self.config) self.orchestrator = dict( requirements=functest_utils.get_parameter_from_yaml( @@ -139,25 +138,27 @@ class JujuEpc(singlevm.VmReady2): try: self.public_auth_url = self.get_public_auth_url(self.orig_cloud) if not self.public_auth_url.endswith(('v3', 'v3/')): - self.public_auth_url = "{}/v3".format(self.public_auth_url) + self.public_auth_url = f"{self.public_auth_url}/v3" except Exception: # pylint: disable=broad-except self.public_auth_url = None self.sec = None self.image_alt = None self.flavor_alt = None - def check_requirements(self): - if not os.path.exists("/src/epc-requirements/go/bin/juju"): - self.__logger.warning( - "Juju cannot be cross-compiled (arm and arm64) from the time " - "being") - self.is_skipped = True - self.project.clean() - if env.get('NEW_USER_ROLE').lower() == "admin": - self.__logger.warning( - "Defining NEW_USER_ROLE=admin will easily break the testcase " - "because Juju doesn't manage tenancy (e.g. subnet " - "overlapping)") + def _install_juju(self): + (_, stdout, stderr) = self.ssh.exec_command( + 'sudo snap install juju --channel=2.3/stable --classic') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + return not stdout.channel.recv_exit_status() + + def _install_juju_wait(self): + (_, stdout, stderr) = self.ssh.exec_command( + 'sudo apt-get update && sudo apt-get install python3-pip -y && ' + 'sudo pip3 install juju_wait===2.6.4') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + return not stdout.channel.recv_exit_status() def _register_cloud(self): assert self.public_auth_url @@ -167,11 +168,15 @@ class JujuEpc(singlevm.VmReady2): 'url': self.public_auth_url, 'region': self.cloud.region_name if self.cloud.region_name else ( 'RegionOne')} - with open(clouds_yaml, 'w') as yfile: + with open(clouds_yaml, 'w', encoding='utf-8') as yfile: yfile.write(CLOUD_TEMPLATE.format(**cloud_data)) - cmd = ['juju', 'add-cloud', 'abot-epc', '-f', clouds_yaml, '--replace'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) + scpc = scp.SCPClient(self.ssh.get_transport()) + scpc.put(clouds_yaml, remote_path='~/') + (_, stdout, stderr) = self.ssh.exec_command( + '/snap/bin/juju add-cloud abot-epc -f clouds.yaml --replace') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + return not stdout.channel.recv_exit_status() def _register_credentials(self): self.__logger.info("Creating Credentials for Abot-epc .....") @@ -184,48 +189,38 @@ class JujuEpc(singlevm.VmReady2): "project_domain_name", "Default"), 'user_domain_n': self.cloud.auth.get( "user_domain_name", "Default")} - with open(credentials_yaml, 'w') as yfile: + with open(credentials_yaml, 'w', encoding='utf-8') as yfile: yfile.write(CREDS_TEMPLATE.format(**creds_data)) - cmd = ['juju', 'add-credential', 'abot-epc', '-f', credentials_yaml, - '--replace'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - - def prepare(self): - """Prepare testcase (Additional pre-configuration steps).""" - assert self.public_auth_url - self.__logger.info("Additional pre-configuration steps") - try: - os.makedirs(self.res_dir) - except OSError as ex: - if ex.errno != errno.EEXIST: - self.__logger.exception("Cannot create %s", self.res_dir) - raise Exception - - self.__logger.info("ENV:\n%s", env.string()) - self._register_cloud() - self._register_credentials() - - def publish_image(self, name=None): - image = super(JujuEpc, self).publish_image(name) - cmd = ['juju', 'metadata', 'generate-image', '-d', '/root', - '-i', image.id, '-s', 'xenial', - '-r', self.cloud.region_name if self.cloud.region_name else ( - 'RegionOne'), - '-u', self.public_auth_url] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - return image + scpc = scp.SCPClient(self.ssh.get_transport()) + scpc.put(credentials_yaml, remote_path='~/') + (_, stdout, stderr) = self.ssh.exec_command( + '/snap/bin/juju add-credential abot-epc -f credentials.yaml ' + ' --replace --debug') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + return not stdout.channel.recv_exit_status() + + def _publish_image(self): + region_name = self.cloud.region_name if self.cloud.region_name else ( + 'RegionOne') + (_, stdout, stderr) = self.ssh.exec_command( + '/snap/bin/juju metadata generate-image -d /home/ubuntu ' + f'-i {self.image.id} -s xenial -r {region_name} ' + f'-u {self.public_auth_url}') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + return not stdout.channel.recv_exit_status() def publish_image_alt(self, name=None): - image_alt = super(JujuEpc, self).publish_image_alt(name) - cmd = ['juju', 'metadata', 'generate-image', '-d', '/root', - '-i', image_alt.id, '-s', 'trusty', - '-r', self.cloud.region_name if self.cloud.region_name else ( - 'RegionOne'), - '-u', self.public_auth_url] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) + image_alt = super().publish_image_alt(name) + region_name = self.cloud.region_name if self.cloud.region_name else ( + 'RegionOne') + (_, stdout, stderr) = self.ssh.exec_command( + '/snap/bin/juju metadata generate-image -d /home/ubuntu ' + f'-i {image_alt.id} -s trusty -r {region_name} ' + f'-u {self.public_auth_url}') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) return image_alt def deploy_orchestrator(self): # pylint: disable=too-many-locals @@ -234,47 +229,39 @@ class JujuEpc(singlevm.VmReady2): Bootstrap juju """ + self._publish_image() self.image_alt = self.publish_image_alt() self.flavor_alt = self.create_flavor_alt() self.__logger.info("Starting Juju Bootstrap process...") - try: - cmd = ['timeout', JujuEpc.juju_timeout, - 'juju', 'bootstrap', - 'abot-epc/{}'.format( - self.cloud.region_name if self.cloud.region_name else ( - 'RegionOne')), - 'abot-controller', - '--agent-version', '2.3.9', - '--metadata-source', '/root', - '--constraints', 'mem=2G', - '--bootstrap-series', 'xenial', - '--config', 'network={}'.format(self.network.id), - '--config', 'ssl-hostname-verification=false', - '--config', 'external-network={}'.format(self.ext_net.id), - '--config', 'use-floating-ip=true', - '--config', 'use-default-secgroup=true', - '--debug'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - except subprocess.CalledProcessError as cpe: - self.__logger.error( - "Exception with Juju Bootstrap: %s\n%s", - cpe.cmd, cpe.output.decode("utf-8")) - return False - except Exception: # pylint: disable=broad-except - self.__logger.exception("Some issue with Juju Bootstrap ...") - return False - - return True + region_name = self.cloud.region_name if self.cloud.region_name else ( + 'RegionOne') + (_, stdout, stderr) = self.ssh.exec_command( + f'timeout {JujuEpc.juju_timeout} ' + f'/snap/bin/juju bootstrap abot-epc/{region_name} abot-controller ' + '--agent-version 2.3.9 --metadata-source /home/ubuntu ' + '--constraints mem=2G --bootstrap-series xenial ' + f'--config network={self.network.id} ' + '--config ssl-hostname-verification=false ' + f'--config external-network={self.ext_net.id} ' + '--config use-floating-ip=true ' + '--config use-default-secgroup=true ' + '--debug') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + return not stdout.channel.recv_exit_status() def check_app(self, name='abot-epc-basic', status='active'): """Check application status.""" - cmd = ['juju', 'status', '--format', 'short', name] for i in range(10): - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) + (_, stdout, stderr) = self.ssh.exec_command( + f'/snap/bin/juju status --format short {name}') + output = stdout.read().decode("utf-8") + self.__logger.debug("stdout:\n%s", output) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + if stdout.channel.recv_exit_status(): + continue ret = re.search( - r'(?=workload:({})\))'.format(status), output.decode("utf-8")) + rf'(?=workload:({status})\))', output) if ret: self.__logger.info("%s workload is %s", name, status) break @@ -289,75 +276,81 @@ class JujuEpc(singlevm.VmReady2): def deploy_vnf(self): """Deploy ABOT-OAI-EPC.""" self.__logger.info("Upload VNFD") - descriptor = self.vnf['descriptor'] + scpc = scp.SCPClient(self.ssh.get_transport()) + scpc.put( + '/src/epc-requirements/abot_charm', remote_path='~/', + recursive=True) self.__logger.info("Deploying Abot-epc bundle file ...") - cmd = ['juju', 'deploy', '{}'.format(descriptor.get('file_name'))] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - self.__logger.info("Waiting for instances .....") - try: - cmd = ['timeout', JujuEpc.juju_timeout, 'juju-wait'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - self.__logger.info("Deployed Abot-epc on Openstack") - except subprocess.CalledProcessError as cpe: - self.__logger.error( - "Exception with Juju VNF Deployment: %s\n%s", - cpe.cmd, cpe.output.decode("utf-8")) - return False - except Exception: # pylint: disable=broad-except - self.__logger.exception("Some issue with the VNF Deployment ..") - return False - + (_, stdout, stderr) = self.ssh.exec_command( + 'sudo mkdir -p /src/epc-requirements && ' + 'sudo mv abot_charm /src/epc-requirements/abot_charm && ' + '/snap/bin/juju deploy ' + '/src/epc-requirements/abot_charm/functest-abot-epc-bundle/' + 'bundle.yaml') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + if stdout.channel.recv_exit_status(): + return not stdout.channel.recv_exit_status() + (_, stdout, stderr) = self.ssh.exec_command( + 'PATH=/snap/bin/:$PATH ' + f'timeout {JujuEpc.juju_timeout} juju-wait') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + if stdout.channel.recv_exit_status(): + return not stdout.channel.recv_exit_status() self.__logger.info("Checking status of ABot and EPC units ...") - cmd = ['juju', 'status'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.debug("%s\n%s", " ".join(cmd), output.decode("utf-8")) + (_, stdout, stderr) = self.ssh.exec_command('/snap/bin/juju status') + output = stdout.read().decode("utf-8") + self.__logger.debug("stdout:\n%s", output) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + if stdout.channel.recv_exit_status(): + return not stdout.channel.recv_exit_status() for app in ['abot-epc-basic', 'oai-epc', 'oai-hss']: if not self.check_app(app): return False - - self.__logger.info("Transferring the feature files to Abot_node ...") - cmd = ['timeout', JujuEpc.juju_timeout, - 'juju', 'scp', '--', '-r', '-v', - '{}/featureFiles'.format(self.case_dir), 'abot-epc-basic/0:~/'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - - self.__logger.info("Copying the feature files within Abot_node ") - cmd = ['timeout', JujuEpc.juju_timeout, - 'juju', 'ssh', 'abot-epc-basic/0', - 'sudo', 'cp', '-vfR', '~/featureFiles/*', - '/etc/rebaca-test-suite/featureFiles'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - return True + scpc = scp.SCPClient(self.ssh.get_transport()) + scpc.put( + f'{self.case_dir}/featureFiles', remote_path='~/', + recursive=True) + (_, stdout, stderr) = self.ssh.exec_command( + f'timeout {JujuEpc.juju_timeout} /snap/bin/juju scp -- -r -v ' + '~/featureFiles abot-epc-basic/0:/etc/rebaca-test-suite/') + output = stdout.read().decode("utf-8") + self.__logger.debug("stdout:\n%s", output) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + return not stdout.channel.recv_exit_status() def test_vnf(self): """Run test on ABoT.""" start_time = time.time() - self.__logger.info("Running VNF Test cases....") - cmd = ['juju', 'run-action', 'abot-epc-basic/0', 'run', - 'tagnames={}'.format(self.details['test_vnf']['tag_name'])] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - - cmd = ['timeout', JujuEpc.juju_timeout, 'juju-wait'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - + (_, stdout, stderr) = self.ssh.exec_command( + "/snap/bin/juju run-action abot-epc-basic/0 " + f"run tagnames={self.details['test_vnf']['tag_name']}") + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + if stdout.channel.recv_exit_status(): + return not stdout.channel.recv_exit_status() + (_, stdout, stderr) = self.ssh.exec_command( + 'PATH=/snap/bin/:$PATH ' + f'timeout {JujuEpc.juju_timeout} juju-wait') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + if stdout.channel.recv_exit_status(): + return not stdout.channel.recv_exit_status() duration = time.time() - start_time self.__logger.info("Getting results from Abot node....") - cmd = ['timeout', JujuEpc.juju_timeout, - 'juju', 'scp', '--', '-v', - 'abot-epc-basic/0:' - '/var/lib/abot-epc-basic/artifacts/TestResults.json', - '{}/.'.format(self.res_dir)] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) + (_, stdout, stderr) = self.ssh.exec_command( + f'timeout {JujuEpc.juju_timeout} /snap/bin/juju scp ' + '-- -v abot-epc-basic/0:' + '/var/lib/abot-epc-basic/artifacts/TestResults.json .') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + if stdout.channel.recv_exit_status(): + return not stdout.channel.recv_exit_status() + scpc = scp.SCPClient(self.ssh.get_transport()) + scpc.get('TestResults.json', self.res_dir) self.__logger.info("Parsing the Test results...") - res = (process_abot_test_result('{}/TestResults.json'.format( - self.res_dir))) + res = process_abot_test_result(f'{self.res_dir}/TestResults.json') short_result = sig_test_format(res) self.__logger.info(short_result) self.details['test_vnf'].update( @@ -369,51 +362,48 @@ class JujuEpc(singlevm.VmReady2): short_result['failures'], short_result['skipped']) return True - def run(self, **kwargs): - self.start_time = time.time() + def execute(self): + """Prepare testcase (Additional pre-configuration steps).""" + assert self.public_auth_url + self.__logger.info("Additional pre-configuration steps") try: - assert super(JujuEpc, self).run(**kwargs) == self.EX_OK - self.prepare() - if (self.deploy_orchestrator() and - self.deploy_vnf() and - self.test_vnf()): - self.stop_time = time.time() - self.result = 100 - return self.EX_OK - self.result = 0 - self.stop_time = time.time() - return self.EX_TESTCASE_FAILED + os.makedirs(self.res_dir) + except OSError as ex: + if ex.errno != errno.EEXIST: + self.__logger.exception("Cannot create %s", self.res_dir) + raise Exception from ex + self.__logger.info("ENV:\n%s", env.string()) + try: + assert self._install_juju() + assert self._install_juju_wait() + assert self._register_cloud() + assert self._register_credentials() + assert self.deploy_orchestrator() + assert self.deploy_vnf() + assert self.test_vnf() except Exception: # pylint: disable=broad-except - self.stop_time = time.time() - self.__logger.exception("Exception on VNF testing") - return self.EX_TESTCASE_FAILED + self.__logger.exception("juju_epc failed") + return 1 + return 0 def clean(self): """Clean created objects/functions.""" - try: - cmd = ['juju', 'debug-log', '--replay', '--no-tail'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.debug( - "%s\n%s", " ".join(cmd), output.decode("utf-8")) - self.__logger.info("Destroying Orchestrator...") - cmd = ['timeout', JujuEpc.juju_timeout, - 'juju', 'destroy-controller', '-y', 'abot-controller', - '--destroy-all-models'] - output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) - self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8")) - except subprocess.CalledProcessError as cpe: - self.__logger.error( - "Exception with Juju Cleanup: %s\n%s", - cpe.cmd, cpe.output.decode("utf-8")) - except Exception: # pylint: disable=broad-except - self.__logger.exception("General issue during the undeployment ..") + (_, stdout, stderr) = self.ssh.exec_command( + '/snap/bin/juju debug-log --replay --no-tail') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) + (_, stdout, stderr) = self.ssh.exec_command( + '/snap/bin/juju destroy-controller -y abot-controller ' + '--destroy-all-models') + self.__logger.debug("stdout:\n%s", stdout.read().decode("utf-8")) + self.__logger.debug("stderr:\n%s", stderr.read().decode("utf-8")) for fip in self.cloud.list_floating_ips(): self.cloud.delete_floating_ip(fip.id) if self.image_alt: self.cloud.delete_image(self.image_alt) if self.flavor_alt: self.orig_cloud.delete_flavor(self.flavor_alt.id) - super(JujuEpc, self).clean() + super().clean() def sig_test_format(sig_test): @@ -439,7 +429,7 @@ def sig_test_format(sig_test): def process_abot_test_result(file_path): """ Process ABoT Result """ - with open(file_path) as test_result: + with open(file_path, encoding='utf-8') as test_result: data = json.load(test_result) res = [] for tests in data: diff --git a/functest/opnfv_tests/vnf/ims/clearwater.py b/functest/opnfv_tests/vnf/ims/clearwater.py index 67128b11c..4c143fd70 100644 --- a/functest/opnfv_tests/vnf/ims/clearwater.py +++ b/functest/opnfv_tests/vnf/ims/clearwater.py @@ -50,7 +50,7 @@ class ClearwaterTesting(): output_dict = {} self.logger.debug('Ellis IP: %s', self.ellis_ip) output_dict['ellis_ip'] = self.ellis_ip - account_url = 'http://{0}/accounts'.format(self.ellis_ip) + account_url = f'http://{self.ellis_ip}/accounts' params = {"password": "functest", "full_name": "opnfv functest user", "email": "functest@opnfv.org", @@ -60,7 +60,7 @@ class ClearwaterTesting(): number_res = self._create_ellis_account(account_url, params) output_dict['number'] = number_res - session_url = 'http://{0}/session'.format(self.ellis_ip) + session_url = f'http://{self.ellis_ip}/session' session_data = { 'username': params['email'], 'password': params['password'], @@ -68,8 +68,8 @@ class ClearwaterTesting(): } cookies = self._get_ellis_session_cookies(session_url, session_data) - number_url = 'http://{0}/accounts/{1}/numbers'.format( - self.ellis_ip, params['email']) + number_url = ( + f"http://{self.ellis_ip}/accounts/{params['email']}/numbers") self.logger.debug('Create 1st calling number on Ellis') number_res = self._create_ellis_number(number_url, cookies) @@ -97,8 +97,7 @@ class ClearwaterTesting(): "try %s: cannot create ellis account", iloop + 1) time.sleep(30) raise Exception( - "Unable to create an account {}".format( - params.get('full_name'))) + f"Unable to create an account {params.get('full_name')}") def _get_ellis_session_cookies(self, session_url, params): i = 15 @@ -150,24 +149,20 @@ class ClearwaterTesting(): """ # pylint: disable=too-many-locals,too-many-arguments self.logger.info('Run Clearwater live test') - script = ('cd {0};' - 'rake test[{1}] SIGNUP_CODE={2}' - .format(self.test_dir, - public_domain, - signup_code)) + script = (f'cd {self.test_dir};' + f'rake test[{public_domain}] SIGNUP_CODE={signup_code}') if self.bono_ip and self.ellis_ip: - subscript = ' PROXY={0} ELLIS={1}'.format( - self.bono_ip, self.ellis_ip) - script = '{0}{1}'.format(script, subscript) - script = ('{0}{1}'.format(script, ' --trace')) - cmd = "/bin/bash -c '{0}'".format(script) + subscript = f' PROXY={self.bono_ip} ELLIS={self.ellis_ip}' + script = f'{script}{subscript}' + script = f'{script} --trace' + cmd = f"/bin/sh -c '{script}'" self.logger.debug('Live test cmd: %s', cmd) output_file = os.path.join(self.result_dir, "ims_test_output.txt") ft_utils.execute_command(cmd, error_msg='Clearwater live test failed', output_file=output_file) - with open(output_file, 'r') as ofile: + with open(output_file, 'r', encoding='utf-8') as ofile: result = ofile.read() if result != "": diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.py b/functest/opnfv_tests/vnf/ims/cloudify_ims.py index d937cc052..b93af7d6d 100644 --- a/functest/opnfv_tests/vnf/ims/cloudify_ims.py +++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py @@ -53,14 +53,14 @@ class CloudifyIms(cloudify.Cloudify): """Initialize CloudifyIms testcase object.""" if "case_name" not in kwargs: kwargs["case_name"] = "cloudify_ims" - super(CloudifyIms, self).__init__(**kwargs) + super().__init__(**kwargs) # Retrieve the configuration try: self.config = getattr( - config.CONF, 'vnf_{}_config'.format(self.case_name)) - except Exception: - raise Exception("VNF config file not found") + config.CONF, f'vnf_{self.case_name}_config') + except Exception as exc: + raise Exception("VNF config file not found") from exc self.case_dir = pkg_resources.resource_filename( 'functest', 'opnfv_tests/vnf/ims') @@ -114,7 +114,7 @@ class CloudifyIms(cloudify.Cloudify): network, security group, fip, VM creation """ - assert super(CloudifyIms, self).execute() == 0 + assert super().execute() == 0 start_time = time.time() self.orig_cloud.set_network_quotas( self.project.project.name, @@ -259,4 +259,4 @@ class CloudifyIms(cloudify.Cloudify): self.cloud.delete_image(self.image_alt) if self.flavor_alt: self.orig_cloud.delete_flavor(self.flavor_alt.id) - super(CloudifyIms, self).clean() + super().clean() diff --git a/functest/opnfv_tests/vnf/ims/heat_ims.py b/functest/opnfv_tests/vnf/ims/heat_ims.py index 4a57a7445..0d4e345a0 100644 --- a/functest/opnfv_tests/vnf/ims/heat_ims.py +++ b/functest/opnfv_tests/vnf/ims/heat_ims.py @@ -57,14 +57,14 @@ class HeatIms(singlevm.VmReady2): """Initialize HeatIms testcase object.""" if "case_name" not in kwargs: kwargs["case_name"] = "heat_ims" - super(HeatIms, self).__init__(**kwargs) + super().__init__(**kwargs) # Retrieve the configuration try: self.config = getattr( - config.CONF, 'vnf_{}_config'.format(self.case_name)) - except Exception: - raise Exception("VNF config file not found") + config.CONF, f'vnf_{self.case_name}_config') + except Exception as exc: + raise Exception("VNF config file not found") from exc self.case_dir = pkg_resources.resource_filename( 'functest', 'opnfv_tests/vnf/ims') @@ -112,9 +112,10 @@ class HeatIms(singlevm.VmReady2): project=self.project.project.id, domain=self.project.domain.id) self.keypair = self.cloud.create_keypair( - '{}-kp_{}'.format(self.case_name, self.guid)) + f'{self.case_name}-kp_{self.guid}') self.__logger.info("keypair:\n%s", self.keypair.private_key) - with open(self.key_filename, 'w') as private_key_file: + with open( + self.key_filename, 'w', encoding='utf-8') as private_key_file: private_key_file.write(self.keypair.private_key) if self.deploy_vnf() and self.test_vnf(): @@ -137,7 +138,7 @@ class HeatIms(singlevm.VmReady2): status = testcase.TestCase.EX_RUN_ERROR try: assert self.cloud - assert super(HeatIms, self).run( + assert super().run( **kwargs) == testcase.TestCase.EX_OK self.result = 0 if not self.execute(): @@ -162,7 +163,7 @@ class HeatIms(singlevm.VmReady2): server.public_v4, username=username, key_filename=self.key_filename, timeout=timeout) (_, stdout, _) = ssh.exec_command('sudo monit summary') - self.__logger.info("output:\n%s", stdout.read()) + self.__logger.info("output:\n%s", stdout.read().decode("utf-8")) ssh.close() def deploy_vnf(self): @@ -247,6 +248,6 @@ class HeatIms(singlevm.VmReady2): pass except Exception: # pylint: disable=broad-except self.__logger.exception("Cannot clean stack ressources") - super(HeatIms, self).clean() + super().clean() if self.role: self.orig_cloud.delete_role(self.role.id) diff --git a/functest/opnfv_tests/vnf/router/cloudify_vrouter.py b/functest/opnfv_tests/vnf/router/cloudify_vrouter.py index c793953d3..32d675347 100644 --- a/functest/opnfv_tests/vnf/router/cloudify_vrouter.py +++ b/functest/opnfv_tests/vnf/router/cloudify_vrouter.py @@ -40,6 +40,8 @@ class CloudifyVrouter(cloudify.Cloudify): flavor_alt_vcpus = 1 flavor_alt_disk = 3 + check_console_loop = 12 + cop_yaml = ("https://github.com/cloudify-cosmo/cloudify-openstack-plugin/" "releases/download/2.14.7/plugin.yaml") cop_wgn = ("https://github.com/cloudify-cosmo/cloudify-openstack-plugin/" @@ -49,14 +51,14 @@ class CloudifyVrouter(cloudify.Cloudify): def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = "vyos_vrouter" - super(CloudifyVrouter, self).__init__(**kwargs) + super().__init__(**kwargs) # Retrieve the configuration try: self.config = getattr( - config.CONF, 'vnf_{}_config'.format(self.case_name)) - except Exception: - raise Exception("VNF config file not found") + config.CONF, f'vnf_{self.case_name}_config') + except Exception as exc: + raise Exception("VNF config file not found") from exc self.case_dir = pkg_resources.resource_filename( 'functest', 'opnfv_tests/vnf/router') @@ -125,7 +127,7 @@ class CloudifyVrouter(cloudify.Cloudify): network, security group, fip, VM creation """ # network creation - super(CloudifyVrouter, self).execute() + super().execute() start_time = time.time() self.put_private_key() self.upload_cfy_plugins(self.cop_yaml, self.cop_wgn) @@ -229,4 +231,4 @@ class CloudifyVrouter(cloudify.Cloudify): self.cloud.delete_image(self.image_alt) if self.flavor_alt: self.orig_cloud.delete_flavor(self.flavor_alt.id) - super(CloudifyVrouter, self).clean() + super().clean() diff --git a/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py b/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py index 0a56913b7..9eb3c5d69 100644 --- a/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py +++ b/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py @@ -32,17 +32,16 @@ class FunctionTestExec(): credentials = util_info["credentials"] self.vnf_ctrl = VnfController(util_info) - test_cmd_map_file = open( - os.path.join( - self.util.vnf_data_dir, self.util.command_template_dir, - self.util.test_cmd_map_yaml_file), - 'r') - self.test_cmd_map_yaml = yaml.safe_load(test_cmd_map_file) - test_cmd_map_file.close() + with open( + os.path.join( + self.util.vnf_data_dir, self.util.command_template_dir, + self.util.test_cmd_map_yaml_file), + 'r', encoding='utf-8') as test_cmd_map_file: + self.test_cmd_map_yaml = yaml.safe_load(test_cmd_map_file) self.util.set_credentials(credentials["cloud"]) - with open(self.util.test_env_config_yaml) as file_fd: + with open(self.util.test_env_config_yaml, encoding='utf-8') as file_fd: test_env_config_yaml = yaml.safe_load(file_fd) file_fd.close() diff --git a/functest/opnfv_tests/vnf/router/utilvnf.py b/functest/opnfv_tests/vnf/router/utilvnf.py index 2db3b38e5..111f20c1a 100644 --- a/functest/opnfv_tests/vnf/router/utilvnf.py +++ b/functest/opnfv_tests/vnf/router/utilvnf.py @@ -64,7 +64,7 @@ class Utilvnf(): # pylint: disable=too-many-instance-attributes if not os.path.exists(self.vnf_data_dir): os.makedirs(self.vnf_data_dir) - with open(self.test_env_config_yaml) as file_fd: + with open(self.test_env_config_yaml, encoding='utf-8') as file_fd: test_env_config_yaml = yaml.safe_load(file_fd) file_fd.close() @@ -98,9 +98,7 @@ class Utilvnf(): # pylint: disable=too-many-instance-attributes return mac_address def get_blueprint_outputs(self, cfy_manager_ip, deployment_name): - url = "http://%s/deployments/%s/outputs" % ( - cfy_manager_ip, deployment_name) - + url = f"http://{cfy_manager_ip}/deployments/{deployment_name}/outputs" response = requests.get( url, auth=requests.auth.HTTPBasicAuth('admin', 'admin'), @@ -212,24 +210,29 @@ class Utilvnf(): # pylint: disable=too-many-instance-attributes def write_result_data(self, result_data): test_result = [] if not os.path.isfile(self.test_result_json_file): - file_fd = open(self.test_result_json_file, "w") - file_fd.close() + with open( + self.test_result_json_file, "w", + encoding="utf-8") as file_fd: + pass else: - file_fd = open(self.test_result_json_file, "r") - test_result = json.load(file_fd) - file_fd.close() + with open( + self.test_result_json_file, "r", + encoding="utf-8") as file_fd: + test_result = json.load(file_fd) test_result.append(result_data) - file_fd = open(self.test_result_json_file, "w") - json.dump(test_result, file_fd) - file_fd.close() + with open( + self.test_result_json_file, "w", + encoding="utf-8") as file_fd: + json.dump(test_result, file_fd) def output_test_result_json(self): if os.path.isfile(self.test_result_json_file): - file_fd = open(self.test_result_json_file, "r") - test_result = json.load(file_fd) - file_fd.close() + with open( + self.test_result_json_file, "r", + encoding="utf-8") as file_fd: + test_result = json.load(file_fd) output_json_data = json.dumps(test_result, sort_keys=True, indent=4) @@ -239,8 +242,6 @@ class Utilvnf(): # pylint: disable=too-many-instance-attributes @staticmethod def get_test_scenario(file_path): - test_scenario_file = open(file_path, - 'r') - test_scenario_yaml = yaml.safe_load(test_scenario_file) - test_scenario_file.close() + with open(file_path, "r", encoding="utf-8") as test_scenario_file: + test_scenario_yaml = yaml.safe_load(test_scenario_file) return test_scenario_yaml["test_scenario_list"] diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py b/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py index 0969eab3b..269f6526b 100644 --- a/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py +++ b/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py @@ -43,7 +43,7 @@ class SshClient(): # pylint: disable=too-many-instance-attributes self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.util = Utilvnf() - with open(self.util.test_env_config_yaml) as file_fd: + with open(self.util.test_env_config_yaml, encoding='utf-8') as file_fd: test_env_config_yaml = yaml.safe_load(file_fd) file_fd.close() diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py b/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py index b159ddda4..2210b3909 100644 --- a/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py +++ b/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py @@ -36,7 +36,7 @@ class VmController(): self.util = Utilvnf() self.util.set_credentials(credentials["cloud"]) - with open(self.util.test_env_config_yaml) as file_fd: + with open(self.util.test_env_config_yaml, encoding='utf-8') as file_fd: test_env_config_yaml = yaml.safe_load(file_fd) file_fd.close() @@ -101,10 +101,8 @@ class VmController(): def command_create_and_execute(self, ssh, test_cmd_file_path, cmd_input_param, prompt_file_path): - prompt_file = open(prompt_file_path, - 'r') - prompt = yaml.safe_load(prompt_file) - prompt_file.close() + with open(prompt_file_path, 'r', encoding='utf-8') as prompt_file: + prompt = yaml.safe_load(prompt_file) config_mode_prompt = prompt["config_mode"] commands = self.command_gen_from_template(test_cmd_file_path, diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py b/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py index 7ed287c6e..46584456f 100644 --- a/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py +++ b/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py @@ -36,7 +36,7 @@ class VnfController(): self.util = Utilvnf() self.vm_controller = VmController(util_info) - with open(self.util.test_env_config_yaml) as file_fd: + with open(self.util.test_env_config_yaml, encoding='utf-8') as file_fd: test_env_config_yaml = yaml.safe_load(file_fd) file_fd.close() @@ -49,10 +49,9 @@ class VnfController(): def config_vnf(self, source_vnf, destination_vnf, test_cmd_file_path, parameter_file_path, prompt_file_path): # pylint: disable=too-many-arguments - parameter_file = open(parameter_file_path, - 'r') - cmd_input_param = yaml.safe_load(parameter_file) - parameter_file.close() + with open( + parameter_file_path, 'r', encoding='utf-8') as parameter_file: + cmd_input_param = yaml.safe_load(parameter_file) cmd_input_param["macaddress"] = source_vnf["data_plane_network_mac"] cmd_input_param["source_ip"] = source_vnf["data_plane_network_ip"] @@ -71,19 +70,16 @@ class VnfController(): res_dict_data_list = [] - parameter_file = open(parameter_file_path, - 'r') - cmd_input_param = yaml.safe_load(parameter_file) - parameter_file.close() + with open( + parameter_file_path, 'r', encoding='utf-8') as parameter_file: + cmd_input_param = yaml.safe_load(parameter_file) cmd_input_param["source_ip"] = target_vnf["data_plane_network_ip"] cmd_input_param["destination_ip"] = reference_vnf[ "data_plane_network_ip"] - prompt_file = open(prompt_file_path, - 'r') - prompt = yaml.safe_load(prompt_file) - prompt_file.close() + with open(prompt_file_path, 'r', encoding='utf-8') as prompt_file: + prompt = yaml.safe_load(prompt_file) terminal_mode_prompt = prompt["terminal_mode"] ssh = SshClient(target_vnf["floating_ip"], diff --git a/functest/tests/unit/odl/test_odl.py b/functest/tests/unit/odl/test_odl.py index 1b2e10b07..c675c2988 100644 --- a/functest/tests/unit/odl/test_odl.py +++ b/functest/tests/unit/odl/test_odl.py @@ -33,10 +33,10 @@ class ODLTesting(unittest.TestCase): logging.disable(logging.CRITICAL) _keystone_ip = "127.0.0.1" - _neutron_url = u"https://127.0.0.1:9696" - _neutron_id = u"dummy" + _neutron_url = "https://127.0.0.1:9696" + _neutron_id = "dummy" _sdn_controller_ip = "127.0.0.3" - _os_auth_url = "http://{}:5000/v3".format(_keystone_ip) + _os_auth_url = f"http://{_keystone_ip}:5000/v3" _os_projectname = "admin" _os_username = "admin" _os_password = "admin" @@ -63,8 +63,7 @@ class ODLTesting(unittest.TestCase): self.test = odl.ODLTests(case_name='odl', project_name='functest') self.defaultargs = {'odlusername': self._odl_username, 'odlpassword': self._odl_password, - 'neutronurl': "http://{}:9696".format( - self._keystone_ip), + 'neutronurl': f"http://{self._keystone_ip}:9696", 'osauthurl': self._os_auth_url, 'osusername': self._os_username, 'osuserdomainname': self._os_userdomainname, @@ -105,7 +104,7 @@ class ODLRobotTesting(ODLTesting): mock_method.assert_called_once_with( os.path.join(odl.ODLTests.odl_test_repo, 'csit/variables/Variables.robot'), inplace=True) - self.assertEqual(args[0].getvalue(), "{}\n".format(msg2)) + self.assertEqual(args[0].getvalue(), f"{msg2}\n") def test_set_vars_auth_default(self): self._test_set_vars( @@ -160,19 +159,19 @@ class ODLMainTesting(ODLTesting): args[0].assert_called_once_with(self.test.odl_variables_file) if len(args) > 1: variable = [ - 'KEYSTONEURL:{}://{}'.format( - urllib.parse.urlparse(self._os_auth_url).scheme, - urllib.parse.urlparse(self._os_auth_url).netloc), - 'NEUTRONURL:{}'.format(self._neutron_url), - 'OS_AUTH_URL:"{}"'.format(self._os_auth_url), - 'OSUSERNAME:"{}"'.format(self._os_username), - 'OSUSERDOMAINNAME:"{}"'.format(self._os_userdomainname), - 'OSTENANTNAME:"{}"'.format(self._os_projectname), - 'OSPROJECTDOMAINNAME:"{}"'.format(self._os_projectdomainname), - 'OSPASSWORD:"{}"'.format(self._os_password), - 'ODL_SYSTEM_IP:{}'.format(self._sdn_controller_ip), - 'PORT:{}'.format(self._odl_webport), - 'RESTCONFPORT:{}'.format(self._odl_restconfport)] + ('KEYSTONEURL:' + f'{urllib.parse.urlparse(self._os_auth_url).scheme}://' + f'{urllib.parse.urlparse(self._os_auth_url).netloc}'), + f'NEUTRONURL:{self._neutron_url}', + f'OS_AUTH_URL:"{self._os_auth_url}"', + f'OSUSERNAME:"{self._os_username}"', + f'OSUSERDOMAINNAME:"{self._os_userdomainname}"', + f'OSTENANTNAME:"{self._os_projectname}"', + f'OSPROJECTDOMAINNAME:"{self._os_projectdomainname}"', + f'OSPASSWORD:"{self._os_password}"', + f'ODL_SYSTEM_IP:{self._sdn_controller_ip}', + f'PORT:{self._odl_webport}', + f'RESTCONFPORT:{self._odl_restconfport}'] args[1].assert_called_once_with( odl.ODLTests.basic_suite_dir, odl.ODLTests.neutron_suite_dir, include=[], @@ -541,7 +540,7 @@ class ODLArgParserTesting(ODLTesting): def setUp(self): self.parser = odl.ODLParser() - super(ODLArgParserTesting, self).setUp() + super().setUp() def test_default(self): self.assertEqual(self.parser.parse_args(), self.defaultargs) @@ -551,8 +550,8 @@ class ODLArgParserTesting(ODLTesting): self.defaultargs['odlip'] = self._sdn_controller_ip self.assertEqual( self.parser.parse_args( - ["--neutronurl={}".format(self._neutron_url), - "--odlip={}".format(self._sdn_controller_ip)]), + [f"--neutronurl={self._neutron_url}", + f"--odlip={self._sdn_controller_ip}"]), self.defaultargs) @mock.patch('sys.stderr', new_callable=six.StringIO) @@ -565,7 +564,7 @@ class ODLArgParserTesting(ODLTesting): def _test_arg(self, arg, value): self.defaultargs[arg] = value self.assertEqual( - self.parser.parse_args(["--{}={}".format(arg, value)]), + self.parser.parse_args([f"--{arg}={value}"]), self.defaultargs) def test_odlusername(self): @@ -606,7 +605,7 @@ class ODLArgParserTesting(ODLTesting): def test_pushtodb(self): self.defaultargs['pushtodb'] = True - self.assertEqual(self.parser.parse_args(["--{}".format('pushtodb')]), + self.assertEqual(self.parser.parse_args(["--pushtodb"]), self.defaultargs) def test_multiple_args(self): @@ -614,8 +613,8 @@ class ODLArgParserTesting(ODLTesting): self.defaultargs['odlip'] = self._sdn_controller_ip self.assertEqual( self.parser.parse_args( - ["--neutronurl={}".format(self._neutron_url), - "--odlip={}".format(self._sdn_controller_ip)]), + [f"--neutronurl={self._neutron_url}", + f"--odlip={self._sdn_controller_ip}"]), self.defaultargs) diff --git a/functest/tests/unit/openstack/cinder/test_cinder.py b/functest/tests/unit/openstack/cinder/test_cinder.py index 4052408d9..d3c9cabb6 100644 --- a/functest/tests/unit/openstack/cinder/test_cinder.py +++ b/functest/tests/unit/openstack/cinder/test_cinder.py @@ -59,7 +59,7 @@ class CinderTesting(unittest.TestCase): self.cinder.prepare() args[0].assert_called_with() args[1].assert_called_once_with( - '{}-vm2_{}'.format(self.cinder.case_name, self.cinder.guid), + f'{self.cinder.case_name}-vm2_{self.cinder.guid}', security_groups=[self.cinder.sec.id], key_name=self.cinder.keypair.id) self.cinder.cloud.create_volume.assert_not_called() @@ -81,13 +81,12 @@ class CinderTesting(unittest.TestCase): self.cinder.prepare() args[0].assert_called_once_with() args[1].assert_called_once_with( - '{}-vm2_{}'.format(self.cinder.case_name, self.cinder.guid), + f'{self.cinder.case_name}-vm2_{self.cinder.guid}', security_groups=[self.cinder.sec.id], key_name=self.cinder.keypair.id) self.cinder.connect.assert_called_once_with(args[1].return_value) self.cinder.cloud.create_volume.assert_called_once_with( - name='{}-volume_{}'.format( - self.cinder.case_name, self.cinder.guid), + name=f'{self.cinder.case_name}-volume_{self.cinder.guid}', size='2', timeout=self.cinder.volume_timeout, wait=True) @mock.patch('scp.SCPClient.put') @@ -101,7 +100,7 @@ class CinderTesting(unittest.TestCase): self.cinder.ssh.exec_command.return_value = (None, stdout, mock.Mock()) self.assertEqual(self.cinder._write_data(), 0) self.cinder.ssh.exec_command.assert_called_once_with( - "sh ~/write_data.sh {}".format(env.get('VOLUME_DEVICE_NAME'))) + f"sh ~/write_data.sh {env.get('VOLUME_DEVICE_NAME')}") self.cinder.cloud.attach_volume.assert_called_once_with( self.cinder.sshvm, self.cinder.volume, timeout=self.cinder.volume_timeout) @@ -138,7 +137,7 @@ class CinderTesting(unittest.TestCase): stdout.channel.recv_exit_status.return_value = 0 self.assertEqual(self.cinder._read_data(), 0) self.cinder.ssh2.exec_command.assert_called_once_with( - "sh ~/read_data.sh {}".format(env.get('VOLUME_DEVICE_NAME'))) + f"sh ~/read_data.sh {env.get('VOLUME_DEVICE_NAME')}") self.cinder.cloud.attach_volume.assert_called_once_with( self.cinder.vm2, self.cinder.volume, timeout=self.cinder.volume_timeout) diff --git a/functest/tests/unit/openstack/rally/test_rally.py b/functest/tests/unit/openstack/rally/test_rally.py index c5cd5019e..f3c2e7cf6 100644 --- a/functest/tests/unit/openstack/rally/test_rally.py +++ b/functest/tests/unit/openstack/rally/test_rally.py @@ -50,7 +50,7 @@ class OSRallyTesting(unittest.TestCase): @staticmethod def check_scenario_file(value): - yaml_file = 'opnfv-{}.yaml'.format('test_file_name') + yaml_file = 'opnfv-test_file_name.yaml' if yaml_file in value: return False return True @@ -64,7 +64,7 @@ class OSRallyTesting(unittest.TestCase): @staticmethod def check_temp_dir(value): - yaml_file = 'opnfv-{}.yaml'.format('test_file_name') + yaml_file = 'opnfv-test_file_name.yaml' if yaml_file in value: return True return False @@ -95,7 +95,7 @@ class OSRallyTesting(unittest.TestCase): self, mock_method, mock_os_makedirs, mock_path_exists): mock_path_exists.side_effect = self.check_temp_dir - yaml_file = 'opnfv-{}.yaml'.format('test_file_name') + yaml_file = 'opnfv-test_file_name.yaml' ret_val = os.path.join(self.rally_base.temp_dir, yaml_file) self.assertEqual(self.rally_base._prepare_test_list('test_file_name'), ret_val) @@ -103,15 +103,19 @@ class OSRallyTesting(unittest.TestCase): mock_method.assert_called() mock_os_makedirs.assert_called() - def test_get_task_id_default(self): - cmd_raw = b'Task 1: started' - self.assertEqual(self.rally_base.get_task_id(cmd_raw), - '1') + @mock.patch('subprocess.check_output', return_value=b'1\n') + def test_get_task_id_default(self, *args): + tag = 'nova' + self.assertEqual(self.rally_base.get_task_id(tag), '1') + args[0].assert_called_with( + ['rally', 'task', 'list', '--tag', tag, '--uuids-only']) - def test_get_task_id_missing_id(self): - cmd_raw = b'' - self.assertEqual(self.rally_base.get_task_id(cmd_raw), - None) + @mock.patch('subprocess.check_output', return_value=b'\n') + def test_get_task_id_missing_id(self, *args): + tag = 'nova' + self.assertEqual(self.rally_base.get_task_id(tag), '') + args[0].assert_called_with( + ['rally', 'task', 'list', '--tag', tag, '--uuids-only']) def test_task_succeed_fail(self): json_raw = json.dumps({}) @@ -291,8 +295,8 @@ class OSRallyTesting(unittest.TestCase): def test_prepare_run_flavor_alt_creation_failed(self, *args): # pylint: disable=unused-argument self.rally_base.stests = ['test1', 'test2'] - with mock.patch.object(self.rally_base.cloud, - 'list_hypervisors') as mock_list_hyperv, \ + with mock.patch.object(self.rally_base, 'count_hypervisors') \ + as mock_list_hyperv, \ mock.patch.object(self.rally_base, 'create_flavor_alt', side_effect=Exception) \ as mock_create_flavor: @@ -419,8 +423,8 @@ class OSRallyTesting(unittest.TestCase): @mock.patch('subprocess.check_output', side_effect=subprocess.CalledProcessError('', '')) def test_export_task_ko(self, *args): - file_name = "{}/{}.html".format( - self.rally_base.results_dir, self.rally_base.case_name) + file_name = (f"{self.rally_base.results_dir}/" + f"{self.rally_base.case_name}.html") with self.assertRaises(subprocess.CalledProcessError): self.rally_base.export_task(file_name) cmd = ["rally", "task", "export", "--type", "html", "--deployment", @@ -430,8 +434,8 @@ class OSRallyTesting(unittest.TestCase): @mock.patch('subprocess.check_output', return_value=b'') def test_export_task(self, *args): - file_name = "{}/{}.html".format( - self.rally_base.results_dir, self.rally_base.case_name) + file_name = (f"{self.rally_base.results_dir}/" + f"{self.rally_base.case_name}.html") self.assertEqual(self.rally_base.export_task(file_name), None) cmd = ["rally", "task", "export", "--type", "html", "--deployment", str(getattr(config.CONF, 'rally_deployment_name')), @@ -441,8 +445,8 @@ class OSRallyTesting(unittest.TestCase): @mock.patch('subprocess.check_output', side_effect=subprocess.CalledProcessError('', '')) def test_verify_report_ko(self, *args): - file_name = "{}/{}.html".format( - self.rally_base.results_dir, self.rally_base.case_name) + file_name = (f"{self.rally_base.results_dir}/" + f"{self.rally_base.case_name}.html") with self.assertRaises(subprocess.CalledProcessError): self.rally_base.verify_report(file_name, "1") cmd = ["rally", "verify", "report", "--type", "html", "--uuid", "1", @@ -451,8 +455,8 @@ class OSRallyTesting(unittest.TestCase): @mock.patch('subprocess.check_output', return_value=b'') def test_verify_report(self, *args): - file_name = "{}/{}.html".format( - self.rally_base.results_dir, self.rally_base.case_name) + file_name = (f"{self.rally_base.results_dir}/" + f"{self.rally_base.case_name}.html") self.assertEqual(self.rally_base.verify_report(file_name, "1"), None) cmd = ["rally", "verify", "report", "--type", "html", "--uuid", "1", "--to", file_name] diff --git a/functest/tests/unit/openstack/tempest/test_tempest.py b/functest/tests/unit/openstack/tempest/test_tempest.py index 87438ae7c..efc4393c8 100644 --- a/functest/tests/unit/openstack/tempest/test_tempest.py +++ b/functest/tests/unit/openstack/tempest/test_tempest.py @@ -83,8 +83,8 @@ class OSTempestTesting(unittest.TestCase): testr_mode = self.tempestcommon.mode verifier_repo_dir = 'test_verifier_repo_dir' self.tempestcommon.verifier_repo_dir = verifier_repo_dir - cmd = "(cd {0}; stestr list '{1}' >{2} 2>/dev/null)".format( - verifier_repo_dir, testr_mode, self.tempestcommon.list) + cmd = (f"(cd {verifier_repo_dir}; stestr list '{testr_mode}' > " + f"{self.tempestcommon.list} 2>/dev/null)") self.tempestcommon.generate_test_list(mode=testr_mode) args[0].assert_called_once_with(cmd, shell=True) args[2].assert_called_once_with('/etc/tempest.conf') @@ -125,7 +125,8 @@ class OSTempestTesting(unittest.TestCase): return_value=['test1', 'test2']): self.tempestcommon.tempest_blacklist = Exception os.environ['DEPLOY_SCENARIO'] = 'deploy_scenario' - self.tempestcommon.apply_tempest_blacklist() + self.tempestcommon.apply_tempest_blacklist( + self.tempestcommon.tempest_blacklist) obj = mock_open() obj.write.assert_any_call('test1\n') obj.write.assert_any_call('test2\n') @@ -147,7 +148,8 @@ class OSTempestTesting(unittest.TestCase): mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' 'yaml.safe_load', return_value=item_dict): os.environ['DEPLOY_SCENARIO'] = 'deploy_scenario' - self.tempestcommon.apply_tempest_blacklist() + self.tempestcommon.apply_tempest_blacklist( + self.tempestcommon.tempest_blacklist) obj = mock_open() obj.write.assert_any_call('test1\n') self.assertFalse(obj.write.assert_any_call('test2\n')) @@ -156,20 +158,17 @@ class OSTempestTesting(unittest.TestCase): args[2].assert_called_once_with( self.tempestcommon.list, self.tempestcommon.raw_list) + @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' + 'subprocess.Popen') + @mock.patch('six.moves.builtins.open', mock.mock_open()) @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.LOGGER.info') - def test_run_verifier_tests_default(self, mock_logger_info): - with mock.patch('six.moves.builtins.open', mock.mock_open()), \ - mock.patch('six.moves.builtins.iter', - return_value=[r'\} tempest\.']), \ - mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' - 'subprocess.Popen'): - self.tempestcommon.tempest_list = 'test_tempest_list' - cmd = ["rally", "verify", "start", "--load-list", - self.tempestcommon.tempest_list] - with self.assertRaises(Exception): - self.tempestcommon.run_verifier_tests() - mock_logger_info. \ - assert_any_call("Starting Tempest test suite: '%s'.", cmd) + def test_run_verifier_tests_default(self, *args): + self.tempestcommon.tempest_list = 'test_tempest_list' + cmd = ["rally", "verify", "start", "--load-list", + self.tempestcommon.tempest_list] + with self.assertRaises(Exception): + self.tempestcommon.run_verifier_tests() + args[0].assert_any_call("Starting Tempest test suite: '%s'.", cmd) @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' 'os.path.exists', return_value=False) @@ -270,10 +269,9 @@ class OSTempestTesting(unittest.TestCase): with mock.patch('functest.opnfv_tests.openstack.tempest.' 'tempest.subprocess.Popen') as mock_popen: - mock_stdout = mock.Mock() - attrs = {'stdout.readline.return_value': b'test_deploy_id'} - mock_stdout.configure_mock(**attrs) - mock_popen.return_value = mock_stdout + attrs = {'return_value.__enter__.return_value.' + 'stdout.readline.return_value': b'test_deploy_id'} + mock_popen.configure_mock(**attrs) self.assertEqual(self.tempestcommon.get_verifier_id(), 'test_deploy_id') @@ -282,10 +280,9 @@ class OSTempestTesting(unittest.TestCase): setattr(config.CONF, 'tempest_verifier_name', 'test_deploy_name') with mock.patch('functest.opnfv_tests.openstack.tempest.' 'tempest.subprocess.Popen') as mock_popen: - mock_stdout = mock.Mock() - attrs = {'stdout.readline.return_value': b'test_deploy_id'} - mock_stdout.configure_mock(**attrs) - mock_popen.return_value = mock_stdout + attrs = {'return_value.__enter__.return_value.' + 'stdout.readline.return_value': b'test_deploy_id'} + mock_popen.configure_mock(**attrs) self.assertEqual(rally.RallyBase.get_verifier_deployment_id(), 'test_deploy_id') diff --git a/functest/tests/unit/openstack/vmtp/test_vmtp.py b/functest/tests/unit/openstack/vmtp/test_vmtp.py index fcbb0c46b..850273476 100644 --- a/functest/tests/unit/openstack/vmtp/test_vmtp.py +++ b/functest/tests/unit/openstack/vmtp/test_vmtp.py @@ -66,21 +66,22 @@ class VmtpTesting(unittest.TestCase): def test_generate_keys1(self, *args): self.testcase.generate_keys() self.testcase.cloud.create_keypair.assert_called_once_with( - 'vmtp_{}'.format(self.testcase.guid)) + f'vmtp_{self.testcase.guid}') self.testcase.cloud.delete_keypair.assert_called_once_with('id') - calls = [mock.call(self.testcase.privkey_filename, 'w'), - mock.call(self.testcase.pubkey_filename, 'w')] + calls = [mock.call( + self.testcase.privkey_filename, 'w', encoding='utf-8'), + mock.call( + self.testcase.pubkey_filename, 'w', encoding='utf-8')] args[0].assert_has_calls(calls, any_order=True) @mock.patch('six.moves.builtins.open') def test_generate_keys2(self, *args): - # pylint: disable=bad-continuation with mock.patch.object( self.testcase.cloud, "create_keypair", side_effect=shade.OpenStackCloudException(None)) as mock_obj, \ self.assertRaises(shade.OpenStackCloudException): self.testcase.generate_keys() - mock_obj.assert_called_once_with('vmtp_{}'.format(self.testcase.guid)) + mock_obj.assert_called_once_with(f'vmtp_{self.testcase.guid}') args[0].assert_not_called() diff --git a/functest/tests/unit/openstack/vping/test_vping_ssh.py b/functest/tests/unit/openstack/vping/test_vping_ssh.py index 05482ed6b..a07148aab 100644 --- a/functest/tests/unit/openstack/vping/test_vping_ssh.py +++ b/functest/tests/unit/openstack/vping/test_vping_ssh.py @@ -47,7 +47,7 @@ class VpingSSHTesting(unittest.TestCase): self.vping.prepare() args[0].assert_called_once_with() args[1].assert_called_once_with( - '{}-vm2_{}'.format(self.vping.case_name, self.vping.guid), + f'{self.vping.case_name}-vm2_{self.vping.guid}', security_groups=[self.vping.sec.id]) @mock.patch('functest.opnfv_tests.openstack.vping.vping_ssh.VPingSSH.' @@ -58,27 +58,43 @@ class VpingSSHTesting(unittest.TestCase): self.vping.prepare() args[0].assert_called_once_with() args[1].assert_called_once_with( - '{}-vm2_{}'.format(self.vping.case_name, self.vping.guid), + f'{self.vping.case_name}-vm2_{self.vping.guid}', security_groups=[self.vping.sec.id]) - def test_execute_exc(self): - self.vping.vm2 = munch.Munch(private_v4='127.0.0.1') + @mock.patch('functest.opnfv_tests.openstack.vping.vping_ssh.VPingSSH.' + 'check_regex_in_console', return_value=True) + def test_execute_exc(self, *args): + self.vping.vm2 = munch.Munch(private_v4='127.0.0.1', name='foo') self.vping.ssh = mock.Mock() self.vping.ssh.exec_command.side_effect = ssh_exception.SSHException with self.assertRaises(ssh_exception.SSHException): self.vping.execute() self.vping.ssh.exec_command.assert_called_once_with( - 'ping -c 1 {}'.format(self.vping.vm2.private_v4)) + f'ping -c 1 {self.vping.vm2.private_v4}') + args[0].assert_called_once_with('foo') + + @mock.patch('functest.opnfv_tests.openstack.vping.vping_ssh.VPingSSH.' + 'check_regex_in_console', return_value=False) + def test_execute_exc2(self, *args): + self.vping.vm2 = munch.Munch(private_v4='127.0.0.1', name='foo') + self.vping.ssh = mock.Mock() + self.vping.execute() + self.vping.ssh.exec_command.assert_not_called() + args[0].assert_called_once_with('foo') def _test_execute(self, ret=0): - self.vping.vm2 = munch.Munch(private_v4='127.0.0.1') + self.vping.vm2 = munch.Munch(private_v4='127.0.0.1', name='foo') self.vping.ssh = mock.Mock() stdout = mock.Mock() stdout.channel.recv_exit_status.return_value = ret self.vping.ssh.exec_command.return_value = (None, stdout, mock.Mock()) - self.assertEqual(self.vping.execute(), ret) + with mock.patch( + 'functest.opnfv_tests.openstack.vping.vping_ssh.VPingSSH.' + 'check_regex_in_console', return_value=True) as mock_check: + self.assertEqual(self.vping.execute(), ret) + mock_check.assert_called_once_with('foo') self.vping.ssh.exec_command.assert_called_once_with( - 'ping -c 1 {}'.format(self.vping.vm2.private_v4)) + f'ping -c 1 {self.vping.vm2.private_v4}') def test_execute1(self): self._test_execute() diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py index f6a80e264..4b642ff9d 100644 --- a/functest/tests/unit/utils/test_functest_utils.py +++ b/functest/tests/unit/utils/test_functest_utils.py @@ -100,17 +100,18 @@ class FunctestUtilsTesting(unittest.TestCase): mock.mock_open()) as mopen: stream = six.BytesIO() stream.write(self.cmd_readline().encode("utf-8")) - mock_obj2 = mock.Mock() - attrs = {'stdout': stream, 'wait.return_value': 1} - mock_obj2.configure_mock(**attrs) - mock_subproc_open.return_value = mock_obj2 + attrs = { + 'return_value.__enter__.return_value.stdout': stream, + 'return_value.__enter__.return_value.wait.return_value': 1} + mock_subproc_open.configure_mock(**attrs) resp = functest_utils.execute_command( self.cmd, info=True, error_msg=self.error_msg, verbose=True, output_file=self.output_file) self.assertEqual(resp, 1) - msg_exec = ("Executing command: '%s'" % self.cmd) + msg_exec = f"Executing command: '{self.cmd}'" mock_logger_info.assert_called_once_with(msg_exec) - mopen.assert_called_once_with(self.output_file, "w") + mopen.assert_called_once_with( + self.output_file, "w", encoding='utf-8') mock_logger_error.assert_called_once_with(self.error_msg) @mock.patch('functest.utils.functest_utils.LOGGER.info') @@ -121,17 +122,18 @@ class FunctestUtilsTesting(unittest.TestCase): mock.mock_open()) as mopen: stream = six.BytesIO() stream.write(self.cmd_readline().encode("utf-8")) - mock_obj2 = mock.Mock() - attrs = {'stdout': stream, 'wait.return_value': 0} - mock_obj2.configure_mock(**attrs) - mock_subproc_open.return_value = mock_obj2 + attrs = { + 'return_value.__enter__.return_value.stdout': stream, + 'return_value.__enter__.return_value.wait.return_value': 0} + mock_subproc_open.configure_mock(**attrs) resp = functest_utils.execute_command( self.cmd, info=True, error_msg=self.error_msg, verbose=True, output_file=self.output_file) self.assertEqual(resp, 0) - msg_exec = ("Executing command: '%s'" % self.cmd) + msg_exec = (f"Executing command: '{self.cmd}'") mock_logger_info.assert_called_once_with(msg_exec) - mopen.assert_called_once_with(self.output_file, "w") + mopen.assert_called_once_with( + self.output_file, "w", encoding='utf-8') @mock.patch('sys.stdout') def test_exec_cmd_args_missing_ok(self, stdout=None): @@ -140,10 +142,10 @@ class FunctestUtilsTesting(unittest.TestCase): as mock_subproc_open: stream = six.BytesIO() stream.write(self.cmd_readline().encode("utf-8")) - mock_obj2 = mock.Mock() - attrs = {'stdout': stream, 'wait.return_value': 0} - mock_obj2.configure_mock(**attrs) - mock_subproc_open.return_value = mock_obj2 + attrs = { + 'return_value.__enter__.return_value.stdout': stream, + 'return_value.__enter__.return_value.wait.return_value': 0} + mock_subproc_open.configure_mock(**attrs) resp = functest_utils.execute_command( self.cmd, info=False, error_msg="", verbose=False, output_file=None) @@ -154,12 +156,13 @@ class FunctestUtilsTesting(unittest.TestCase): # pylint: disable=unused-argument with mock.patch('functest.utils.functest_utils.subprocess.Popen') \ as mock_subproc_open: + attrs = {} stream = six.BytesIO() stream.write(self.cmd_readline().encode("utf-8")) - mock_obj2 = mock.Mock() - attrs = {'stdout': stream, 'wait.return_value': 1} - mock_obj2.configure_mock(**attrs) - mock_subproc_open.return_value = mock_obj2 + attrs = { + 'return_value.__enter__.return_value.stdout': stream, + 'return_value.__enter__.return_value.wait.return_value': 1} + mock_subproc_open.configure_mock(**attrs) resp = functest_utils.execute_command( self.cmd, info=False, error_msg="", verbose=False, output_file=None) @@ -174,9 +177,9 @@ class FunctestUtilsTesting(unittest.TestCase): mock_yaml.return_value = self.file_yaml functest_utils.get_parameter_from_yaml(self.parameter, self.test_file) - self.assertTrue(("The parameter %s is not" - " defined in config_functest.yaml" % - self.parameter) in excep.exception) + self.assertTrue((f"The parameter {self.parameter} is not" + " defined in config_functest.yaml" + ) in excep.exception) def test_get_param_from_yaml_def(self): with mock.patch('six.moves.builtins.open', mock.mock_open()), \ @@ -309,6 +312,46 @@ class FunctestUtilsTesting(unittest.TestCase): args[0].assert_called_once_with(cloud) @mock.patch('functest.utils.functest_utils.get_nova_version', + return_value=(2, 78)) + def test_openstack_version12(self, *args): + cloud = mock.Mock() + self.assertEqual(functest_utils.get_openstack_version( + cloud), "Train") + args[0].assert_called_once_with(cloud) + + @mock.patch('functest.utils.functest_utils.get_nova_version', + return_value=(2, 87)) + def test_openstack_version13(self, *args): + cloud = mock.Mock() + self.assertEqual(functest_utils.get_openstack_version( + cloud), "Ussuri") + args[0].assert_called_once_with(cloud) + + @mock.patch('functest.utils.functest_utils.get_nova_version', + return_value=(2, 88)) + def test_openstack_version14(self, *args): + cloud = mock.Mock() + self.assertEqual(functest_utils.get_openstack_version( + cloud), "Wallaby") + args[0].assert_called_once_with(cloud) + + @mock.patch('functest.utils.functest_utils.get_nova_version', + return_value=(2, 89)) + def test_openstack_version15(self, *args): + cloud = mock.Mock() + self.assertEqual(functest_utils.get_openstack_version( + cloud), "Xena") + args[0].assert_called_once_with(cloud) + + @mock.patch('functest.utils.functest_utils.get_nova_version', + return_value=(2, 92)) + def test_openstack_version16(self, *args): + cloud = mock.Mock() + self.assertEqual(functest_utils.get_openstack_version( + cloud), "Zed") + args[0].assert_called_once_with(cloud) + + @mock.patch('functest.utils.functest_utils.get_nova_version', return_value=None) def test_openstack_version_exc(self, *args): cloud = mock.Mock() diff --git a/functest/tests/unit/vnf/ims/test_clearwater.py b/functest/tests/unit/vnf/ims/test_clearwater.py index 435b172db..f590a2857 100644 --- a/functest/tests/unit/vnf/ims/test_clearwater.py +++ b/functest/tests/unit/vnf/ims/test_clearwater.py @@ -38,6 +38,7 @@ class ClearwaterTesting(unittest.TestCase): 'cookies': ""} self.mock_post_200.configure_mock(**attrs) + if __name__ == "__main__": logging.disable(logging.CRITICAL) unittest.main(verbosity=2) diff --git a/functest/utils/config.py b/functest/utils/config.py index c2897d361..40414b88b 100644 --- a/functest/utils/config.py +++ b/functest/utils/config.py @@ -13,12 +13,13 @@ from functest.utils import env class Config(): def __init__(self): try: - # pylint: disable=bad-continuation with open(pkg_resources.resource_filename( - 'functest', 'ci/config_functest.yaml')) as yfile: + 'functest', 'ci/config_functest.yaml'), + encoding='utf-8') as yfile: self.functest_yaml = yaml.safe_load(yfile) except Exception as error: - raise Exception('Parse config failed: {}'.format(str(error))) + raise Exception( + f'Parse config failed: {str(error)}') from error @staticmethod def _merge_dicts(dict1, dict2): @@ -34,7 +35,7 @@ class Config(): yield (k, dict2[k]) def patch_file(self, patch_file_path): - with open(patch_file_path) as yfile: + with open(patch_file_path, encoding='utf-8') as yfile: patch_file = yaml.safe_load(yfile) for key in patch_file: @@ -53,13 +54,14 @@ class Config(): @staticmethod def _get_attr_further(attr_now, next): # pylint: disable=redefined-builtin return attr_now if next == 'general' else ( - '{}_{}'.format(attr_now, next) if attr_now else next) + f'{attr_now}_{next}' if attr_now else next) def fill(self): try: self._parse(None, self.functest_yaml) except Exception as error: - raise Exception('Parse config failed: {}'.format(str(error))) + raise Exception( + f'Parse config failed: {str(error)}') from error CONF = Config() diff --git a/functest/utils/env.py b/functest/utils/env.py index c5869e449..2e312726c 100644 --- a/functest/utils/env.py +++ b/functest/utils/env.py @@ -35,7 +35,13 @@ INPUTS = { 'NAMESERVER': '8.8.8.8', 'NEW_USER_ROLE': 'Member', 'USE_DYNAMIC_CREDENTIALS': 'True', - 'BLOCK_MIGRATION': 'True' + 'BLOCK_MIGRATION': 'False', + 'CLEAN_ORPHAN_SECURITY_GROUPS': 'True', + 'SKIP_DOWN_HYPERVISORS': 'False', + 'PUBLIC_ENDPOINT_ONLY': 'False', + 'DASHBOARD_URL': '', + 'VMTP_HYPERVISORS': '', + 'NO_TENANT_NETWORK': 'False' } diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py index 42c1edc9b..eec544489 100644 --- a/functest/utils/functest_utils.py +++ b/functest/utils/functest_utils.py @@ -11,10 +11,12 @@ from __future__ import print_function import logging +import os import subprocess import sys import yaml +from shade import _utils import six LOGGER = logging.getLogger(__name__) @@ -30,28 +32,26 @@ def execute_command_raise(cmd, info=False, error_msg="", def execute_command(cmd, info=False, error_msg="", verbose=True, output_file=None): if not error_msg: - error_msg = ("The command '%s' failed." % cmd) - msg_exec = ("Executing command: '%s'" % cmd) + error_msg = f"The command '{cmd}' failed." + msg_exec = f"Executing command: '{cmd}'" if verbose: if info: LOGGER.info(msg_exec) else: LOGGER.debug(msg_exec) - popen = subprocess.Popen( - cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if output_file: - ofd = open(output_file, "w") - for line in iter(popen.stdout.readline, b''): + with subprocess.Popen( + cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) as popen: if output_file: - ofd.write(line.decode("utf-8")) - else: - line = line.decode("utf-8").replace('\n', '') - print(line) - sys.stdout.flush() - if output_file: - ofd.close() - popen.stdout.close() - returncode = popen.wait() + with open(output_file, "w", encoding='utf-8') as ofd: + for line in iter(popen.stdout.readline, b''): + if output_file: + ofd.write(line.decode("utf-8")) + else: + line = line.decode("utf-8").replace('\n', '') + print(line) + sys.stdout.flush() + returncode = popen.wait() if returncode != 0: if verbose: LOGGER.error(error_msg) @@ -65,14 +65,14 @@ def get_parameter_from_yaml(parameter, yfile): parameter must be given in string format with dots Example: general.openstack.image_name """ - with open(yfile) as yfd: + with open(yfile, encoding='utf-8') as yfd: file_yaml = yaml.safe_load(yfd) value = file_yaml for element in parameter.split("."): value = value.get(element) if value is None: - raise ValueError("The parameter %s is not defined in" - " %s" % (parameter, yfile)) + raise ValueError(f"The parameter {parameter} is not defined in" + f" {yfile}") return value @@ -108,11 +108,22 @@ def get_openstack_version(cloud): - OpenStack release - Unknown on operation error """ + # pylint: disable=too-many-branches version = get_nova_version(cloud) try: assert version - if version > (2, 72): + if version > (2, 93): osversion = "Master" + elif version > (2, 90): + osversion = "Zed" + elif version > (2, 88): + osversion = "Xena" + elif version > (2, 87): + osversion = "Wallaby" + elif version > (2, 79): + osversion = "Ussuri" + elif version > (2, 72): + osversion = "Train" elif version > (2, 65): osversion = "Stein" elif version > (2, 60): @@ -140,24 +151,68 @@ def get_openstack_version(cloud): return "Unknown" +def list_services(cloud): + # pylint: disable=protected-access + """Search Keystone services via $OS_INTERFACE. + + It mainly conforms with `Shade + <https://docs.openstack.org/shade/latest>`_ but allows testing vs + public endpoints. It's worth mentioning that it doesn't support keystone + v2. + + :returns: a list of ``munch.Munch`` containing the services description + + :raises: ``OpenStackCloudException`` if something goes wrong during the + openstack API call. + """ + url, key = '/services', 'services' + data = cloud._identity_client.get( + url, endpoint_filter={ + 'interface': os.environ.get('OS_INTERFACE', 'public')}, + error_message="Failed to list services") + services = cloud._get_and_munchify(key, data) + return _utils.normalize_keystone_services(services) + + +def search_services(cloud, name_or_id=None, filters=None): + # pylint: disable=protected-access + """Search Keystone services ia $OS_INTERFACE. + + It mainly conforms with `Shade + <https://docs.openstack.org/shade/latest>`_ but allows testing vs + public endpoints. It's worth mentioning that it doesn't support keystone + v2. + + :param name_or_id: Name or id of the desired service. + :param filters: a dict containing additional filters to use. e.g. + {'type': 'network'}. + + :returns: a list of ``munch.Munch`` containing the services description + + :raises: ``OpenStackCloudException`` if something goes wrong during the + openstack API call. + """ + services = list_services(cloud) + return _utils._filter_list(services, name_or_id, filters) + + def convert_dict_to_ini(value): "Convert dict to oslo.conf input" assert isinstance(value, dict) - return ",".join("{}:{}".format( - key, val) for (key, val) in six.iteritems(value)) + return ",".join(f"{key}:{val}" for (key, val) in six.iteritems(value)) def convert_list_to_ini(value): "Convert list to oslo.conf input" assert isinstance(value, list) - return ",".join("{}".format(val) for val in value) + return ",".join(val for val in value) def convert_ini_to_dict(value): "Convert oslo.conf input to dict" assert isinstance(value, str) try: - return {k: v for k, v in (x.rsplit(':', 1) for x in value.split(','))} + return dict((x.rsplit(':', 1) for x in value.split(','))) except ValueError: return {} @@ -167,4 +222,4 @@ def convert_ini_to_list(value): assert isinstance(value, str) if not value: return [] - return [x for x in value.split(',')] + return list(value.split(',')) |