Merge "Ensure subnet for port security group tests"
diff --git a/doc/source/index.rst b/doc/source/index.rst
index bc4fc46..1f06bc5 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -37,6 +37,7 @@
:maxdepth: 1
cleanup
+ javelin
==================
Indices and tables
diff --git a/doc/source/javelin.rst b/doc/source/javelin.rst
new file mode 100644
index 0000000..01090ca
--- /dev/null
+++ b/doc/source/javelin.rst
@@ -0,0 +1,5 @@
+----------------------------------------------------------
+Javelin2 - How to check that resources survived an upgrade
+----------------------------------------------------------
+
+.. automodule:: tempest.cmd.javelin
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index b396503..a9778e3 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -256,9 +256,6 @@
# Catalog type of the Compute service. (string value)
#catalog_type = compute
-# Catalog type of the Compute v3 service. (string value)
-#catalog_v3_type = computev3
-
# The endpoint type to use for the compute service. (string value)
#endpoint_type = publicURL
@@ -363,27 +360,6 @@
#volume_device_name = vdb
-[compute-admin]
-
-#
-# From tempest.config
-#
-
-# Domain name for authentication as admin (Keystone V3).The same
-# domain applies to user and project (string value)
-#domain_name = <None>
-
-# API key to use when authenticating as admin. (string value)
-#password = <None>
-
-# Administrative Tenant name to use for Nova API requests. (string
-# value)
-#tenant_name = <None>
-
-# Administrative Username to use for Nova API requests. (string value)
-#username = <None>
-
-
[compute-feature-enabled]
#
@@ -396,15 +372,6 @@
# disabled (list value)
#api_extensions = all
-# If false, skip all nova v3 tests. (boolean value)
-#api_v3 = false
-
-# A list of enabled v3 extensions with a special entry all which
-# indicates every extension is enabled. Each extension should be
-# specified with alias name. Empty list indicates all extensions are
-# disabled (list value)
-#api_v3_extensions = all
-
# Does the test environment block migration support cinder iSCSI
# volumes (boolean value)
#block_migrate_cinder_iscsi = false
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 38a623a..bc45da5 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -232,99 +232,6 @@
self.assertFalse(self.created_set - self.dup_set <= result_set)
-class ListSnapshotImagesTest(base.BaseV1ImageTest):
- @classmethod
- def resource_setup(cls):
- # This test class only uses nova v3 api to create snapshot
- # as the similar test which uses nova v2 api already exists
- # in nova v2 compute images api tests.
- # Since nova v3 doesn't have images api proxy, this test
- # class was added in the image api tests.
- if not CONF.compute_feature_enabled.api_v3:
- skip_msg = ("%s skipped as nova v3 api is not available" %
- cls.__name__)
- raise cls.skipException(skip_msg)
- super(ListSnapshotImagesTest, cls).resource_setup()
- cls.servers_client = cls.os.servers_v3_client
- cls.servers = []
- # We add a few images here to test the listing functionality of
- # the images API
- cls.snapshot = cls._create_snapshot(
- 'snapshot', CONF.compute.image_ref,
- CONF.compute.flavor_ref)
- cls.snapshot_set = set((cls.snapshot,))
-
- image_file = StringIO.StringIO('*' * 42)
- _, image = cls.create_image(name="Standard Image",
- container_format='ami',
- disk_format='ami',
- is_public=False, data=image_file)
- cls.image_id = image['id']
- cls.client.wait_for_image_status(image['id'], 'active')
-
- @classmethod
- def resource_cleanup(cls):
- for server in getattr(cls, "servers", []):
- cls.servers_client.delete_server(server['id'])
- super(ListSnapshotImagesTest, cls).resource_cleanup()
-
- @classmethod
- def _create_snapshot(cls, name, image_id, flavor, **kwargs):
- _, server = cls.servers_client.create_server(
- name, image_id, flavor, **kwargs)
- cls.servers.append(server)
- cls.servers_client.wait_for_server_status(
- server['id'], 'ACTIVE')
- resp, _ = cls.servers_client.create_image(server['id'], name)
- image_id = data_utils.parse_image_id(resp['location'])
- cls.created_images.append(image_id)
- cls.client.wait_for_image_status(image_id,
- 'active')
- return image_id
-
- @test.attr(type='gate')
- @test.services('compute')
- def test_index_server_id(self):
- # The images should contain images filtered by server id
- _, images = self.client.image_list_detail(
- {'instance_uuid': self.servers[0]['id']})
- result_set = set(map(lambda x: x['id'], images))
- self.assertEqual(self.snapshot_set, result_set)
-
- @test.attr(type='gate')
- @test.services('compute')
- def test_index_type(self):
- # The list of servers should be filtered by image type
- params = {'image_type': 'snapshot'}
- _, images = self.client.image_list_detail(params)
-
- result_set = set(map(lambda x: x['id'], images))
- self.assertIn(self.snapshot, result_set)
-
- @test.attr(type='gate')
- @test.services('compute')
- def test_index_limit(self):
- # Verify only the expected number of results are returned
- _, images = self.client.image_list_detail(limit=1)
-
- self.assertEqual(1, len(images))
-
- @test.attr(type='gate')
- @test.services('compute')
- def test_index_by_change_since(self):
- # Verify an update image is returned
- # Becoming ACTIVE will modify the updated time
- # Filter by the image's created time
- _, image = self.client.get_image_meta(self.snapshot)
- self.assertEqual(self.snapshot, image['id'])
- _, images = self.client.image_list_detail(
- changes_since=image['updated_at'])
-
- result_set = set(map(lambda x: x['id'], images))
- self.assertIn(self.image_id, result_set)
- self.assertNotIn(self.snapshot, result_set)
-
-
class UpdateImageMetaTest(base.BaseV1ImageTest):
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 1f827da..e70519e 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -66,7 +66,8 @@
super(NetworksTestJSON, cls).resource_setup()
cls.network = cls.create_network()
cls.name = cls.network['name']
- cls.subnet = cls.create_subnet(cls.network)
+ cls.subnet = cls._create_subnet_with_last_subnet_block(cls.network,
+ cls._ip_version)
cls.cidr = cls.subnet['cidr']
cls._subnet_data = {6: {'gateway':
str(cls._get_gateway_from_tempest_conf(6)),
@@ -96,6 +97,23 @@
'new_dns_nameservers': ['7.8.8.8', '7.8.4.4']}}
@classmethod
+ def _create_subnet_with_last_subnet_block(cls, network, ip_version):
+ """Derive last subnet CIDR block from tenant CIDR and
+ create the subnet with that derived CIDR
+ """
+ if ip_version == 4:
+ cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
+ mask_bits = CONF.network.tenant_network_mask_bits
+ elif ip_version == 6:
+ cidr = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
+ mask_bits = CONF.network.tenant_network_v6_mask_bits
+
+ subnet_cidr = list(cidr.subnet(mask_bits))[-1]
+ gateway_ip = str(netaddr.IPAddress(subnet_cidr) + 1)
+ return cls.create_subnet(network, gateway=gateway_ip,
+ cidr=subnet_cidr, mask_bits=mask_bits)
+
+ @classmethod
def _get_gateway_from_tempest_conf(cls, ip_version):
"""Return first subnet gateway for configured CIDR """
if ip_version == 4:
@@ -129,6 +147,15 @@
self.assertThat(actual, custom_matchers.MatchesDictExceptForKeys(
expected, exclude_keys))
+ def _delete_network(self, network):
+ # Deleting network also deletes its subnets if exists
+ self.client.delete_network(network['id'])
+ if network in self.networks:
+ self.networks.remove(network)
+ for subnet in self.subnets:
+ if subnet['network_id'] == network['id']:
+ self.subnets.remove(subnet)
+
def _create_verify_delete_subnet(self, cidr=None, mask_bits=None,
**kwargs):
network = self.create_network()
@@ -156,6 +183,7 @@
# Create a network
name = data_utils.rand_name('network-')
network = self.create_network(network_name=name)
+ self.addCleanup(self._delete_network, network)
net_id = network['id']
self.assertEqual('ACTIVE', network['status'])
# Verify network update
@@ -312,6 +340,7 @@
@test.attr(type='smoke')
def test_update_subnet_gw_dns_host_routes_dhcp(self):
network = self.create_network()
+ self.addCleanup(self._delete_network, network)
subnet = self.create_subnet(
network, **self.subnet_dict(['gateway', 'host_routes',
diff --git a/tempest/auth.py b/tempest/auth.py
index 2550cfb..9687905 100644
--- a/tempest/auth.py
+++ b/tempest/auth.py
@@ -499,7 +499,6 @@
ATTRIBUTES = []
TYPES = {
'identity_admin': ('identity', 'admin'),
- 'compute_admin': ('compute_admin', None),
'user': ('identity', None),
'alt_user': ('identity', 'alt')
}
diff --git a/tempest/clients.py b/tempest/clients.py
index 261b27c..a79275e 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -289,18 +289,3 @@
credentials=auth.get_default_credentials('identity_admin'),
interface=interface,
service=service)
-
-
-class ComputeAdminManager(Manager):
-
- """
- Manager object that uses the compute_admin credentials for its
- managed client objects
- """
-
- def __init__(self, interface='json', service=None):
- base = super(ComputeAdminManager, self)
- base.__init__(
- credentials=auth.get_default_credentials('compute_admin'),
- interface=interface,
- service=service)
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 97aa62b..c7ec359 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -12,11 +12,94 @@
# License for the specific language governing permissions and limitations
# under the License.
-"""Javelin makes resources that should survive an upgrade.
-
-Javelin is a tool for creating, verifying, and deleting a small set of
+"""Javelin is a tool for creating, verifying, and deleting a small set of
resources in a declarative way.
+Javelin is meant to be used as a way to validate quickly that resources can
+survive an upgrade process.
+
+Authentication
+--------------
+
+Javelin will be creating (and removing) users and tenants so it needs the admin
+credentials of your cloud to operate properly. The corresponding info can be
+given the usual way, either through CLI options or environment variables.
+
+You're probably familiar with these, but just in case::
+
+ +----------+------------------+----------------------+
+ | Param | CLI | Environment Variable |
+ +----------+------------------+----------------------+
+ | Username | --os-username | OS_USERNAME |
+ | Password | --os-password | OS_PASSWORD |
+ | Tenant | --os-tenant-name | OS_TENANT_NAME |
+ +----------+------------------+----------------------+
+
+
+Runtime Arguments
+-----------------
+
+**-m/--mode**: (Required) Has to be one of 'check', 'create' or 'destroy'. It
+indicates which actions javelin is going to perform.
+
+**-r/--resources**: (Required) The path to a YAML file describing the resources
+used by Javelin.
+
+**-d/--devstack-base**: (Required) The path to the devstack repo used to
+retrieve artefacts (like images) that will be referenced in the resource files.
+
+**-c/--config-file**: (Optional) The path to a valid Tempest config file
+describing your cloud. Javelin may use this to determine if certain services
+are enabled and modify its behavior accordingly.
+
+
+Resource file
+-------------
+
+The resource file is a valid YAML file describing the resources that will be
+created, checked and destroyed by javelin. Here's a canonical example of a
+resource file::
+
+ tenants:
+ - javelin
+ - discuss
+
+ users:
+ - name: javelin
+ pass: gungnir
+ tenant: javelin
+ - name: javelin2
+ pass: gungnir2
+ tenant: discuss
+
+ # resources that we want to create
+ images:
+ - name: javelin_cirros
+ owner: javelin
+ file: cirros-0.3.2-x86_64-blank.img
+ format: ami
+ aki: cirros-0.3.2-x86_64-vmlinuz
+ ari: cirros-0.3.2-x86_64-initrd
+
+ servers:
+ - name: peltast
+ owner: javelin
+ flavor: m1.small
+ image: javelin_cirros
+ - name: hoplite
+ owner: javelin
+ flavor: m1.medium
+ image: javelin_cirros
+
+
+An important piece of the resource definition is the *owner* field, which is
+the user (that we've created) that is the owner of that resource. All
+operations on that resource will happen as that regular user to ensure that
+admin level access does not mask issues.
+
+The check phase will act like a unit test, using well known assert methods to
+verify that the correct resources exist.
+
"""
import argparse
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index b2c2ffb..0f88461 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -104,13 +104,6 @@
not CONF.identity_feature_enabled.api_v3, update)
-def verify_nova_api_versions(os, update):
- versions = _get_api_versions(os, 'nova')
- if CONF.compute_feature_enabled.api_v3 != ('v3.0' in versions):
- print_and_or_update('api_v3', 'compute_feature_enabled',
- not CONF.compute_feature_enabled.api_v3, update)
-
-
def verify_cinder_api_versions(os, update):
# Check cinder api versions
versions = _get_api_versions(os, 'cinder')
@@ -127,7 +120,6 @@
'cinder': verify_cinder_api_versions,
'glance': verify_glance_api_versions,
'keystone': verify_keystone_api_versions,
- 'nova': verify_nova_api_versions,
}
if service not in verify:
return
@@ -335,7 +327,7 @@
CONF_PARSER = moves.configparser.SafeConfigParser()
CONF_PARSER.optionxform = str
CONF_PARSER.readfp(conf_file)
- os = clients.ComputeAdminManager(interface='json')
+ os = clients.AdminManager(interface='json')
services = check_service_availability(os, update)
results = {}
for service in ['nova', 'cinder', 'neutron', 'swift']:
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 93f02c9..3066667 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -28,11 +28,7 @@
"""Waits for a server to reach a given status."""
def _get_task_state(body):
- if client.service == CONF.compute.catalog_v3_type:
- task_state = body.get("os-extended-status:task_state", None)
- else:
- task_state = body.get('OS-EXT-STS:task_state', None)
- return task_state
+ return body.get('OS-EXT-STS:task_state', None)
# NOTE(afazekas): UNKNOWN status possible on ERROR
# or in a very early stage.
diff --git a/tempest/config.py b/tempest/config.py
index bbfe70b..54a4dd1 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -251,9 +251,6 @@
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the compute service."),
- cfg.StrOpt('catalog_v3_type',
- default='computev3',
- help="Catalog type of the Compute v3 service."),
cfg.StrOpt('path_to_private_key',
help="Path to a private key file for SSH access to remote "
"hosts"),
@@ -280,9 +277,6 @@
title="Enabled Compute Service Features")
ComputeFeaturesGroup = [
- cfg.BoolOpt('api_v3',
- default=False,
- help="If false, skip all nova v3 tests."),
cfg.BoolOpt('disk_config',
default=True,
help="If false, skip disk config tests"),
@@ -292,12 +286,6 @@
'entry all which indicates every extension is enabled. '
'Each extension should be specified with alias name. '
'Empty list indicates all extensions are disabled'),
- cfg.ListOpt('api_v3_extensions',
- default=['all'],
- help='A list of enabled v3 extensions with a special entry all'
- ' which indicates every extension is enabled. '
- 'Each extension should be specified with alias name. '
- 'Empty list indicates all extensions are disabled'),
cfg.BoolOpt('change_password',
default=False,
help="Does the test environment support changing the admin "
@@ -362,23 +350,6 @@
]
-compute_admin_group = cfg.OptGroup(name='compute-admin',
- title="Compute Admin Options")
-
-ComputeAdminGroup = [
- cfg.StrOpt('username',
- help="Administrative Username to use for Nova API requests."),
- cfg.StrOpt('tenant_name',
- help="Administrative Tenant name to use for Nova API "
- "requests."),
- cfg.StrOpt('password',
- help="API key to use when authenticating as admin.",
- secret=True),
- cfg.StrOpt('domain_name',
- help="Domain name for authentication as admin (Keystone V3)."
- "The same domain applies to user and project"),
-]
-
image_group = cfg.OptGroup(name='image',
title="Image Service Options")
@@ -1062,7 +1033,6 @@
(dashboard_group, DashboardGroup),
(data_processing_group, DataProcessingGroup),
(boto_group, BotoGroup),
- (compute_admin_group, ComputeAdminGroup),
(stress_group, StressGroup),
(scenario_group, ScenarioGroup),
(service_available_group, ServiceAvailableGroup),
@@ -1133,7 +1103,6 @@
self.dashboard = cfg.CONF.dashboard
self.data_processing = cfg.CONF.data_processing
self.boto = cfg.CONF.boto
- self.compute_admin = cfg.CONF['compute-admin']
self.stress = cfg.CONF.stress
self.scenario = cfg.CONF.scenario
self.service_available = cfg.CONF.service_available
@@ -1142,17 +1111,11 @@
self.input_scenario = cfg.CONF['input-scenario']
self.cli = cfg.CONF.cli
self.negative = cfg.CONF.negative
- if not self.compute_admin.username:
- self.compute_admin.username = self.identity.admin_username
- self.compute_admin.password = self.identity.admin_password
- self.compute_admin.tenant_name = self.identity.admin_tenant_name
cfg.CONF.set_default('domain_name', self.identity.admin_domain_name,
group='identity')
cfg.CONF.set_default('alt_domain_name',
self.identity.admin_domain_name,
group='identity')
- cfg.CONF.set_default('domain_name', self.identity.admin_domain_name,
- group='compute-admin')
def __init__(self, parse_conf=True, config_path=None):
"""Initialize a configuration from a conf directory and conf file."""
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 20b95e4..9cb24b9 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import logging
import os
import subprocess
@@ -36,13 +35,6 @@
LOG = log.getLogger(__name__)
-# NOTE(afazekas): Workaround for the stdout logging
-LOG_nova_client = logging.getLogger('novaclient.client')
-LOG_nova_client.addHandler(log.NullHandler())
-
-LOG_cinder_client = logging.getLogger('cinderclient.client')
-LOG_cinder_client.addHandler(log.NullHandler())
-
class ScenarioTest(tempest.test.BaseTestCase):
"""Base class for scenario tests. Uses tempest own clients. """
@@ -751,9 +743,9 @@
# The target login is assumed to have been configured for
# key-based authentication by cloud-init.
try:
- for net_name, ip_addresses in server['networks'].iteritems():
+ for net_name, ip_addresses in server['addresses'].iteritems():
for ip_address in ip_addresses:
- self.check_vm_connectivity(ip_address,
+ self.check_vm_connectivity(ip_address['addr'],
username,
private_key,
should_connect=should_connect)
diff --git a/tempest/test.py b/tempest/test.py
index ff829f3..cc8370c 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -194,7 +194,6 @@
"""
config_dict = {
'compute': CONF.compute_feature_enabled.api_extensions,
- 'compute_v3': CONF.compute_feature_enabled.api_v3_extensions,
'volume': CONF.volume_feature_enabled.api_extensions,
'network': CONF.network_feature_enabled.api_extensions,
'object': CONF.object_storage_feature_enabled.discoverable_apis,
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index 3b9a990..65106cc 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -15,7 +15,6 @@
import json
import mock
-from oslo.config import cfg
from tempest.cmd import verify_tempest_config
from tempest import config
@@ -87,7 +86,7 @@
self.assertIn('v3.0', versions)
def test_verify_api_versions(self):
- api_services = ['cinder', 'glance', 'keystone', 'nova']
+ api_services = ['cinder', 'glance', 'keystone']
fake_os = mock.MagicMock()
for svc in api_services:
m = 'verify_%s_api_versions' % svc
@@ -96,7 +95,7 @@
verify_mock.assert_called_once_with(fake_os, True)
def test_verify_api_versions_not_implemented(self):
- api_services = ['cinder', 'glance', 'keystone', 'nova']
+ api_services = ['cinder', 'glance', 'keystone']
fake_os = mock.MagicMock()
for svc in api_services:
m = 'verify_%s_api_versions' % svc
@@ -170,23 +169,6 @@
print_mock.assert_called_once_with('api_v1', 'volume_feature_enabled',
False, True)
- def test_verify_nova_versions(self):
- cfg.CONF.set_default('api_v3', True, 'compute-feature-enabled')
- self.useFixture(mockpatch.PatchObject(
- verify_tempest_config, '_get_unversioned_endpoint',
- return_value='http://fake_endpoint:5000'))
- fake_resp = {'versions': [{'id': 'v2.0'}]}
- fake_resp = json.dumps(fake_resp)
- self.useFixture(mockpatch.PatchObject(
- verify_tempest_config.RAW_HTTP, 'request',
- return_value=(None, fake_resp)))
- fake_os = mock.MagicMock()
- with mock.patch.object(verify_tempest_config,
- 'print_and_or_update') as print_mock:
- verify_tempest_config.verify_nova_api_versions(fake_os, True)
- print_mock.assert_called_once_with('api_v3', 'compute_feature_enabled',
- False, True)
-
def test_verify_glance_version_no_v2_with_v1_1(self):
def fake_get_versions():
return (None, ['v1.1'])
diff --git a/tempest/tests/fake_config.py b/tempest/tests/fake_config.py
index 9e56916..2f8efa1 100644
--- a/tempest/tests/fake_config.py
+++ b/tempest/tests/fake_config.py
@@ -52,9 +52,6 @@
self.conf.set_default(prefix + config_option,
'fake_' + config_option,
group='identity')
- # Compute Admin group items
- self.conf.set_default(config_option, 'fake_' + config_option,
- group='compute-admin')
class FakePrivate(config.TempestConfigPrivate):
diff --git a/tempest/tests/test_credentials.py b/tempest/tests/test_credentials.py
index fc80fe2..aa3df36 100644
--- a/tempest/tests/test_credentials.py
+++ b/tempest/tests/test_credentials.py
@@ -194,9 +194,6 @@
for prefix in ['', 'alt_', 'admin_']:
cfg.CONF.set_default(prefix + 'domain_name', 'fake_domain_name',
group='identity')
- # Compute Admin group items
- cfg.CONF.set_default('domain_name', 'fake_domain_name',
- group='compute-admin')
def test_default(self):
self.useFixture(fixtures.LockFixture('auth_version'))