Merge "Catching new exception while disassociating a disassociated floating ip"
diff --git a/cli/__init__.py b/cli/__init__.py
index cea0b62..e97fe3e 100644
--- a/cli/__init__.py
+++ b/cli/__init__.py
@@ -16,8 +16,11 @@
# under the License.
import logging
+import shlex
+import subprocess
from tempest.openstack.common import cfg
+import tempest.test
LOG = logging.getLogger(__name__)
@@ -34,3 +37,45 @@
cli_group = cfg.OptGroup(name='cli', title="cli Configuration Options")
CONF.register_group(cli_group)
CONF.register_opts(cli_opts, group=cli_group)
+
+
+class ClientTestBase(tempest.test.BaseTestCase):
+ @classmethod
+ def setUpClass(cls):
+ if not CONF.cli.enabled:
+ msg = "cli testing disabled"
+ raise cls.skipException(msg)
+ cls.identity = cls.config.identity
+ super(ClientTestBase, cls).setUpClass()
+
+ def __init__(self, *args, **kwargs):
+ super(ClientTestBase, self).__init__(*args, **kwargs)
+
+ def nova(self, action, flags='', params='', admin=True, fail_ok=False):
+ """Executes nova command for the given action."""
+ return self.cmd_with_auth(
+ 'nova', action, flags, params, admin, fail_ok)
+
+ def cmd_with_auth(self, cmd, action, flags='', params='',
+ admin=True, fail_ok=False):
+ """Executes given command with auth attributes appended."""
+ #TODO(jogo) make admin=False work
+ creds = ('--os-username %s --os-tenant-name %s --os-password %s '
+ '--os-auth-url %s ' % (self.identity.admin_username,
+ self.identity.admin_tenant_name, self.identity.admin_password,
+ self.identity.uri))
+ flags = creds + ' ' + flags
+ return self.cmd(cmd, action, flags, params, fail_ok)
+
+ def cmd(self, cmd, action, flags='', params='', fail_ok=False):
+ """Executes specified command for the given action."""
+ cmd = ' '.join([CONF.cli.cli_dir + cmd,
+ flags, action, params])
+ LOG.info("running: '%s'" % cmd)
+ cmd = shlex.split(cmd)
+ try:
+ result = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError, e:
+ LOG.error("command output:\n%s" % e.output)
+ raise
+ return result
diff --git a/cli/simple_read_only/test_compute.py b/cli/simple_read_only/test_compute.py
index 073fde1..849ed6f 100644
--- a/cli/simple_read_only/test_compute.py
+++ b/cli/simple_read_only/test_compute.py
@@ -16,14 +16,12 @@
# under the License.
import logging
-import shlex
import subprocess
import testtools
import cli
-from tempest import config
from tempest.openstack.common import cfg
@@ -33,7 +31,7 @@
LOG = logging.getLogger(__name__)
-class SimpleReadOnlyNovaCLientTest(testtools.TestCase):
+class SimpleReadOnlyNovaClientTest(cli.ClientTestBase):
"""
This is a first pass at a simple read only python-novaclient test. This
@@ -47,33 +45,6 @@
"""
- @classmethod
- def setUpClass(cls):
- if not CONF.cli.enabled:
- msg = "cli testing disabled"
- raise cls.skipException(msg)
- cls.identity = config.TempestConfig().identity
- super(SimpleReadOnlyNovaCLientTest, cls).setUpClass()
-
- #NOTE(jogo): This should eventually be moved into a base class
- def nova(self, action, flags='', params='', admin=True, fail_ok=False):
- """Executes nova command for the given action."""
- #TODO(jogo) make admin=False work
- creds = ('--os-username %s --os-tenant-name %s --os-password %s '
- '--os-auth-url %s ' % (self.identity.admin_username,
- self.identity.admin_tenant_name, self.identity.admin_password,
- self.identity.uri))
- flags = creds + ' ' + flags
- cmd = ' '.join([CONF.cli.cli_dir + 'nova', flags, action, params])
- LOG.info("running: '%s'" % cmd)
- cmd = shlex.split(cmd)
- try:
- result = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
- except subprocess.CalledProcessError, e:
- LOG.error("command output:\n%s" % e.output)
- raise
- return result
-
def test_admin_fake_action(self):
self.assertRaises(subprocess.CalledProcessError,
self.nova,
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index 143257a..0870c96 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -17,7 +17,6 @@
import ConfigParser
import contextlib
-import re
import types
import urlparse
diff --git a/tempest/test.py b/tempest/test.py
index 90793ac..e0639b6 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -58,12 +58,11 @@
class TestCase(BaseTestCase):
-
- """
- Base test case class for all Tempest tests
+ """Base test case class for all Tempest tests
Contains basic setup and convenience methods
"""
+
manager_class = None
@classmethod
diff --git a/tempest/testboto.py b/tempest/testboto.py
index 5625841..cee8843 100644
--- a/tempest/testboto.py
+++ b/tempest/testboto.py
@@ -17,16 +17,21 @@
from contextlib import closing
import logging
+import os
import re
+import urlparse
import boto
from boto import ec2
from boto import exception
from boto import s3
+import keystoneclient.exceptions
+import tempest.clients
+from tempest.common.utils.file_utils import have_effective_read_access
+import tempest.config
from tempest import exceptions
import tempest.test
-import tempest.tests.boto
from tempest.tests.boto.utils.wait import re_search_wait
from tempest.tests.boto.utils.wait import state_wait
from tempest.tests.boto.utils.wait import wait_exception
@@ -34,6 +39,71 @@
LOG = logging.getLogger(__name__)
+def decision_maker():
+ A_I_IMAGES_READY = True # ari,ami,aki
+ S3_CAN_CONNECT_ERROR = None
+ EC2_CAN_CONNECT_ERROR = None
+ secret_matcher = re.compile("[A-Za-z0-9+/]{32,}") # 40 in other system
+ id_matcher = re.compile("[A-Za-z0-9]{20,}")
+
+ def all_read(*args):
+ return all(map(have_effective_read_access, args))
+
+ config = tempest.config.TempestConfig()
+ materials_path = config.boto.s3_materials_path
+ ami_path = materials_path + os.sep + config.boto.ami_manifest
+ aki_path = materials_path + os.sep + config.boto.aki_manifest
+ ari_path = materials_path + os.sep + config.boto.ari_manifest
+
+ A_I_IMAGES_READY = all_read(ami_path, aki_path, ari_path)
+ boto_logger = logging.getLogger('boto')
+ level = boto_logger.level
+ boto_logger.setLevel(logging.CRITICAL) # suppress logging for these
+
+ def _cred_sub_check(connection_data):
+ if not id_matcher.match(connection_data["aws_access_key_id"]):
+ raise Exception("Invalid AWS access Key")
+ if not secret_matcher.match(connection_data["aws_secret_access_key"]):
+ raise Exception("Invalid AWS secret Key")
+ raise Exception("Unknown (Authentication?) Error")
+ openstack = tempest.clients.Manager()
+ try:
+ if urlparse.urlparse(config.boto.ec2_url).hostname is None:
+ raise Exception("Failed to get hostname from the ec2_url")
+ ec2client = openstack.ec2api_client
+ try:
+ ec2client.get_all_regions()
+ except exception.BotoServerError as exc:
+ if exc.error_code is None:
+ raise Exception("EC2 target does not looks EC2 service")
+ _cred_sub_check(ec2client.connection_data)
+
+ except keystoneclient.exceptions.Unauthorized:
+ EC2_CAN_CONNECT_ERROR = "AWS credentials not set," +\
+ " faild to get them even by keystoneclient"
+ except Exception as exc:
+ EC2_CAN_CONNECT_ERROR = str(exc)
+
+ try:
+ if urlparse.urlparse(config.boto.s3_url).hostname is None:
+ raise Exception("Failed to get hostname from the s3_url")
+ s3client = openstack.s3_client
+ try:
+ s3client.get_bucket("^INVALID*#()@INVALID.")
+ except exception.BotoServerError as exc:
+ if exc.status == 403:
+ _cred_sub_check(s3client.connection_data)
+ except Exception as exc:
+ S3_CAN_CONNECT_ERROR = str(exc)
+ except keystoneclient.exceptions.Unauthorized:
+ S3_CAN_CONNECT_ERROR = "AWS credentials not set," +\
+ " faild to get them even by keystoneclient"
+ boto_logger.setLevel(level)
+ return {'A_I_IMAGES_READY': A_I_IMAGES_READY,
+ 'S3_CAN_CONNECT_ERROR': S3_CAN_CONNECT_ERROR,
+ 'EC2_CAN_CONNECT_ERROR': EC2_CAN_CONNECT_ERROR}
+
+
class BotoExceptionMatcher(object):
STATUS_RE = r'[45]\d\d'
CODE_RE = '.*' # regexp makes sense in group match
@@ -121,7 +191,7 @@
class BotoTestCase(tempest.test.BaseTestCase):
"""Recommended to use as base class for boto related test."""
- conclusion = tempest.tests.boto.generic_setup_package()
+ conclusion = decision_maker()
@classmethod
def setUpClass(cls):
@@ -130,13 +200,13 @@
cls._resource_trash_bin = {}
cls._sequence = -1
if (hasattr(cls, "EC2") and
- tempest.tests.boto.EC2_CAN_CONNECT_ERROR is not None):
+ cls.conclusion['EC2_CAN_CONNECT_ERROR'] is not None):
raise cls.skipException("EC2 " + cls.__name__ + ": " +
- tempest.tests.boto.EC2_CAN_CONNECT_ERROR)
+ cls.conclusion['EC2_CAN_CONNECT_ERROR'])
if (hasattr(cls, "S3") and
- tempest.tests.boto.S3_CAN_CONNECT_ERROR is not None):
+ cls.conclusion['S3_CAN_CONNECT_ERROR'] is not None):
raise cls.skipException("S3 " + cls.__name__ + ": " +
- tempest.tests.boto.S3_CAN_CONNECT_ERROR)
+ cls.conclusion['S3_CAN_CONNECT_ERROR'])
@classmethod
def addResourceCleanUp(cls, function, *args, **kwargs):
diff --git a/tempest/tests/boto/__init__.py b/tempest/tests/boto/__init__.py
index dd224d6..e69de29 100644
--- a/tempest/tests/boto/__init__.py
+++ b/tempest/tests/boto/__init__.py
@@ -1,94 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2012 OpenStack, LLC
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import logging
-import os
-import re
-import urlparse
-
-import boto.exception
-import keystoneclient.exceptions
-
-import tempest.clients
-from tempest.common.utils.file_utils import have_effective_read_access
-import tempest.config
-
-A_I_IMAGES_READY = True # ari,ami,aki
-S3_CAN_CONNECT_ERROR = None
-EC2_CAN_CONNECT_ERROR = None
-
-
-def generic_setup_package():
- global A_I_IMAGES_READY
- global S3_CAN_CONNECT_ERROR
- global EC2_CAN_CONNECT_ERROR
- secret_matcher = re.compile("[A-Za-z0-9+/]{32,}") # 40 in other system
- id_matcher = re.compile("[A-Za-z0-9]{20,}")
-
- def all_read(*args):
- return all(map(have_effective_read_access, args))
-
- config = tempest.config.TempestConfig()
- materials_path = config.boto.s3_materials_path
- ami_path = materials_path + os.sep + config.boto.ami_manifest
- aki_path = materials_path + os.sep + config.boto.aki_manifest
- ari_path = materials_path + os.sep + config.boto.ari_manifest
-
- A_I_IMAGES_READY = all_read(ami_path, aki_path, ari_path)
- boto_logger = logging.getLogger('boto')
- level = boto_logger.level
- boto_logger.setLevel(logging.CRITICAL) # suppress logging for these
-
- def _cred_sub_check(connection_data):
- if not id_matcher.match(connection_data["aws_access_key_id"]):
- raise Exception("Invalid AWS access Key")
- if not secret_matcher.match(connection_data["aws_secret_access_key"]):
- raise Exception("Invalid AWS secret Key")
- raise Exception("Unknown (Authentication?) Error")
- openstack = tempest.clients.Manager()
- try:
- if urlparse.urlparse(config.boto.ec2_url).hostname is None:
- raise Exception("Failed to get hostname from the ec2_url")
- ec2client = openstack.ec2api_client
- try:
- ec2client.get_all_regions()
- except boto.exception.BotoServerError as exc:
- if exc.error_code is None:
- raise Exception("EC2 target does not looks EC2 service")
- _cred_sub_check(ec2client.connection_data)
-
- except keystoneclient.exceptions.Unauthorized:
- EC2_CAN_CONNECT_ERROR = "AWS credentials not set," +\
- " faild to get them even by keystoneclient"
- except Exception as exc:
- EC2_CAN_CONNECT_ERROR = str(exc)
-
- try:
- if urlparse.urlparse(config.boto.s3_url).hostname is None:
- raise Exception("Failed to get hostname from the s3_url")
- s3client = openstack.s3_client
- try:
- s3client.get_bucket("^INVALID*#()@INVALID.")
- except boto.exception.BotoServerError as exc:
- if exc.status == 403:
- _cred_sub_check(s3client.connection_data)
- except Exception as exc:
- S3_CAN_CONNECT_ERROR = str(exc)
- except keystoneclient.exceptions.Unauthorized:
- S3_CAN_CONNECT_ERROR = "AWS credentials not set," +\
- " faild to get them even by keystoneclient"
- boto_logger.setLevel(level)
diff --git a/tempest/tests/boto/test_ec2_instance_run.py b/tempest/tests/boto/test_ec2_instance_run.py
index 6b61c11..98fdc8b 100644
--- a/tempest/tests/boto/test_ec2_instance_run.py
+++ b/tempest/tests/boto/test_ec2_instance_run.py
@@ -17,15 +17,15 @@
import logging
-from boto.exception import EC2ResponseError
+from boto import exception
import testtools
from tempest import clients
from tempest.common.utils.data_utils import rand_name
from tempest.common.utils.linux.remote_client import RemoteClient
+from tempest import exceptions
from tempest.test import attr
from tempest.testboto import BotoTestCase
-import tempest.tests.boto
from tempest.tests.boto.utils.s3 import s3_upload_dir
from tempest.tests.boto.utils.wait import re_search_wait
from tempest.tests.boto.utils.wait import state_wait
@@ -39,7 +39,7 @@
@classmethod
def setUpClass(cls):
super(InstanceRunTest, cls).setUpClass()
- if not tempest.tests.boto.A_I_IMAGES_READY:
+ if not cls.conclusion['A_I_IMAGES_READY']:
raise cls.skipException("".join(("EC2 ", cls.__name__,
": requires ami/aki/ari manifest")))
cls.os = clients.Manager()
@@ -86,7 +86,8 @@
if state != "available":
for _image in cls.images.itervalues():
cls.ec2_client.deregister_image(_image["image_id"])
- raise EC2RegisterImageException(image_id=image["image_id"])
+ raise exceptions.EC2RegisterImageException(image_id=
+ image["image_id"])
@attr(type='smoke')
def test_run_stop_terminate_instance(self):
@@ -129,7 +130,7 @@
instance.update(validate=True)
except ValueError:
pass
- except EC2ResponseError as exc:
+ except exception.EC2ResponseError as exc:
if self.ec2_error_code.\
client.InvalidInstanceID.NotFound.match(exc):
pass
diff --git a/tempest/tests/boto/test_s3_ec2_images.py b/tempest/tests/boto/test_s3_ec2_images.py
index 1088b00..4068aba 100644
--- a/tempest/tests/boto/test_s3_ec2_images.py
+++ b/tempest/tests/boto/test_s3_ec2_images.py
@@ -23,7 +23,6 @@
from tempest.common.utils.data_utils import rand_name
from tempest.test import attr
from tempest.testboto import BotoTestCase
-import tempest.tests.boto
from tempest.tests.boto.utils.s3 import s3_upload_dir
from tempest.tests.boto.utils.wait import state_wait
@@ -34,7 +33,7 @@
@classmethod
def setUpClass(cls):
super(S3ImagesTest, cls).setUpClass()
- if not tempest.tests.boto.A_I_IMAGES_READY:
+ if not cls.conclusion['A_I_IMAGES_READY']:
raise cls.skipException("".join(("EC2 ", cls.__name__,
": requires ami/aki/ari manifest")))
cls.os = clients.Manager()