Merge "port test_simple_tenant_usage into nova v3 part1"
diff --git a/HACKING.rst b/HACKING.rst
index 377c647..a74ff73 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -186,3 +186,9 @@
- Scenario tests
- API tests that have a wide focus
+
+Sample Configuration File
+-------------------------
+The sample config file is autogenerated using a script. If any changes are made
+to the config variables in tempest then the sample config file must be
+regenerated. This can be done running the script: tools/generate_sample.sh
diff --git a/README.rst b/README.rst
index 0996022..96f6e4c 100644
--- a/README.rst
+++ b/README.rst
@@ -79,6 +79,9 @@
document. The etc/tempest.conf.sample attempts to be a self
documenting version of the configuration.
+The sample config file is auto generated using the script:
+tools/generate_sample.sh
+
The most important pieces that are needed are the user ids, openstack
endpoints, and basic flavors and images needed to run tests.
diff --git a/etc/whitelist.yaml b/etc/whitelist.yaml
index aef49dd..24ee5e1 100644
--- a/etc/whitelist.yaml
+++ b/etc/whitelist.yaml
@@ -31,6 +31,12 @@
message: "Getting disk size of instance"
- module: "nova.virt.libvirt.driver"
message: "No such file or directory: '/opt/stack/data/nova/instances"
+ - module: "nova.compute.manager"
+ message: "error during stop\\(\\) in sync_power_state"
+ - module: "nova.compute.manager"
+ message: "Instance failed network setup after 1 attempt"
+ - module: "nova.compute.manager"
+ message: "Periodic sync_power_state task had an error"
g-api:
- module: "glance.store.sheepdog"
@@ -43,11 +49,19 @@
ceilometer-acompute:
- module: "ceilometer.compute.pollsters.disk"
+ message: "Unable to read from monitor: Connection reset by peer"
+ - module: "ceilometer.compute.pollsters.disk"
+ message: "Requested operation is not valid: domain is not running"
+ - module: "ceilometer.compute.pollsters.net"
message: "Requested operation is not valid: domain is not running"
- module: "ceilometer.compute.pollsters.disk"
message: "Domain not found: no domain with matching uuid"
- module: "ceilometer.compute.pollsters.net"
message: "No module named libvirt"
+ - module: "ceilometer.compute.pollsters.net"
+ message: "Unable to write to monitor: Broken pipe"
+ - module: "ceilometer.compute.pollsters.cpu"
+ message: "Domain not found: no domain with matching uuid"
ceilometer-alarm-evaluator:
- module: "ceilometer.alarm.service"
@@ -85,6 +99,8 @@
message: "takes exactly 4 arguments"
- module: "nova.api.openstack"
message: "Caught error: Instance .* could not be found"
+ - module: "nova.api.metadata.handler"
+ message: "Failed to get metadata for instance id:"
n-cond:
- module: "nova.notifications"
@@ -100,6 +116,12 @@
- module: "nova.scheduler.filter_scheduler"
message: "Error from last host: "
+n-net:
+ - module: "nova.openstack.common.rpc.amqp"
+ message: "Exception during message handling"
+ - module: "nova.openstack.common.rpc.common"
+ message: "'NoneType' object has no attribute '__getitem__'"
+
c-api:
- module: "cinder.api.middleware.fault"
message: "Caught error: Volume .* could not be found"
@@ -116,6 +138,8 @@
- module: "cinder.brick.local_dev.lvm"
message: "/dev/dm-1: stat failed: No such file or directory"
- module: "cinder.brick.local_dev.lvm"
+ message: "LV stack-volumes.*in use: not deactivating"
+ - module: "cinder.brick.local_dev.lvm"
message: "Can't remove open logical volume"
q-dhpc:
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index a4a877c..4c823ad 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -234,6 +234,7 @@
cls.services_client = cls.os.services_v3_client
cls.extensions_client = cls.os.extensions_v3_client
cls.availability_zone_client = cls.os.availability_zone_v3_client
+ cls.interfaces_client = cls.os.interfaces_v3_client
@classmethod
def create_image_from_server(cls, server_id, **kwargs):
diff --git a/tempest/api/compute/v3/servers/test_attach_interfaces.py b/tempest/api/compute/v3/servers/test_attach_interfaces.py
index a177cea..f208a4b 100644
--- a/tempest/api/compute/v3/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/v3/servers/test_attach_interfaces.py
@@ -19,15 +19,15 @@
import time
-class AttachInterfacesTestJSON(base.BaseV2ComputeTest):
+class AttachInterfacesV3TestJSON(base.BaseV3ComputeTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
if not cls.config.service_available.neutron:
raise cls.skipException("Neutron is required")
- super(AttachInterfacesTestJSON, cls).setUpClass()
- cls.client = cls.os.interfaces_client
+ super(AttachInterfacesV3TestJSON, cls).setUpClass()
+ cls.client = cls.interfaces_client
def _check_interface(self, iface, port_id=None, network_id=None,
fixed_ip=None):
@@ -114,5 +114,5 @@
self.assertEqual(len(ifs) - 1, len(_ifs))
-class AttachInterfacesTestXML(AttachInterfacesTestJSON):
+class AttachInterfacesV3TestXML(AttachInterfacesV3TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/v3/servers/test_server_addresses.py b/tempest/api/compute/v3/servers/test_server_addresses.py
index 7ca8a52..82588b6 100644
--- a/tempest/api/compute/v3/servers/test_server_addresses.py
+++ b/tempest/api/compute/v3/servers/test_server_addresses.py
@@ -20,12 +20,12 @@
from tempest.test import attr
-class ServerAddressesTest(base.BaseV2ComputeTest):
+class ServerAddressesV3Test(base.BaseV3ComputeTest):
_interface = 'json'
@classmethod
def setUpClass(cls):
- super(ServerAddressesTest, cls).setUpClass()
+ super(ServerAddressesV3Test, cls).setUpClass()
cls.client = cls.servers_client
resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
@@ -80,5 +80,5 @@
self.assertTrue(any([a for a in addr if a == address]))
-class ServerAddressesTestXML(ServerAddressesTest):
+class ServerAddressesV3TestXML(ServerAddressesV3Test):
_interface = 'xml'
diff --git a/tempest/clients.py b/tempest/clients.py
index b2399c7..0f54fc0 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -54,6 +54,8 @@
AvailabilityZoneV3ClientJSON
from tempest.services.compute.v3.json.extensions_client import \
ExtensionsV3ClientJSON
+from tempest.services.compute.v3.json.interfaces_client import \
+ InterfacesV3ClientJSON
from tempest.services.compute.v3.json.servers_client import \
ServersV3ClientJSON
from tempest.services.compute.v3.json.services_client import \
@@ -62,6 +64,8 @@
AvailabilityZoneV3ClientXML
from tempest.services.compute.v3.xml.extensions_client import \
ExtensionsV3ClientXML
+from tempest.services.compute.v3.xml.interfaces_client import \
+ InterfacesV3ClientXML
from tempest.services.compute.v3.xml.servers_client import ServersV3ClientXML
from tempest.services.compute.v3.xml.services_client import \
ServicesV3ClientXML
@@ -210,6 +214,7 @@
self.token_client = TokenClientXML(self.config)
self.security_groups_client = SecurityGroupsClientXML(
*client_args)
+ self.interfaces_v3_client = InterfacesV3ClientXML(*client_args)
self.interfaces_client = InterfacesClientXML(*client_args)
self.endpoints_client = EndPointClientXML(*client_args)
self.fixed_ips_client = FixedIPsClientXML(*client_args)
@@ -256,6 +261,7 @@
self.token_client = TokenClientJSON(self.config)
self.security_groups_client = SecurityGroupsClientJSON(
*client_args)
+ self.interfaces_v3_client = InterfacesV3ClientJSON(*client_args)
self.interfaces_client = InterfacesClientJSON(*client_args)
self.endpoints_client = EndPointClientJSON(*client_args)
self.fixed_ips_client = FixedIPsClientJSON(*client_args)
diff --git a/tempest/common/generate_sample_tempest.py b/tempest/common/generate_sample_tempest.py
index 3811088..545703b 100644
--- a/tempest/common/generate_sample_tempest.py
+++ b/tempest/common/generate_sample_tempest.py
@@ -21,6 +21,15 @@
from tempest import config
from tempest.openstack.common.config import generator
+# NOTE(mtreinish): This hack is needed because of how oslo config is used in
+# tempest. Tempest is run from inside a test runner and so we can't rely on the
+# global CONF object being fully populated when we run a test. (test runners
+# don't init every file for running a test) So to get around that we manually
+# load the config file in tempest for each test class to ensure that every
+# config option is set. However, the tool expects the CONF object to be fully
+# populated when it inits all the files in the project. This just works around
+# the issue by manually loading the config file (which may or may not exist)
+# which will populate all the options before running the generator.
config.TempestConfig()
generator.generate(sys.argv[1:])
diff --git a/tempest/services/compute/v3/json/interfaces_client.py b/tempest/services/compute/v3/json/interfaces_client.py
index 06e6476..7fb0fa9 100644
--- a/tempest/services/compute/v3/json/interfaces_client.py
+++ b/tempest/services/compute/v3/json/interfaces_client.py
@@ -20,21 +20,22 @@
from tempest import exceptions
-class InterfacesClientJSON(RestClient):
+class InterfacesV3ClientJSON(RestClient):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(InterfacesClientJSON, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_type
+ super(InterfacesV3ClientJSON, self).__init__(config, username,
+ password, auth_url,
+ tenant_name)
+ self.service = self.config.compute.catalog_v3_type
def list_interfaces(self, server):
- resp, body = self.get('servers/%s/os-interface' % server)
+ resp, body = self.get('servers/%s/os-attach-interfaces' % server)
body = json.loads(body)
- return resp, body['interfaceAttachments']
+ return resp, body['interface_attachments']
def create_interface(self, server, port_id=None, network_id=None,
fixed_ip=None):
- post_body = dict(interfaceAttachment=dict())
+ post_body = dict(interface_attachment=dict())
if port_id:
post_body['port_id'] = port_id
if network_id:
@@ -42,20 +43,22 @@
if fixed_ip:
post_body['fixed_ips'] = [dict(ip_address=fixed_ip)]
post_body = json.dumps(post_body)
- resp, body = self.post('servers/%s/os-interface' % server,
+ resp, body = self.post('servers/%s/os-attach-interfaces' % server,
headers=self.headers,
body=post_body)
body = json.loads(body)
- return resp, body['interfaceAttachment']
+ return resp, body['interface_attachment']
def show_interface(self, server, port_id):
- resp, body = self.get('servers/%s/os-interface/%s' % (server, port_id))
+ resp, body =\
+ self.get('servers/%s/os-attach-interfaces/%s' % (server, port_id))
body = json.loads(body)
- return resp, body['interfaceAttachment']
+ return resp, body['interface_attachment']
def delete_interface(self, server, port_id):
- resp, body = self.delete('servers/%s/os-interface/%s' % (server,
- port_id))
+ resp, body =\
+ self.delete('servers/%s/os-attach-interfaces/%s' % (server,
+ port_id))
return resp, body
def wait_for_interface_status(self, server, port_id, status):
diff --git a/tempest/services/compute/v3/xml/interfaces_client.py b/tempest/services/compute/v3/xml/interfaces_client.py
index a84e0bd..870c130 100644
--- a/tempest/services/compute/v3/xml/interfaces_client.py
+++ b/tempest/services/compute/v3/xml/interfaces_client.py
@@ -25,12 +25,12 @@
from tempest.services.compute.xml.common import xml_to_json
-class InterfacesClientXML(RestClientXML):
+class InterfacesV3ClientXML(RestClientXML):
def __init__(self, config, username, password, auth_url, tenant_name=None):
- super(InterfacesClientXML, self).__init__(config, username, password,
- auth_url, tenant_name)
- self.service = self.config.compute.catalog_type
+ super(InterfacesV3ClientXML, self).__init__(config, username, password,
+ auth_url, tenant_name)
+ self.service = self.config.compute.catalog_v3_type
def _process_xml_interface(self, node):
iface = xml_to_json(node)
@@ -40,7 +40,8 @@
return iface
def list_interfaces(self, server):
- resp, body = self.get('servers/%s/os-interface' % server, self.headers)
+ resp, body = self.get('servers/%s/os-attach-interfaces' % server,
+ self.headers)
node = etree.fromstring(body)
interfaces = [self._process_xml_interface(x)
for x in node.getchildren()]
@@ -49,7 +50,7 @@
def create_interface(self, server, port_id=None, network_id=None,
fixed_ip=None):
doc = Document()
- iface = Element('interfaceAttachment')
+ iface = Element('interface_attachment')
if port_id:
_port_id = Element('port_id')
_port_id.append(Text(port_id))
@@ -67,21 +68,23 @@
_fixed_ips.append(_fixed_ip)
iface.append(_fixed_ips)
doc.append(iface)
- resp, body = self.post('servers/%s/os-interface' % server,
+ resp, body = self.post('servers/%s/os-attach-interfaces' % server,
headers=self.headers,
body=str(doc))
body = self._process_xml_interface(etree.fromstring(body))
return resp, body
def show_interface(self, server, port_id):
- resp, body = self.get('servers/%s/os-interface/%s' % (server, port_id),
- self.headers)
+ resp, body =\
+ self.get('servers/%s/os-attach-interfaces/%s' % (server, port_id),
+ self.headers)
body = self._process_xml_interface(etree.fromstring(body))
return resp, body
def delete_interface(self, server, port_id):
- resp, body = self.delete('servers/%s/os-interface/%s' % (server,
- port_id))
+ resp, body =\
+ self.delete('servers/%s/os-attach-interfaces/%s' % (server,
+ port_id))
return resp, body
def wait_for_interface_status(self, server, port_id, status):
diff --git a/tools/check_logs.py b/tools/check_logs.py
index 2ad4f70..68ffced 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -26,6 +26,10 @@
import yaml
+is_neutron = os.environ.get('DEVSTACK_GATE_NEUTRON', "0") == "1"
+dump_all_errors = is_neutron
+
+
def process_files(file_specs, url_specs, whitelists):
regexp = re.compile(r"^.*(ERROR|CRITICAL).*\[.*\-.*\]")
had_errors = False
@@ -48,6 +52,7 @@
def scan_content(name, content, regexp, whitelist):
had_errors = False
+ print_log_name = True
for line in content:
if not line.startswith("Stderr:") and regexp.match(line):
whitelisted = False
@@ -57,10 +62,12 @@
if re.match(pat, line):
whitelisted = True
break
- if not whitelisted:
- if not had_errors:
+ if not whitelisted or dump_all_errors:
+ if not print_log_name:
print("Log File: %s" % name)
- had_errors = True
+ print_log_name = False
+ if not whitelisted:
+ had_errors = True
print(line)
return had_errors
@@ -115,6 +122,9 @@
whitelists = loaded
if process_files(files_to_process, urls_to_process, whitelists):
print("Logs have errors")
+ if is_neutron:
+ print("Currently not failing neutron builds with errors")
+ return 0
# Return non-zero to start failing builds
return 0
else:
diff --git a/tools/config/check_uptodate.sh b/tools/config/check_uptodate.sh
index 9882ab6..45c8629 100755
--- a/tools/config/check_uptodate.sh
+++ b/tools/config/check_uptodate.sh
@@ -5,6 +5,6 @@
if ! diff $TEMPDIR/$CFGFILE etc/$CFGFILE
then
echo "E: tempest.conf.sample is not up to date, please run:"
- echo "MODULEPATH=tempest.common.generate_sample_tempest tools/config/generate_sample.sh"
+ echo "tools/generate_sample.sh"
exit 42
fi
diff --git a/tools/generate_sample.sh b/tools/generate_sample.sh
new file mode 100755
index 0000000..9b312c9
--- /dev/null
+++ b/tools/generate_sample.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+MODULEPATH=tempest.common.generate_sample_tempest tools/config/generate_sample.sh $@