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 $@