Merge "[Verify] Add tempest configs and move to new section"

This commit is contained in:
Jenkins 2016-06-09 17:16:36 +00:00 committed by Gerrit Code Review
commit 39dc633d41
4 changed files with 124 additions and 87 deletions

View File

@ -6,10 +6,11 @@
# If set to true, the logging level will be set to DEBUG instead of # If set to true, the logging level will be set to DEBUG instead of
# the default INFO level. (boolean value) # the default INFO level. (boolean value)
# Note: This option can be changed without restarting.
#debug = false #debug = false
# If set to false, the logging level will be set to WARNING instead of # DEPRECATED: If set to false, the logging level will be set to
# the default INFO level. (boolean value) # WARNING instead of the default INFO level. (boolean value)
# This option is deprecated for removal. # This option is deprecated for removal.
# Its value may be silently ignored in the future. # Its value may be silently ignored in the future.
#verbose = true #verbose = true
@ -155,13 +156,6 @@
# point value) # point value)
#glance_image_create_poll_interval = 1.0 #glance_image_create_poll_interval = 1.0
# Time to wait for glance image to be deleted. (floating point value)
#glance_image_delete_timeout = 120.0
# Interval between checks when waiting for image deletion. (floating
# point value)
#glance_image_delete_poll_interval = 1.0
# Time(in sec) to sleep after creating a resource before polling for # Time(in sec) to sleep after creating a resource before polling for
# it status. (floating point value) # it status. (floating point value)
#heat_stack_create_prepoll_delay = 2.0 #heat_stack_create_prepoll_delay = 2.0
@ -635,51 +629,74 @@
#db_max_retries = 20 #db_max_retries = 20
[image] [roles_context]
# #
# From rally # From rally
# #
# CirrOS image URL (string value) # How many concurrent threads to use for serving roles context
#cirros_img_url = http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img # (integer value)
#resource_management_workers = 30
[tempest]
#
# From rally
#
# image URL (string value)
# Deprecated group/name - [image]/cirros_img_url
#img_url = http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img
# Image disk format to use when creating the image (string value) # Image disk format to use when creating the image (string value)
#disk_format = qcow2 # Deprecated group/name - [image]/disk_format
#img_disk_format = qcow2
# Image container format to use when creating the image (string value) # Image container format to use when creating the image (string value)
#container_format = bare # Deprecated group/name - [image]/container_format
#img_container_format = bare
# Regular expression for name of a public image to discover it in the # Regular expression for name of a public image to discover it in the
# cloud and use it for the tests. Note that when Rally is searching # cloud and use it for the tests. Note that when Rally is searching
# for the image, case insensitive matching is performed. Specify # for the image, case insensitive matching is performed. Specify
# nothing ('name_regex =') if you want to disable discovering. In this # nothing ('img_name_regex =') if you want to disable discovering. In
# case Rally will create needed resources by itself if the values for # this case Rally will create needed resources by itself if the values
# the corresponding config options are not specified in the Tempest # for the corresponding config options are not specified in the
# config file (string value) # Tempest config file (string value)
#name_regex = ^.*(cirros|testvm).*$ # Deprecated group/name - [image]/name_regex
#img_name_regex = ^.*(cirros|testvm).*$
[role]
#
# From rally
#
# Role required for users to be able to create Swift containers # Role required for users to be able to create Swift containers
# (string value) # (string value)
# Deprecated group/name - [role]/swift_operator_role
#swift_operator_role = Member #swift_operator_role = Member
# User role that has reseller admin (string value) # User role that has reseller admin (string value)
# Deprecated group/name - [role]/swift_reseller_admin_role
#swift_reseller_admin_role = ResellerAdmin #swift_reseller_admin_role = ResellerAdmin
# Role required for users to be able to manage Heat stacks (string # Role required for users to be able to manage Heat stacks (string
# value) # value)
# Deprecated group/name - [role]/heat_stack_owner_role
#heat_stack_owner_role = heat_stack_owner #heat_stack_owner_role = heat_stack_owner
# Role for Heat template-defined users (string value) # Role for Heat template-defined users (string value)
# Deprecated group/name - [role]/heat_stack_user_role
#heat_stack_user_role = heat_stack_user #heat_stack_user_role = heat_stack_user
# Primary flavor RAM size used by most of the test cases (integer
# value)
#flavor_ref_ram = 64
# Alternate reference flavor RAM size used by test thatneed two
# flavors, like those that resize an instnace (integer value)
#flavor_ref_alt_ram = 128
# RAM size flavor used for orchestration test cases (integer value)
#heat_instance_type_ram = 64
[users_context] [users_context]

