aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INFO2
-rw-r--r--docker/Dockerfile3
-rw-r--r--docker/Dockerfile.aarch643
-rw-r--r--docker/thirdparty-requirements.txt2
-rwxr-xr-xfunctest/ci/check_os.sh24
-rw-r--r--functest/ci/config_functest.yaml8
-rwxr-xr-xfunctest/ci/prepare_env.py6
-rwxr-xr-xfunctest/ci/run_tests.py22
-rw-r--r--functest/ci/testcases.yaml1
-rw-r--r--functest/opnfv_tests/openstack/snaps/api_check.py10
-rw-r--r--functest/opnfv_tests/openstack/snaps/health_check.py10
-rw-r--r--functest/opnfv_tests/openstack/snaps/smoke.py10
-rwxr-xr-xfunctest/opnfv_tests/openstack/vping/vping_userdata.py2
-rw-r--r--functest/tests/unit/ci/test_prepare_env.py8
-rw-r--r--functest/tests/unit/openstack/snaps/test_snaps.py169
-rw-r--r--functest/tests/unit/utils/test_openstack_clean.py16
-rw-r--r--functest/tests/unit/utils/test_openstack_snapshot.py16
-rw-r--r--functest/tests/unit/utils/test_openstack_utils.py24
-rwxr-xr-xfunctest/utils/openstack_clean.py32
-rwxr-xr-xfunctest/utils/openstack_snapshot.py22
-rw-r--r--functest/utils/openstack_utils.py49
21 files changed, 311 insertions, 128 deletions
diff --git a/INFO b/INFO
index ea6f41af..315a7777 100644
--- a/INFO
+++ b/INFO
@@ -20,9 +20,9 @@ Juha Kosonen <juha.kosonen@nokia.com>
Valentin Boucher <valentin.boucher@orange.com>
Viktor Tikkanen <viktor.tikkanen@nokia.com>
Mei Mei <meimei@huawei.com>
+Linda Wang <wangwulin@huawei.com>
Additional contributors:
-Linda Wang <wangwulin@huawei.com>
Georgios Paraskevopoulos <georgepar.91@gmail.com>
Romanos Skiadas <rom.skiad@gmail.com>
Michael Polenchuk <mpolenchuk@mirantis.com>
diff --git a/docker/Dockerfile b/docker/Dockerfile
index a9eebeb7..a3ebc1a1 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -14,7 +14,6 @@ LABEL version="0.1" description="OPNFV Functest Docker container"
# Environment variables
ARG BRANCH=master
ARG RALLY_TAG=0.8.1
-ARG TEMPEST_TAG=15.0.0
ARG REFSTACK_TAG=15.0.0
ARG ODL_TAG=release/beryllium-sr4
ARG KINGBIRD_TAG=1.1.0
@@ -121,7 +120,7 @@ RUN find -L ${FUNCTEST_REPO_DIR} -name "*.py" \
RUN /bin/bash ${REPOS_DIR}/parser/tests/parser_install.sh ${REPOS_DIR}
RUN wget -q https://raw.githubusercontent.com/openstack/rally/${RALLY_TAG}/install_rally.sh \
- && bash install_rally.sh --yes && rm install_rally.sh
+ && bash install_rally.sh --branch ${RALLY_TAG} --yes && rm install_rally.sh
RUN add_images.sh
diff --git a/docker/Dockerfile.aarch64 b/docker/Dockerfile.aarch64
index f9d98b23..1a7dc027 100644
--- a/docker/Dockerfile.aarch64
+++ b/docker/Dockerfile.aarch64
@@ -14,7 +14,6 @@ LABEL version="0.1" description="OPNFV Functest Aarch64 Docker container"
# Environment variables
ARG BRANCH=master
ARG RALLY_TAG=0.8.1
-ARG TEMPEST_TAG=15.0.0
ARG REFSTACK_TAG=15.0.0
ARG ODL_TAG=release/beryllium-sr4
ARG KINGBIRD_TAG=0.2.2
@@ -113,7 +112,7 @@ RUN find -L ${FUNCTEST_REPO_DIR} -name "*.py" \
RUN /bin/bash ${REPOS_DIR}/parser/tests/parser_install.sh ${REPOS_DIR}
RUN wget -q https://raw.githubusercontent.com/openstack/rally/${RALLY_TAG}/install_rally.sh \
- && bash install_rally.sh --yes && rm install_rally.sh
+ && bash install_rally.sh --branch ${RALLY_TAG} --yes && rm install_rally.sh
RUN add_images.sh
diff --git a/docker/thirdparty-requirements.txt b/docker/thirdparty-requirements.txt
index 4fe98147..f51a5e29 100644
--- a/docker/thirdparty-requirements.txt
+++ b/docker/thirdparty-requirements.txt
@@ -5,5 +5,5 @@ git+https://gerrit.opnfv.org/gerrit/securityscanning#egg=securityscanning
git+https://gerrit.opnfv.org/gerrit/sfc#egg=sfc
networking-bgpvpn
rally
-tempest>=12.1.0 # Apache-2.0
+tempest>=15.0.0 # Apache-2.0
git+https://github.com/openstack/refstack-client#egg=refstack-client
diff --git a/functest/ci/check_os.sh b/functest/ci/check_os.sh
index ce0bc20c..7b66f3da 100755
--- a/functest/ci/check_os.sh
+++ b/functest/ci/check_os.sh
@@ -6,12 +6,18 @@
# jose.lausuch@ericsson.com
#
+if [[ ${OS_INSECURE,,} == "true" ]]; then
+ options='--insecure'
+else
+ options=''
+fi
+
declare -A service_cmd_array
-service_cmd_array['nova']='openstack server list'
-service_cmd_array['neutron']='openstack network list'
-service_cmd_array['keystone']='openstack endpoint list'
-service_cmd_array['cinder']='openstack volume list'
-service_cmd_array['glance']='openstack image list'
+service_cmd_array['nova']="openstack $options server list"
+service_cmd_array['neutron']="openstack $options network list"
+service_cmd_array['keystone']="openstack $options endpoint list"
+service_cmd_array['cinder']="openstack $options volume list"
+service_cmd_array['glance']="openstack $options image list"
MANDATORY_SERVICES='nova neutron keystone glance'
OPTIONAL_SERVICES='cinder'
@@ -41,7 +47,7 @@ check_service() {
required=$2
fi
echo ">>Checking ${service} service..."
- if ! openstack service list | grep -i ${service} > /dev/null; then
+ if ! openstack $options service list | grep -i ${service} > /dev/null; then
if [ "$required" == 'false' ]; then
echo "WARN: Optional Service ${service} is not enabled!"
return
@@ -67,7 +73,7 @@ fi
echo "Checking OpenStack endpoints:"
-publicURL=$(openstack catalog show identity |awk '/public/ {print $4}')
+publicURL=$(openstack $options catalog show identity |awk '/public/ {print $4}')
publicIP=$(echo $publicURL|sed 's/^.*http.*\:\/\///'|sed 's/.[^:]*$//')
publicPort=$(echo $publicURL|grep -Po '(?<=:)\d+')
https_enabled=$(echo $publicURL | grep 'https')
@@ -99,11 +105,11 @@ for service in $OPTIONAL_SERVICES; do
done
echo "Checking External network..."
-networks=($(neutron net-list -F id | tail -n +4 | head -n -1 | awk '{print $2}'))
+networks=($(neutron $options net-list -F id | tail -n +4 | head -n -1 | awk '{print $2}'))
is_external=False
for net in "${networks[@]}"
do
- is_external=$(neutron net-show $net|grep "router:external"|awk '{print $4}')
+ is_external=$(neutron $options net-show $net|grep "router:external"|awk '{print $4}')
if [ $is_external == "True" ]; then
echo "External network found: $net"
break
diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml
index ed3f2475..1199be5a 100644
--- a/functest/ci/config_functest.yaml
+++ b/functest/ci/config_functest.yaml
@@ -3,7 +3,7 @@ general:
home: /home/opnfv
repos: /home/opnfv/repos
dir_repo_rally: /home/opnfv/repos/rally
- repo_tempest: /home/opnfv/repos/tempest
+ repo_tempest: /home/opnfv/.tempest
dir_repo_releng: /home/opnfv/repos/releng
repo_vims_test: /home/opnfv/repos/vnfs/vims-test
repo_onos: /home/opnfv/repos/onos
@@ -57,9 +57,9 @@ general:
snaps:
use_keystone: True
use_floating_ips: True
-# images:
-# cirros:
-# disk_url: http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img
+ images:
+ cirros:
+ disk_file: /home/opnfv/functest/images/cirros-0.3.5-x86_64-disk.img
# ARM
# disk_url: http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-disk.img
# kernel_url: http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-kernel
diff --git a/functest/ci/prepare_env.py b/functest/ci/prepare_env.py
index fd1f5dbf..64fcc925 100755
--- a/functest/ci/prepare_env.py
+++ b/functest/ci/prepare_env.py
@@ -251,8 +251,8 @@ def update_db_url():
def verify_deployment():
print_separator()
logger.info("Verifying OpenStack services...")
- cmd = ("sh %s" % pkg_resources.resource_filename(
- 'functest', 'ci/check_os.sh'))
+ cmd = ("%s" % pkg_resources.resource_filename(
+ 'functest', 'ci/check_os.sh'))
logger.debug("Executing command: %s" % cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
@@ -366,7 +366,6 @@ def main(**kwargs):
elif kwargs['action'] == "start":
logger.info("######### Preparing Functest environment #########\n")
check_env_variables()
- get_deployment_handler()
create_directories()
source_rc_file()
update_config_file()
@@ -377,7 +376,6 @@ def main(**kwargs):
with open(CONST.__getattribute__('env_active'), "w") as env_file:
env_file.write("1")
check_environment()
- print_deployment_info()
elif kwargs['action'] == "check":
check_environment()
except Exception as e:
diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py
index 430f0ca8..722df14f 100755
--- a/functest/ci/run_tests.py
+++ b/functest/ci/run_tests.py
@@ -252,16 +252,18 @@ class Runner(object):
msg.add_row([env_var, CONST.__getattribute__(env_var)])
logger.info("Deployment description: \n\n%s\n", msg)
- msg = prettytable.PrettyTable(
- header_style='upper', padding_width=5,
- field_names=['test case', 'project', 'tier', 'duration', 'result'])
- for test_case in self.executed_test_cases:
- result = 'PASS' if(test_case.is_successful(
- ) == test_case.EX_OK) else 'FAIL'
- msg.add_row([test_case.case_name, test_case.project_name,
- _tiers.get_tier_name(test_case.case_name),
- test_case.get_duration(), result])
- logger.info("FUNCTEST REPORT: \n\n%s\n", msg)
+ if len(self.executed_test_cases) > 1:
+ msg = prettytable.PrettyTable(
+ header_style='upper', padding_width=5,
+ field_names=['test case', 'project', 'tier',
+ 'duration', 'result'])
+ for test_case in self.executed_test_cases:
+ result = 'PASS' if(test_case.is_successful(
+ ) == test_case.EX_OK) else 'FAIL'
+ msg.add_row([test_case.case_name, test_case.project_name,
+ _tiers.get_tier_name(test_case.case_name),
+ test_case.get_duration(), result])
+ logger.info("FUNCTEST REPORT: \n\n%s\n", msg)
logger.info("Execution exit value: %s" % self.overall_result)
return self.overall_result
diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml
index c30292bc..2763d0c2 100644
--- a/functest/ci/testcases.yaml
+++ b/functest/ci/testcases.yaml
@@ -269,7 +269,6 @@ tiers:
-
case_name: doctor-notification
- enabled: false
project_name: doctor
criteria: 100
blocking: false
diff --git a/functest/opnfv_tests/openstack/snaps/api_check.py b/functest/opnfv_tests/openstack/snaps/api_check.py
index 50f67094..43518cb4 100644
--- a/functest/opnfv_tests/openstack/snaps/api_check.py
+++ b/functest/opnfv_tests/openstack/snaps/api_check.py
@@ -1,4 +1,5 @@
-# Copyright (c) 2015 All rights reserved
+# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
+#
# 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
@@ -26,8 +27,15 @@ class ApiCheck(SnapsTestRunner):
self.suite = unittest.TestSuite()
+ def run(self, **kwargs):
+ """
+ Builds the test suite then calls super.run()
+ :param kwargs: the arguments to pass on
+ :return:
+ """
test_suite_builder.add_openstack_api_tests(
suite=self.suite,
os_creds=self.os_creds,
ext_net_name=self.ext_net_name,
use_keystone=self.use_keystone)
+ return super(self.__class__, self).run()
diff --git a/functest/opnfv_tests/openstack/snaps/health_check.py b/functest/opnfv_tests/openstack/snaps/health_check.py
index 0daddcdd..4e94460c 100644
--- a/functest/opnfv_tests/openstack/snaps/health_check.py
+++ b/functest/opnfv_tests/openstack/snaps/health_check.py
@@ -1,4 +1,5 @@
-# Copyright (c) 2015 All rights reserved
+# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
+#
# 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
@@ -28,6 +29,12 @@ class HealthCheck(SnapsTestRunner):
self.suite = unittest.TestSuite()
+ def run(self, **kwargs):
+ """
+ Builds the test suite then calls super.run()
+ :param kwargs: the arguments to pass on
+ :return:
+ """
image_custom_config = None
if hasattr(CONST, 'snaps_images_cirros'):
@@ -39,3 +46,4 @@ class HealthCheck(SnapsTestRunner):
use_keystone=self.use_keystone,
flavor_metadata=self.flavor_metadata,
image_metadata=image_custom_config))
+ return super(self.__class__, self).run()
diff --git a/functest/opnfv_tests/openstack/snaps/smoke.py b/functest/opnfv_tests/openstack/snaps/smoke.py
index d9f95e90..c3c55c7c 100644
--- a/functest/opnfv_tests/openstack/snaps/smoke.py
+++ b/functest/opnfv_tests/openstack/snaps/smoke.py
@@ -1,4 +1,5 @@
-# Copyright (c) 2015 All rights reserved
+# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
+#
# 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
@@ -28,6 +29,12 @@ class SnapsSmoke(SnapsTestRunner):
self.suite = unittest.TestSuite()
+ def run(self, **kwargs):
+ """
+ Builds the test suite then calls super.run()
+ :param kwargs: the arguments to pass on
+ :return:
+ """
image_config = None
if hasattr(CONST, 'snaps_images_cirros'):
image_config = CONST.__getattribute__('snaps_images_cirros')
@@ -47,3 +54,4 @@ class SnapsSmoke(SnapsTestRunner):
flavor_metadata=self.flavor_metadata,
image_metadata=image_config,
use_floating_ips=self.use_fip)
+ return super(self.__class__, self).run()
diff --git a/functest/opnfv_tests/openstack/vping/vping_userdata.py b/functest/opnfv_tests/openstack/vping/vping_userdata.py
index b69b3955..718f47f0 100755
--- a/functest/opnfv_tests/openstack/vping/vping_userdata.py
+++ b/functest/opnfv_tests/openstack/vping/vping_userdata.py
@@ -97,7 +97,7 @@ class VPingUserdata(vping_base.VPingBase):
while True:
time.sleep(1)
- p_console = vm_creator.get_vm_inst().get_console_output()
+ p_console = vm_creator.get_os_vm_server_obj().get_console_output()
if "vPing OK" in p_console:
self.logger.info("vPing detected!")
exit_code = TestCase.EX_OK
diff --git a/functest/tests/unit/ci/test_prepare_env.py b/functest/tests/unit/ci/test_prepare_env.py
index f3e15a01..69abd643 100644
--- a/functest/tests/unit/ci/test_prepare_env.py
+++ b/functest/tests/unit/ci/test_prepare_env.py
@@ -424,7 +424,6 @@ class PrepareEnvTesting(unittest.TestCase):
mock_logger_info.assert_any_call("Functest environment"
" is installed.")
- @mock.patch('functest.ci.prepare_env.print_deployment_info')
@mock.patch('functest.ci.prepare_env.check_environment')
@mock.patch('functest.ci.prepare_env.create_flavor')
@mock.patch('functest.ci.prepare_env.install_tempest')
@@ -433,21 +432,19 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.update_config_file')
@mock.patch('functest.ci.prepare_env.source_rc_file')
@mock.patch('functest.ci.prepare_env.create_directories')
- @mock.patch('functest.ci.prepare_env.get_deployment_handler')
@mock.patch('functest.ci.prepare_env.check_env_variables')
@mock.patch('functest.ci.prepare_env.logger.info')
- def test_main_start(self, mock_logger_info, mock_env_var, mock_dep_handler,
+ def test_main_start(self, mock_logger_info, mock_env_var,
mock_create_dir, mock_source_rc, mock_update_config,
mock_verify_depl, mock_install_rally,
mock_install_temp, mock_create_flavor,
- mock_check_env, mock_print_info):
+ mock_check_env):
with mock.patch("__builtin__.open", mock.mock_open()) as m:
args = {'action': 'start'}
self.assertEqual(prepare_env.main(**args), 0)
mock_logger_info.assert_any_call("######### Preparing Functest "
"environment #########\n")
self.assertTrue(mock_env_var.called)
- self.assertTrue(mock_dep_handler.called)
self.assertTrue(mock_create_dir.called)
self.assertTrue(mock_source_rc.called)
self.assertTrue(mock_update_config.called)
@@ -458,7 +455,6 @@ class PrepareEnvTesting(unittest.TestCase):
m.assert_called_once_with(
CONST.__getattribute__('env_active'), "w")
self.assertTrue(mock_check_env.called)
- self.assertTrue(mock_print_info.called)
@mock.patch('functest.ci.prepare_env.check_environment')
def test_main_check(self, mock_check_env):
diff --git a/functest/tests/unit/openstack/snaps/test_snaps.py b/functest/tests/unit/openstack/snaps/test_snaps.py
index 9cfcc0a6..7cf53b39 100644
--- a/functest/tests/unit/openstack/snaps/test_snaps.py
+++ b/functest/tests/unit/openstack/snaps/test_snaps.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-
# Copyright (c) 2017 Cable Television Laboratories, Inc. and others.
#
# All rights reserved. This program and the accompanying materials
@@ -9,12 +7,14 @@
# http://www.apache.org/licenses/LICENSE-2.0
import mock
+import os
import unittest
from snaps.openstack.os_credentials import OSCreds
from functest.core.testcase import TestCase
-from functest.opnfv_tests.openstack.snaps import connection_check
+from functest.opnfv_tests.openstack.snaps import (connection_check, api_check,
+ health_check, smoke)
class ConnectionCheckTesting(unittest.TestCase):
@@ -31,10 +31,8 @@ class ConnectionCheckTesting(unittest.TestCase):
self.connection_check = connection_check.ConnectionCheck(
os_creds=self.os_creds, ext_net_name='foo')
- @mock.patch('functest.opnfv_tests.openstack.snaps.connection_check.'
- 'ConnectionCheck')
@mock.patch('snaps.test_suite_builder.add_openstack_client_tests')
- def test_run_success(self, mock_test, add_os_client_tests):
+ def test_run_success(self, add_os_client_tests):
result = mock.MagicMock(name='unittest.TextTestResult')
result.testsRun = 100
result.failures = []
@@ -44,10 +42,8 @@ class ConnectionCheckTesting(unittest.TestCase):
self.assertEquals(TestCase.EX_OK,
self.connection_check.is_successful())
- @mock.patch('functest.opnfv_tests.openstack.snaps.connection_check.'
- 'ConnectionCheck')
@mock.patch('snaps.test_suite_builder.add_openstack_client_tests')
- def test_run_1_of_100_failures(self, mock_test, add_os_client_tests):
+ def test_run_1_of_100_failures(self, add_os_client_tests):
result = mock.MagicMock(name='unittest.TextTestResult')
result.testsRun = 100
result.failures = ['foo']
@@ -57,11 +53,8 @@ class ConnectionCheckTesting(unittest.TestCase):
self.assertEquals(TestCase.EX_TESTCASE_FAILED,
self.connection_check.is_successful())
- @mock.patch('functest.opnfv_tests.openstack.snaps.connection_check.'
- 'ConnectionCheck')
@mock.patch('snaps.test_suite_builder.add_openstack_client_tests')
- def test_run_1_of_100_failures_within_criteria(self, mock_test,
- add_os_client_tests):
+ def test_run_1_of_100_failures_within_criteria(self, add_os_client_tests):
self.connection_check.criteria = 90
result = mock.MagicMock(name='unittest.TextTestResult')
result.testsRun = 100
@@ -71,3 +64,153 @@ class ConnectionCheckTesting(unittest.TestCase):
self.assertEquals(TestCase.EX_OK, self.connection_check.run())
self.assertEquals(TestCase.EX_OK,
self.connection_check.is_successful())
+
+
+class APICheckTesting(unittest.TestCase):
+ """
+ Ensures the VPingUserdata class can run in Functest. This test does not
+ actually connect with an OpenStack pod.
+ """
+
+ def setUp(self):
+ self.os_creds = OSCreds(
+ username='user', password='pass',
+ auth_url='http://foo.com:5000/v3', project_name='bar')
+
+ self.api_check = api_check.ApiCheck(
+ os_creds=self.os_creds, ext_net_name='foo')
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_api_tests')
+ def test_run_success(self, add_tests):
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = []
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.api_check.run())
+ self.assertEquals(TestCase.EX_OK,
+ self.api_check.is_successful())
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_api_tests')
+ def test_run_1_of_100_failures(self, add_tests):
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = ['foo']
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.api_check.run())
+ self.assertEquals(TestCase.EX_TESTCASE_FAILED,
+ self.api_check.is_successful())
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_api_tests')
+ def test_run_1_of_100_failures_within_criteria(self, add_tests):
+ self.api_check.criteria = 90
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = ['foo']
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.api_check.run())
+ self.assertEquals(TestCase.EX_OK,
+ self.api_check.is_successful())
+
+
+class HealthCheckTesting(unittest.TestCase):
+ """
+ Ensures the VPingUserdata class can run in Functest. This test does not
+ actually connect with an OpenStack pod.
+ """
+
+ def setUp(self):
+ self.os_creds = OSCreds(
+ username='user', password='pass',
+ auth_url='http://foo.com:5000/v3', project_name='bar')
+
+ self.health_check = health_check.HealthCheck(
+ os_creds=self.os_creds, ext_net_name='foo')
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_client_tests')
+ def test_run_success(self, add_tests):
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = []
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.health_check.run())
+ self.assertEquals(TestCase.EX_OK,
+ self.health_check.is_successful())
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_client_tests')
+ def test_run_1_of_100_failures(self, add_tests):
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = ['foo']
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.health_check.run())
+ self.assertEquals(TestCase.EX_TESTCASE_FAILED,
+ self.health_check.is_successful())
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_client_tests')
+ def test_run_1_of_100_failures_within_criteria(self, add_tests):
+ self.health_check.criteria = 90
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = ['foo']
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.health_check.run())
+ self.assertEquals(TestCase.EX_OK,
+ self.health_check.is_successful())
+
+
+class SmokeTesting(unittest.TestCase):
+ """
+ Ensures the VPingUserdata class can run in Functest. This test does not
+ actually connect with an OpenStack pod.
+ """
+
+ def setUp(self):
+ self.os_creds = OSCreds(
+ username='user', password='pass',
+ auth_url='http://foo.com:5000/v3', project_name='bar')
+
+ self.smoke = smoke.SnapsSmoke(
+ os_creds=self.os_creds, ext_net_name='foo')
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_integration_tests')
+ @mock.patch('os.path.join', return_value=os.getcwd())
+ def test_run_success(self, add_tests, cwd):
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = []
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.smoke.run())
+ self.assertEquals(TestCase.EX_OK,
+ self.smoke.is_successful())
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_integration_tests')
+ @mock.patch('os.path.join', return_value=os.getcwd())
+ def test_run_1_of_100_failures(self, add_tests, cwd):
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = ['foo']
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.smoke.run())
+ self.assertEquals(TestCase.EX_TESTCASE_FAILED,
+ self.smoke.is_successful())
+
+ @mock.patch('snaps.test_suite_builder.add_openstack_integration_tests')
+ @mock.patch('os.path.join', return_value=os.getcwd())
+ def test_run_1_of_100_failures_within_criteria(self, add_tests, cwd):
+ self.smoke.criteria = 90
+ result = mock.MagicMock(name='unittest.TextTestResult')
+ result.testsRun = 100
+ result.failures = ['foo']
+ result.errors = []
+ with mock.patch('unittest.TextTestRunner.run', return_value=result):
+ self.assertEquals(TestCase.EX_OK, self.smoke.run())
+ self.assertEquals(TestCase.EX_OK,
+ self.smoke.is_successful())
diff --git a/functest/tests/unit/utils/test_openstack_clean.py b/functest/tests/unit/utils/test_openstack_clean.py
index fe7b50d4..6ae7faa4 100644
--- a/functest/tests/unit/utils/test_openstack_clean.py
+++ b/functest/tests/unit/utils/test_openstack_clean.py
@@ -61,6 +61,8 @@ class OSCleanTesting(unittest.TestCase):
{'id': 'id2', 'name': 'name2', 'ip': 'ip2',
'router:external': False,
'external_gateway_info': None}]
+ self.floatingips_list = [{'id': 'id1', 'floating_ip_address': 'ip1'},
+ {'id': 'id2', 'floating_ip_address': 'ip2'}]
self.routers = [mock.Mock()]
self.ports = [mock.Mock()]
@@ -254,7 +256,8 @@ class OSCleanTesting(unittest.TestCase):
@mock.patch('functest.utils.openstack_clean.logger.debug')
def test_remove_floatingips(self, mock_logger_debug):
with mock.patch('functest.utils.openstack_clean.os_utils'
- '.get_floating_ips', return_value=self.test_list):
+ '.get_floating_ips',
+ return_value=self.floatingips_list):
openstack_clean.remove_floatingips(self.client, self.update_list)
mock_logger_debug.assert_any_call("Removing floating IPs...")
mock_logger_debug.assert_any_call(" > this is a default "
@@ -272,9 +275,10 @@ class OSCleanTesting(unittest.TestCase):
@mock.patch('functest.utils.openstack_clean.logger.debug')
def test_remove_floatingips_delete_success(self, mock_logger_debug):
with mock.patch('functest.utils.openstack_clean.os_utils'
- '.get_floating_ips', return_value=self.test_list), \
+ '.get_floating_ips',
+ return_value=self.floatingips_list), \
mock.patch('functest.utils.openstack_clean.os_utils'
- '.delete_volume', return_value=True):
+ '.delete_floating_ip', return_value=True):
openstack_clean.remove_floatingips(self.client, self.remove_list)
mock_logger_debug.assert_any_call("Removing floating IPs...")
mock_logger_debug.assert_any_call(" > Done!")
@@ -287,7 +291,8 @@ class OSCleanTesting(unittest.TestCase):
def test_remove_floatingips_delete_failed(self, mock_logger_debug,
mock_logger_error):
with mock.patch('functest.utils.openstack_clean.os_utils'
- '.get_floating_ips', return_value=self.test_list), \
+ '.get_floating_ips',
+ return_value=self.floatingips_list), \
mock.patch('functest.utils.openstack_clean.os_utils'
'.delete_floating_ip', return_value=False):
openstack_clean.remove_floatingips(self.client, self.remove_list)
@@ -672,6 +677,7 @@ class OSCleanTesting(unittest.TestCase):
RegexMatch(" Removing "
"\s*\S+..."))
+ @mock.patch('functest.utils.openstack_clean.os_utils.get_glance_client')
@mock.patch('functest.utils.openstack_clean.os_utils.get_cinder_client')
@mock.patch('functest.utils.openstack_clean.os_utils'
'.get_keystone_client')
@@ -684,7 +690,7 @@ class OSCleanTesting(unittest.TestCase):
@mock.patch('functest.utils.openstack_clean.logger.debug')
def test_main_default(self, mock_logger_debug, mock_logger_info,
mock_creds, mock_nova, mock_neutron,
- mock_keystone, mock_cinder):
+ mock_keystone, mock_cinder, mock_glance):
with mock.patch('functest.utils.openstack_clean.remove_instances') \
as mock_remove_instances, \
diff --git a/functest/tests/unit/utils/test_openstack_snapshot.py b/functest/tests/unit/utils/test_openstack_snapshot.py
index d3f93994..33e74609 100644
--- a/functest/tests/unit/utils/test_openstack_snapshot.py
+++ b/functest/tests/unit/utils/test_openstack_snapshot.py
@@ -12,7 +12,7 @@ import unittest
from functest.utils import openstack_snapshot
-class OSTackerTesting(unittest.TestCase):
+class OSSnapshotTesting(unittest.TestCase):
def _get_instance(self, key):
mock_obj = mock.Mock()
@@ -26,6 +26,8 @@ class OSTackerTesting(unittest.TestCase):
self.test_list = [self._get_instance(1), self._get_instance(2)]
self.update_list = {'id1': 'name1', 'id2': 'name2'}
self.update_floatingips = {'id1': 'ip1', 'id2': 'ip2'}
+ self.floatingips_list = [{'id': 'id1', 'floating_ip_address': 'ip1'},
+ {'id': 'id2', 'floating_ip_address': 'ip2'}]
self.test_dict_list = [{'id': 'id1', 'name': 'name1', 'ip': 'ip1'},
{'id': 'id2', 'name': 'name2', 'ip': 'ip2'}]
@@ -138,8 +140,9 @@ class OSTackerTesting(unittest.TestCase):
@mock.patch('functest.utils.openstack_snapshot.logger.debug')
def test_get_floatingips(self, mock_logger_debug):
with mock.patch('functest.utils.openstack_snapshot.os_utils'
- '.get_floating_ips', return_value=self.test_list):
- resp = openstack_snapshot.get_floatinips(self.client)
+ '.get_floating_ips',
+ return_value=self.floatingips_list):
+ resp = openstack_snapshot.get_floatingips(self.client)
mock_logger_debug.assert_called_once_with("Getting Floating "
"IPs...")
self.assertDictEqual(resp, {'floatingips':
@@ -149,7 +152,7 @@ class OSTackerTesting(unittest.TestCase):
def test_get_floatingips_missing_floatingips(self, mock_logger_debug):
with mock.patch('functest.utils.openstack_snapshot.os_utils'
'.get_floating_ips', return_value=[]):
- resp = openstack_snapshot.get_floatinips(self.client)
+ resp = openstack_snapshot.get_floatingips(self.client)
mock_logger_debug.assert_called_once_with("Getting Floating "
"IPs...")
self.assertDictEqual(resp, {'floatingips': {}})
@@ -186,6 +189,7 @@ class OSTackerTesting(unittest.TestCase):
mock_logger_debug.assert_called_once_with("Getting tenants...")
self.assertDictEqual(resp, {'tenants': {}})
+ @mock.patch('functest.utils.openstack_clean.os_utils.get_glance_client')
@mock.patch('functest.utils.openstack_snapshot.os_utils.get_cinder_client')
@mock.patch('functest.utils.openstack_snapshot.os_utils'
'.get_keystone_client')
@@ -197,7 +201,7 @@ class OSTackerTesting(unittest.TestCase):
@mock.patch('functest.utils.openstack_snapshot.logger.debug')
def test_main_default(self, mock_logger_debug, mock_logger_info,
mock_creds, mock_nova, mock_neutron,
- mock_keystone, mock_cinder):
+ mock_keystone, mock_cinder, mock_glance):
with mock.patch('functest.utils.openstack_snapshot.get_instances',
return_value=self.update_list), \
mock.patch('functest.utils.openstack_snapshot.get_images',
@@ -212,7 +216,7 @@ class OSTackerTesting(unittest.TestCase):
return_value=self.update_list), \
mock.patch('functest.utils.openstack_snapshot.get_security_groups',
return_value=self.update_list), \
- mock.patch('functest.utils.openstack_snapshot.get_floatinips',
+ mock.patch('functest.utils.openstack_snapshot.get_floatingips',
return_value=self.update_floatingips), \
mock.patch('functest.utils.openstack_snapshot.get_users',
return_value=self.update_list), \
diff --git a/functest/tests/unit/utils/test_openstack_utils.py b/functest/tests/unit/utils/test_openstack_utils.py
index 0f06b1e1..74b49aaa 100644
--- a/functest/tests/unit/utils/test_openstack_utils.py
+++ b/functest/tests/unit/utils/test_openstack_utils.py
@@ -27,7 +27,8 @@ class OSUtilsTesting(unittest.TestCase):
'OS_PROJECT_NAME': os_prefix + 'project_name',
'OS_ENDPOINT_TYPE': os_prefix + 'endpoint_type',
'OS_REGION_NAME': os_prefix + 'region_name',
- 'OS_CACERT': os_prefix + 'https_cacert'}
+ 'OS_CACERT': os_prefix + 'https_cacert',
+ 'OS_INSECURE': os_prefix + 'https_insecure'}
def _get_os_env_vars(self):
return {'username': 'test_username', 'password': 'test_password',
@@ -37,7 +38,8 @@ class OSUtilsTesting(unittest.TestCase):
'project_name': 'test_project_name',
'endpoint_type': 'test_endpoint_type',
'region_name': 'test_region_name',
- 'https_cacert': 'test_https_cacert'}
+ 'https_cacert': 'test_https_cacert',
+ 'https_insecure': 'test_https_insecure'}
def setUp(self):
self.env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
@@ -75,9 +77,8 @@ class OSUtilsTesting(unittest.TestCase):
self.availability_zone = mock_obj
mock_obj = mock.Mock()
- attrs = {'id': 'floating_id',
- 'zoneName': 'test_floating_ip',
- 'status': 'ok'}
+ attrs = {'floating_network_id': 'floating_id',
+ 'floating_ip_address': 'test_floating_ip'}
mock_obj.configure_mock(**attrs)
self.floating_ip = mock_obj
@@ -113,8 +114,6 @@ class OSUtilsTesting(unittest.TestCase):
'aggregates.delete.return_value': mock.Mock(),
'availability_zones.list.return_value':
[self.availability_zone],
- 'floating_ips.list.return_value': [self.floating_ip],
- 'floating_ips.delete.return_value': mock.Mock(),
'hypervisors.list.return_value': [self.hypervisor],
'create.return_value': mock.Mock(),
'add_security_group.return_value': mock.Mock(),
@@ -271,7 +270,10 @@ class OSUtilsTesting(unittest.TestCase):
'create_security_group.return_value': {'security_group':
self.sec_group},
'update_quota.return_value': mock.Mock(),
- 'delete_security_group.return_value': mock.Mock()
+ 'delete_security_group.return_value': mock.Mock(),
+ 'list_floatingips.return_value': {'floatingips':
+ [self.floating_ip]},
+ 'delete_floatingip.return_value': mock.Mock(),
}
self.neutron_client.configure_mock(**attrs)
@@ -721,7 +723,7 @@ class OSUtilsTesting(unittest.TestCase):
def test_get_floating_ips_default(self):
self.assertEqual(openstack_utils.
- get_floating_ips(self.nova_client),
+ get_floating_ips(self.neutron_client),
[self.floating_ip])
@mock.patch('functest.utils.openstack_utils.logger.error')
@@ -867,7 +869,7 @@ class OSUtilsTesting(unittest.TestCase):
def test_delete_floating_ip_default(self):
self.assertTrue(openstack_utils.
- delete_floating_ip(self.nova_client,
+ delete_floating_ip(self.neutron_client,
'floating_ip_id'))
@mock.patch('functest.utils.openstack_utils.logger.error')
@@ -1472,7 +1474,7 @@ class OSUtilsTesting(unittest.TestCase):
def test_get_images_default(self):
self.assertEqual(openstack_utils.
- get_images(self.nova_client),
+ get_images(self.glance_client),
[self.image])
@mock.patch('functest.utils.openstack_utils.logger.error')
diff --git a/functest/utils/openstack_clean.py b/functest/utils/openstack_clean.py
index 0ce08798..e88245d6 100755
--- a/functest/utils/openstack_clean.py
+++ b/functest/utils/openstack_clean.py
@@ -80,22 +80,25 @@ def remove_instances(nova_client, default_instances):
break
-def remove_images(nova_client, default_images):
+def remove_images(glance_client, default_images):
logger.debug("Removing Glance images...")
- images = os_utils.get_images(nova_client)
- if images is None or len(images) == 0:
+ images = os_utils.get_images(glance_client)
+ if images is None:
+ return -1
+ images = {image.id: image.name for image in images}
+ if len(images) == 0:
logger.debug("No images found.")
return
for image in images:
- image_name = getattr(image, 'name')
- image_id = getattr(image, 'id')
+ image_id = image
+ image_name = images.get(image_id)
logger.debug("'%s', ID=%s " % (image_name, image_id))
if (image_id not in default_images and
image_name not in default_images.values()):
logger.debug("Removing image '%s', ID=%s ..."
% (image_name, image_id))
- if os_utils.delete_glance_image(nova_client, image_id):
+ if os_utils.delete_glance_image(glance_client, image_id):
logger.debug(" > Done!")
else:
logger.error("There has been a problem removing the"
@@ -135,9 +138,9 @@ def remove_volumes(cinder_client, default_volumes):
"NOT be deleted.")
-def remove_floatingips(nova_client, default_floatingips):
+def remove_floatingips(neutron_client, default_floatingips):
logger.debug("Removing floating IPs...")
- floatingips = os_utils.get_floating_ips(nova_client)
+ floatingips = os_utils.get_floating_ips(neutron_client)
if floatingips is None or len(floatingips) == 0:
logger.debug("No floating IPs found.")
return
@@ -145,13 +148,13 @@ def remove_floatingips(nova_client, default_floatingips):
init_len = len(floatingips)
deleted = 0
for fip in floatingips:
- fip_id = getattr(fip, 'id')
- fip_ip = getattr(fip, 'ip')
+ fip_id = fip['id']
+ fip_ip = fip['floating_ip_address']
logger.debug("'%s', ID=%s " % (fip_ip, fip_id))
if (fip_id not in default_floatingips and
fip_ip not in default_floatingips.values()):
logger.debug("Removing floating IP %s ..." % fip_id)
- if os_utils.delete_floating_ip(nova_client, fip_id):
+ if os_utils.delete_floating_ip(neutron_client, fip_id):
logger.debug(" > Done!")
deleted += 1
else:
@@ -163,7 +166,7 @@ def remove_floatingips(nova_client, default_floatingips):
timeout = 50
while timeout > 0:
- floatingips = os_utils.get_floating_ips(nova_client)
+ floatingips = os_utils.get_floating_ips(neutron_client)
if floatingips is None or len(floatingips) == (init_len - deleted):
break
else:
@@ -385,6 +388,7 @@ def main():
neutron_client = os_utils.get_neutron_client()
keystone_client = os_utils.get_keystone_client()
cinder_client = os_utils.get_cinder_client()
+ glance_client = os_utils.get_glance_client()
try:
with open(OS_SNAPSHOT_FILE) as f:
@@ -411,11 +415,11 @@ def main():
remove_instances(nova_client, default_instances)
separator()
- remove_images(nova_client, default_images)
+ remove_images(glance_client, default_images)
separator()
remove_volumes(cinder_client, default_volumes)
separator()
- remove_floatingips(nova_client, default_floatingips)
+ remove_floatingips(neutron_client, default_floatingips)
separator()
remove_networks(neutron_client, default_networks, default_routers)
separator()
diff --git a/functest/utils/openstack_snapshot.py b/functest/utils/openstack_snapshot.py
index 233c316a..f4ef751c 100755
--- a/functest/utils/openstack_snapshot.py
+++ b/functest/utils/openstack_snapshot.py
@@ -48,13 +48,13 @@ def get_instances(nova_client):
return {'instances': dic_instances}
-def get_images(nova_client):
+def get_images(glance_client):
logger.debug("Getting images...")
dic_images = {}
- images = os_utils.get_images(nova_client)
- if not (images is None or len(images) == 0):
- for image in images:
- dic_images.update({getattr(image, 'id'): getattr(image, 'name')})
+ images = os_utils.get_images(glance_client)
+ if images is None:
+ return -1
+ dic_images.update({image.id: image.name for image in images})
return {'images': dic_images}
@@ -98,13 +98,14 @@ def get_security_groups(neutron_client):
return {'secgroups': dic_secgroups}
-def get_floatinips(nova_client):
+def get_floatingips(neutron_client):
logger.debug("Getting Floating IPs...")
dic_floatingips = {}
- floatingips = os_utils.get_floating_ips(nova_client)
+ floatingips = os_utils.get_floating_ips(neutron_client)
if not (floatingips is None or len(floatingips) == 0):
for floatingip in floatingips:
- dic_floatingips.update({floatingip.id: floatingip.ip})
+ dic_floatingips.update({floatingip['id']:
+ floatingip['floating_ip_address']})
return {'floatingips': dic_floatingips}
@@ -136,6 +137,7 @@ def main():
neutron_client = os_utils.get_neutron_client()
keystone_client = os_utils.get_keystone_client()
cinder_client = os_utils.get_cinder_client()
+ glance_client = os_utils.get_glance_client()
if not os_utils.check_credentials():
logger.error("Please source the openrc credentials and run the" +
@@ -144,12 +146,12 @@ def main():
snapshot = {}
snapshot.update(get_instances(nova_client))
- snapshot.update(get_images(nova_client))
+ snapshot.update(get_images(glance_client))
snapshot.update(get_volumes(cinder_client))
snapshot.update(get_networks(neutron_client))
snapshot.update(get_routers(neutron_client))
snapshot.update(get_security_groups(neutron_client))
- snapshot.update(get_floatinips(nova_client))
+ snapshot.update(get_floatingips(neutron_client))
snapshot.update(get_users(keystone_client))
snapshot.update(get_tenants(keystone_client))
diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py
index f155449d..e7cdfc86 100644
--- a/functest/utils/openstack_utils.py
+++ b/functest/utils/openstack_utils.py
@@ -82,7 +82,8 @@ def get_env_cred_dict():
'OS_PROJECT_NAME': 'project_name',
'OS_ENDPOINT_TYPE': 'endpoint_type',
'OS_REGION_NAME': 'region_name',
- 'OS_CACERT': 'https_cacert'
+ 'OS_CACERT': 'https_cacert',
+ 'OS_INSECURE': 'https_insecure'
}
return env_cred_dict
@@ -150,10 +151,12 @@ def get_credentials_for_rally():
cred_key = env_cred_dict.get('OS_REGION_NAME')
rally_conf[cred_key] = region_name
- cacert = os.getenv('OS_CACERT')
- if cacert is not None:
- cred_key = env_cred_dict.get('OS_CACERT')
- rally_conf[cred_key] = cacert
+ cred_key = env_cred_dict.get('OS_CACERT')
+ rally_conf[cred_key] = os.getenv('OS_CACERT', '')
+
+ insecure_key = env_cred_dict.get('OS_INSECURE')
+ rally_conf[insecure_key] = os.getenv('OS_INSECURE', '').lower() == 'true'
+
return rally_conf
@@ -181,14 +184,10 @@ def get_endpoint(service_type, endpoint_type='publicURL'):
def get_session(other_creds={}):
auth = get_session_auth(other_creds)
- cacert = os.getenv('OS_CACERT')
- if cacert is not None:
- if not os.path.isfile(cacert):
- raise Exception("The 'OS_CACERT' environment"
- "variable is set to %s but the file"
- "does not exist.", cacert)
-
- return session.Session(auth=auth, verify=cacert)
+ https_cacert = os.getenv('OS_CACERT', '')
+ https_insecure = os.getenv('OS_INSECURE', '').lower() == 'true'
+ return session.Session(auth=auth,
+ verify=(https_cacert or not https_insecure))
# *********************************************
@@ -426,12 +425,12 @@ def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
return flavor_exists, flavor_id
-def get_floating_ips(nova_client):
+def get_floating_ips(neutron_client):
try:
- floating_ips = nova_client.floating_ips.list()
- return floating_ips
+ floating_ips = neutron_client.list_floatingips()
+ return floating_ips['floatingips']
except Exception as e:
- logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
+ logger.error("Error [get_floating_ips(neutron_client)]: %s" % e)
return None
@@ -594,12 +593,12 @@ def delete_instance(nova_client, instance_id):
return False
-def delete_floating_ip(nova_client, floatingip_id):
+def delete_floating_ip(neutron_client, floatingip_id):
try:
- nova_client.floating_ips.delete(floatingip_id)
+ neutron_client.delete_floatingip(floatingip_id)
return True
except Exception as e:
- logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
+ logger.error("Error [delete_floating_ip(neutron_client, '%s')]: %s"
% (floatingip_id, e))
return False
@@ -1192,9 +1191,9 @@ def delete_security_group(neutron_client, secgroup_id):
# *********************************************
# GLANCE
# *********************************************
-def get_images(nova_client):
+def get_images(glance_client):
try:
- images = nova_client.images.list()
+ images = glance_client.images.list()
return images
except Exception as e:
logger.error("Error [get_images]: %s" % e)
@@ -1258,12 +1257,12 @@ def get_or_create_image(name, path, format):
return image_exists, image_id
-def delete_glance_image(nova_client, image_id):
+def delete_glance_image(glance_client, image_id):
try:
- nova_client.images.delete(image_id)
+ glance_client.images.delete(image_id)
return True
except Exception as e:
- logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
+ logger.error("Error [delete_glance_image(glance_client, '%s')]: %s"
% (image_id, e))
return False