View File

@ -48,9 +48,8 @@ def list_opts():
nova_utils.NOVA_BENCHMARK_OPTS, nova_utils.NOVA_BENCHMARK_OPTS,
sahara_utils.SAHARA_BENCHMARK_OPTS, sahara_utils.SAHARA_BENCHMARK_OPTS,
vm_utils.VM_BENCHMARK_OPTS)), vm_utils.VM_BENCHMARK_OPTS)),
("image", ("tempest",
itertools.chain(tempest_conf.IMAGE_OPTS)), itertools.chain(tempest_conf.TEMPEST_OPTS)),
("role", itertools.chain(tempest_conf.ROLE_OPTS)),
("roles_context", itertools.chain(roles.ROLES_CONTEXT_OPTS)), ("roles_context", itertools.chain(roles.ROLES_CONTEXT_OPTS)),
("users_context", itertools.chain(users.USER_CONTEXT_OPTS)), ("users_context", itertools.chain(users.USER_CONTEXT_OPTS)),
("cleanup", itertools.chain(cleanup_base.CLEANUP_OPTS)) ("cleanup", itertools.chain(cleanup_base.CLEANUP_OPTS))

View File

@ -38,49 +38,67 @@ from rally.task import utils as task_utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
IMAGE_OPTS = [ TEMPEST_OPTS = [
cfg.StrOpt("cirros_img_url", cfg.StrOpt("img_url",
deprecated_opts=[cfg.DeprecatedOpt("cirros_img_url",
group="image")],
default="http://download.cirros-cloud.net/" default="http://download.cirros-cloud.net/"
"0.3.4/cirros-0.3.4-x86_64-disk.img", "0.3.4/cirros-0.3.4-x86_64-disk.img",
help="CirrOS image URL"), help="image URL"),
cfg.StrOpt("disk_format", cfg.StrOpt("img_disk_format",
deprecated_opts=[cfg.DeprecatedOpt("disk_format",
group="image")],
default="qcow2", default="qcow2",
help="Image disk format to use when creating the image"), help="Image disk format to use when creating the image"),
cfg.StrOpt("container_format", cfg.StrOpt("img_container_format",
deprecated_opts=[cfg.DeprecatedOpt("container_format",
group="image")],
default="bare", default="bare",
help="Image container format to use when creating the image"), help="Image container format to use when creating the image"),
cfg.StrOpt("name_regex", cfg.StrOpt("img_name_regex",
deprecated_opts=[cfg.DeprecatedOpt("name_regex",
group="image")],
default="^.*(cirros|testvm).*$", default="^.*(cirros|testvm).*$",
help="Regular expression for name of a public image to " help="Regular expression for name of a public image to "
"discover it in the cloud and use it for the tests. " "discover it in the cloud and use it for the tests. "
"Note that when Rally is searching for the image, case " "Note that when Rally is searching for the image, case "
"insensitive matching is performed. Specify nothing " "insensitive matching is performed. Specify nothing "
"('name_regex =') if you want to disable discovering. " "('img_name_regex =') if you want to disable discovering. "
"In this case Rally will create needed resources by " "In this case Rally will create needed resources by "
"itself if the values for the corresponding config " "itself if the values for the corresponding config "
"options are not specified in the Tempest config file") "options are not specified in the Tempest config file"),
]
ROLE_OPTS = [
cfg.StrOpt("swift_operator_role", cfg.StrOpt("swift_operator_role",
deprecated_group="role",
default="Member", default="Member",
help="Role required for users " help="Role required for users "
"to be able to create Swift containers"), "to be able to create Swift containers"),
cfg.StrOpt("swift_reseller_admin_role", cfg.StrOpt("swift_reseller_admin_role",
deprecated_group="role",
default="ResellerAdmin", default="ResellerAdmin",
help="User role that has reseller admin"), help="User role that has reseller admin"),
cfg.StrOpt("heat_stack_owner_role", cfg.StrOpt("heat_stack_owner_role",
deprecated_group="role",
default="heat_stack_owner", default="heat_stack_owner",
help="Role required for users " help="Role required for users "
"to be able to manage Heat stacks"), "to be able to manage Heat stacks"),
cfg.StrOpt("heat_stack_user_role", cfg.StrOpt("heat_stack_user_role",
deprecated_group="role",
default="heat_stack_user", default="heat_stack_user",
help="Role for Heat template-defined users") help="Role for Heat template-defined users"),
cfg.IntOpt("flavor_ref_ram",
default="64",
help="Primary flavor RAM size used by most of the test cases"),
cfg.IntOpt("flavor_ref_alt_ram",
default="128",
help="Alternate reference flavor RAM size used by test that"
"need two flavors, like those that resize an instnace"),
cfg.IntOpt("heat_instance_type_ram",
default="64",
help="RAM size flavor used for orchestration test cases")
] ]
CONF = cfg.CONF CONF = cfg.CONF
CONF.register_opts(IMAGE_OPTS, "image") CONF.register_opts(TEMPEST_OPTS, "tempest")
CONF.register_opts(ROLE_OPTS, "role")
CONF.import_opt("glance_image_delete_timeout", CONF.import_opt("glance_image_delete_timeout",
"rally.plugins.openstack.scenarios.glance.utils", "rally.plugins.openstack.scenarios.glance.utils",
"benchmark") "benchmark")
@ -120,18 +138,18 @@ class TempestConfig(utils.RandomNameGeneratorMixin):
self.conf.read(os.path.join(os.path.dirname(__file__), "config.ini")) self.conf.read(os.path.join(os.path.dirname(__file__), "config.ini"))
self.image_name = parse.urlparse( self.image_name = parse.urlparse(
CONF.image.cirros_img_url).path.split("/")[-1] CONF.tempest.img_url).path.split("/")[-1]
self._download_cirros_image() self._download_image()
def _download_cirros_image(self): def _download_image(self):
img_path = os.path.join(self.data_dir, self.image_name) img_path = os.path.join(self.data_dir, self.image_name)
if os.path.isfile(img_path): if os.path.isfile(img_path):
return return
try: try:
response = requests.get(CONF.image.cirros_img_url, stream=True) response = requests.get(CONF.tempest.img_url, stream=True)
except requests.ConnectionError as err: except requests.ConnectionError as err:
msg = _("Failed to download CirrOS image. " msg = _("Failed to download image. "
"Possibly there is no connection to Internet. " "Possibly there is no connection to Internet. "
"Error: %s.") % (str(err) or "unknown") "Error: %s.") % (str(err) or "unknown")
raise exceptions.TempestConfigCreationFailure(msg) raise exceptions.TempestConfigCreationFailure(msg)
@ -145,10 +163,10 @@ class TempestConfig(utils.RandomNameGeneratorMixin):
os.rename(img_path + ".tmp", img_path) os.rename(img_path + ".tmp", img_path)
else: else:
if response.status_code == 404: if response.status_code == 404:
msg = _("Failed to download CirrOS image. " msg = _("Failed to download image. "
"Image was not found.") "Image was not found.")
else: else:
msg = _("Failed to download CirrOS image. " msg = _("Failed to download image. "
"HTTP error code %d.") % response.status_code "HTTP error code %d.") % response.status_code
raise exceptions.TempestConfigCreationFailure(msg) raise exceptions.TempestConfigCreationFailure(msg)
@ -280,9 +298,9 @@ class TempestConfig(utils.RandomNameGeneratorMixin):
def _configure_object_storage(self, section_name="object-storage"): def _configure_object_storage(self, section_name="object-storage"):
self.conf.set(section_name, "operator_role", self.conf.set(section_name, "operator_role",
CONF.role.swift_operator_role) CONF.tempest.swift_operator_role)
self.conf.set(section_name, "reseller_admin_role", self.conf.set(section_name, "reseller_admin_role",
CONF.role.swift_reseller_admin_role) CONF.tempest.swift_reseller_admin_role)
def _configure_scenario(self, section_name="scenario"): def _configure_scenario(self, section_name="scenario"):
self.conf.set(section_name, "img_dir", self.data_dir) self.conf.set(section_name, "img_dir", self.data_dir)
@ -321,9 +339,9 @@ class TempestConfig(utils.RandomNameGeneratorMixin):
def _configure_orchestration(self, section_name="orchestration"): def _configure_orchestration(self, section_name="orchestration"):
self.conf.set(section_name, "stack_owner_role", self.conf.set(section_name, "stack_owner_role",
CONF.role.heat_stack_owner_role) CONF.tempest.heat_stack_owner_role)
self.conf.set(section_name, "stack_user_role", self.conf.set(section_name, "stack_user_role",
CONF.role.heat_stack_user_role) CONF.tempest.heat_stack_user_role)
def generate(self, conf_path=None): def generate(self, conf_path=None):
for name, method in inspect.getmembers(self, inspect.ismethod): for name, method in inspect.getmembers(self, inspect.ismethod):
@ -351,7 +369,7 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
self.conf.read(conf_path) self.conf.read(conf_path)
self.image_name = parse.urlparse( self.image_name = parse.urlparse(
CONF.image.cirros_img_url).path.split("/")[-1] CONF.tempest.img_url).path.split("/")[-1]
self._created_roles = [] self._created_roles = []
self._created_images = [] self._created_images = []
@ -365,9 +383,11 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
self._configure_option("compute", "image_ref_alt", self._configure_option("compute", "image_ref_alt",
self._discover_or_create_image) self._discover_or_create_image)
self._configure_option("compute", "flavor_ref", self._configure_option("compute", "flavor_ref",
self._discover_or_create_flavor, 64) self._discover_or_create_flavor,
CONF.tempest.flavor_ref_ram)
self._configure_option("compute", "flavor_ref_alt", self._configure_option("compute", "flavor_ref_alt",
self._discover_or_create_flavor, 128) self._discover_or_create_flavor,
CONF.tempest.flavor_ref_alt_ram)
if "neutron" in self.available_services: if "neutron" in self.available_services:
neutronclient = self.clients.neutron() neutronclient = self.clients.neutron()
if neutronclient.list_networks(shared=True)["networks"]: if neutronclient.list_networks(shared=True)["networks"]:
@ -384,7 +404,8 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
self._create_network_resources) self._create_network_resources)
if "heat" in self.available_services: if "heat" in self.available_services:
self._configure_option("orchestration", "instance_type", self._configure_option("orchestration", "instance_type",
self._discover_or_create_flavor, 64) self._discover_or_create_flavor,
CONF.tempest.heat_instance_type_ram)
_write_config(self.conf_path, self.conf) _write_config(self.conf_path, self.conf)
@ -404,10 +425,10 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
def _create_tempest_roles(self): def _create_tempest_roles(self):
keystoneclient = self.clients.verified_keystone() keystoneclient = self.clients.verified_keystone()
roles = [CONF.role.swift_operator_role, roles = [CONF.tempest.swift_operator_role,
CONF.role.swift_reseller_admin_role, CONF.tempest.swift_reseller_admin_role,
CONF.role.heat_stack_owner_role, CONF.tempest.heat_stack_owner_role,
CONF.role.heat_stack_user_role] CONF.tempest.heat_stack_user_role]
existing_roles = set(role.name for role in keystoneclient.roles.list()) existing_roles = set(role.name for role in keystoneclient.roles.list())
for role in roles: for role in roles:
@ -435,14 +456,14 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
def _discover_or_create_image(self): def _discover_or_create_image(self):
glance_wrapper = glance.wrap(self.clients.glance, self) glance_wrapper = glance.wrap(self.clients.glance, self)
if CONF.image.name_regex: if CONF.tempest.img_name_regex:
LOG.debug("Trying to discover a public image with name matching " LOG.debug("Trying to discover a public image with name matching "
"regular expression '%s'. Note that case insensitive " "regular expression '%s'. Note that case insensitive "
"matching is performed" % CONF.image.name_regex) "matching is performed" % CONF.tempest.img_name_regex)
images = glance_wrapper.list_images(status="active", images = glance_wrapper.list_images(status="active",
visibility="public") visibility="public")
for img in images: for img in images:
if img.name and re.match(CONF.image.name_regex, if img.name and re.match(CONF.tempest.img_name_regex,
img.name, re.IGNORECASE): img.name, re.IGNORECASE):
LOG.debug( LOG.debug(
"The following public image discovered: '{0}'. " "The following public image discovered: '{0}'. "
@ -450,12 +471,12 @@ class TempestResourcesContext(utils.RandomNameGeneratorMixin):
return img return img
LOG.debug("There is no public image with name matching " LOG.debug("There is no public image with name matching "
"regular expression '%s'" % CONF.image.name_regex) "regular expression '%s'" % CONF.tempest.img_name_regex)
params = { params = {
"name": self.generate_random_name(), "name": self.generate_random_name(),
"disk_format": CONF.image.disk_format, "disk_format": CONF.tempest.img_disk_format,
"container_format": CONF.image.container_format, "container_format": CONF.tempest.img_container_format,
"image_location": os.path.join(_create_or_get_data_dir(), "image_location": os.path.join(_create_or_get_data_dir(),
self.image_name), self.image_name),
"visibility": "public" "visibility": "public"

View File

@ -61,26 +61,26 @@ class TempestConfigTestCase(test.TestCase):
@mock.patch("os.rename") @mock.patch("os.rename")
@mock.patch("six.moves.builtins.open", side_effect=mock.mock_open()) @mock.patch("six.moves.builtins.open", side_effect=mock.mock_open())
@mock.patch("requests.get", return_value=mock.MagicMock(status_code=200)) @mock.patch("requests.get", return_value=mock.MagicMock(status_code=200))
def test__download_cirros_image_success(self, mock_get, def test__download_image_success(self, mock_get,
mock_open, mock_rename): mock_open, mock_rename):
self.mock_isfile.return_value = False self.mock_isfile.return_value = False
self.tempest_conf._download_cirros_image() self.tempest_conf._download_image()
mock_get.assert_called_once_with( mock_get.assert_called_once_with(
CONF.image.cirros_img_url, stream=True) CONF.tempest.img_url, stream=True)
@mock.patch("requests.get") @mock.patch("requests.get")
@ddt.data(404, 500) @ddt.data(404, 500)
def test__download_cirros_image_failure(self, status_code, mock_get): def test__download_image_failure(self, status_code, mock_get):
self.mock_isfile.return_value = False self.mock_isfile.return_value = False
mock_get.return_value = mock.MagicMock(status_code=status_code) mock_get.return_value = mock.MagicMock(status_code=status_code)
self.assertRaises(exceptions.TempestConfigCreationFailure, self.assertRaises(exceptions.TempestConfigCreationFailure,
self.tempest_conf._download_cirros_image) self.tempest_conf._download_image)
@mock.patch("requests.get", side_effect=requests.ConnectionError()) @mock.patch("requests.get", side_effect=requests.ConnectionError())
def test__download_cirros_image_connection_error(self, mock_requests_get): def test__download_image_connection_error(self, mock_requests_get):
self.mock_isfile.return_value = False self.mock_isfile.return_value = False
self.assertRaises(exceptions.TempestConfigCreationFailure, self.assertRaises(exceptions.TempestConfigCreationFailure,
self.tempest_conf._download_cirros_image) self.tempest_conf._download_image)
@ddt.data({"publicURL": "test_url"}, @ddt.data({"publicURL": "test_url"},
{"interface": "public", "url": "test_url"}) {"interface": "public", "url": "test_url"})
@ -228,8 +228,8 @@ class TempestConfigTestCase(test.TestCase):
self.tempest_conf._configure_object_storage() self.tempest_conf._configure_object_storage()
expected = ( expected = (
("operator_role", CONF.role.swift_operator_role), ("operator_role", CONF.tempest.swift_operator_role),
("reseller_admin_role", CONF.role.swift_reseller_admin_role)) ("reseller_admin_role", CONF.tempest.swift_reseller_admin_role))
result = self.tempest_conf.conf.items("object-storage") result = self.tempest_conf.conf.items("object-storage")
for item in expected: for item in expected:
self.assertIn(item, result) self.assertIn(item, result)
@ -238,8 +238,8 @@ class TempestConfigTestCase(test.TestCase):
self.tempest_conf._configure_orchestration() self.tempest_conf._configure_orchestration()
expected = ( expected = (
("stack_owner_role", CONF.role.heat_stack_owner_role), ("stack_owner_role", CONF.tempest.heat_stack_owner_role),
("stack_user_role", CONF.role.heat_stack_user_role)) ("stack_user_role", CONF.tempest.heat_stack_user_role))
result = self.tempest_conf.conf.items("orchestration") result = self.tempest_conf.conf.items("orchestration")
for item in expected: for item in expected:
self.assertIn(item, result) self.assertIn(item, result)
@ -248,7 +248,7 @@ class TempestConfigTestCase(test.TestCase):
self.tempest_conf._configure_scenario() self.tempest_conf._configure_scenario()
image_name = parse.urlparse( image_name = parse.urlparse(
config.CONF.image.cirros_img_url).path.split("/")[-1] config.CONF.tempest.img_url).path.split("/")[-1]
expected = (("img_dir", self.tempest_conf.data_dir), expected = (("img_dir", self.tempest_conf.data_dir),
("img_file", image_name)) ("img_file", image_name))
result = self.tempest_conf.conf.items("scenario") result = self.tempest_conf.conf.items("scenario")
@ -370,10 +370,10 @@ class TempestResourcesContextTestCase(test.TestCase):
self.assertEqual(mock_neutron_wrapper_create_network.call_count, 0) self.assertEqual(mock_neutron_wrapper_create_network.call_count, 0)
def test__create_tempest_roles(self): def test__create_tempest_roles(self):
role1 = CONF.role.swift_operator_role role1 = CONF.tempest.swift_operator_role
role2 = CONF.role.swift_reseller_admin_role role2 = CONF.tempest.swift_reseller_admin_role
role3 = CONF.role.heat_stack_owner_role role3 = CONF.tempest.heat_stack_owner_role
role4 = CONF.role.heat_stack_user_role role4 = CONF.tempest.heat_stack_user_role
client = self.context.clients.verified_keystone() client = self.context.clients.verified_keystone()
client.roles.list.return_value = [fakes.FakeRole(name=role1), client.roles.list.return_value = [fakes.FakeRole(name=role1),
@ -423,9 +423,9 @@ class TempestResourcesContextTestCase(test.TestCase):
mock_wrap.assert_called_once_with(self.context.clients.glance, mock_wrap.assert_called_once_with(self.context.clients.glance,
self.context) self.context)
client.create_image.assert_called_once_with( client.create_image.assert_called_once_with(
container_format=CONF.image.container_format, container_format=CONF.tempest.img_container_format,
image_location=mock.ANY, image_location=mock.ANY,
disk_format=CONF.image.disk_format, disk_format=CONF.tempest.img_disk_format,
name=mock.ANY, name=mock.ANY,
visibility="public") visibility="public")