From 2fcbbf3031fe1d326ddb2b9bb1b06e0e39422022 Mon Sep 17 00:00:00 2001 From: John Schwarz Date: Thu, 7 May 2015 09:02:59 +0300 Subject: [PATCH] Move full-stack logs post-tests Currently, it's up to the developer who wants to run full-stack on his machine to make the directory in question (/opt/stack/logs). However, this also means that the files don't get compressed at the end of a gate run. Now, each full-stack test will have each own log directory in /tmp. Once the logs are there, post_test_hook.sh can run 'gzip' on all the log files before moving them to /opt/stack/logs on its own. Change-Id: I5c04d0af0b9858722ae0c4baf0ee478ffb078e02 --- TESTING.rst | 5 +- neutron/tests/contrib/post_test_hook.sh | 9 ++++ neutron/tests/fullstack/base.py | 5 ++ neutron/tests/fullstack/fullstack_fixtures.py | 46 ++++++++++++++----- neutron/tests/fullstack/test_l3_agent.py | 3 +- 5 files changed, 54 insertions(+), 14 deletions(-) diff --git a/TESTING.rst b/TESTING.rst index 27289b191d1..c05018e558d 100644 --- a/TESTING.rst +++ b/TESTING.rst @@ -245,7 +245,10 @@ advise to run ./stack.sh successfully to make sure all Neutron's dependencies are met. Also note that in order to preserve resources on the gate, running the dsvm-functional suite will also run all full-stack tests (and a new worker won't be assigned specifically for -dsvm-fullstack). +dsvm-fullstack). Full-stack based Neutron daemons produce logs to a +sub-folder in /tmp/fullstack-logs (for example, a test named +"test_example" will produce logs to /tmp/fullstack-logs/test_example/), +so that will be a good place to look if your test is failing. API Tests ========= diff --git a/neutron/tests/contrib/post_test_hook.sh b/neutron/tests/contrib/post_test_hook.sh index 2c8360a47a7..62d47ce01a8 100644 --- a/neutron/tests/contrib/post_test_hook.sh +++ b/neutron/tests/contrib/post_test_hook.sh @@ -19,6 +19,15 @@ function generate_testr_results { gzip -9 ./testr_results.html sudo mv ./*.gz /opt/stack/logs/ fi + + # Compress all /tmp/fullstack-*/*.txt files and move the directories + # holding those files to /opt/stack/logs. Files with .log suffix have their + # suffix changed to .txt (so browsers will know to open the compressed + # files and not download them). + if [ -d /tmp/fullstack-logs/ ]; then + sudo find /tmp/fullstack-logs -iname "*.log" -type f -exec mv {} {}.txt \; -exec gzip -9 {}.txt \; + sudo mv /tmp/fullstack-logs/* /opt/stack/logs/ + fi } if [ "$venv" == "dsvm-functional" ] diff --git a/neutron/tests/fullstack/base.py b/neutron/tests/fullstack/base.py index b783612360d..61b50d3a185 100644 --- a/neutron/tests/fullstack/base.py +++ b/neutron/tests/fullstack/base.py @@ -33,10 +33,15 @@ class BaseFullStackTestCase(test_base.MySQLOpportunisticTestCase): self.create_db_tables() if self.environment: + self.environment.test_name = self.get_name() self.useFixture(self.environment) self.client = self.environment.neutron_server.client + def get_name(self): + class_name, test_name = self.id().split(".")[-2:] + return "%s.%s" % (class_name, test_name) + def create_db_tables(self): """Populate the new database. diff --git a/neutron/tests/fullstack/fullstack_fixtures.py b/neutron/tests/fullstack/fullstack_fixtures.py index c06d450cb3d..f714273aeea 100644 --- a/neutron/tests/fullstack/fullstack_fixtures.py +++ b/neutron/tests/fullstack/fullstack_fixtures.py @@ -13,6 +13,7 @@ # under the License. from distutils import spawn +import errno import functools import os @@ -32,12 +33,13 @@ from neutron.tests.fullstack import config_fixtures LOG = logging.getLogger(__name__) # This should correspond the directory from which infra retrieves log files -DEFAULT_LOG_DIR = '/opt/stack/logs' +DEFAULT_LOG_DIR = '/tmp/fullstack-logs/' class ProcessFixture(fixtures.Fixture): - def __init__(self, name, exec_name, config_filenames): - self.name = name + def __init__(self, test_name, process_name, exec_name, config_filenames): + self.test_name = test_name + self.process_name = process_name self.exec_name = exec_name self.config_filenames = config_filenames self.process = None @@ -47,9 +49,19 @@ class ProcessFixture(fixtures.Fixture): self.start() def start(self): - fmt = self.name + "--%Y-%m-%d--%H%M%S.log" + fmt = self.process_name + "--%Y-%m-%d--%H%M%S.log" + log_dir = os.path.join(DEFAULT_LOG_DIR, self.test_name) + if not os.path.exists(log_dir): + try: + os.makedirs(log_dir) + except OSError as e: + # Make sure that the error was that the directory was created + # by a different (concurrent) worker. If not, raise the error. + if e.errno != errno.EEXIST: + raise + cmd = [spawn.find_executable(self.exec_name), - '--log-dir', DEFAULT_LOG_DIR, + '--log-dir', log_dir, '--log-file', timeutils.strtime(fmt=fmt)] for filename in self.config_filenames: cmd += ['--config-file', filename] @@ -88,6 +100,8 @@ class RabbitmqEnvironmentFixture(fixtures.Fixture): class FullstackFixture(fixtures.Fixture): + def __init__(self): + self.test_name = None def setUp(self): super(FullstackFixture, self).setUp() @@ -96,7 +110,8 @@ class FullstackFixture(fixtures.Fixture): rabbitmq_environment = self.useFixture(RabbitmqEnvironmentFixture()) self.neutron_server = self.useFixture( - NeutronServerFixture(self.temp_dir, rabbitmq_environment)) + NeutronServerFixture( + self.test_name, self.temp_dir, rabbitmq_environment)) def wait_until_env_is_up(self, agents_count=0): utils.wait_until_true( @@ -116,7 +131,8 @@ class NeutronServerFixture(fixtures.Fixture): NEUTRON_SERVER = "neutron-server" - def __init__(self, temp_dir, rabbitmq_environment): + def __init__(self, test_name, temp_dir, rabbitmq_environment): + self.test_name = test_name self.temp_dir = temp_dir self.rabbitmq_environment = rabbitmq_environment @@ -139,7 +155,8 @@ class NeutronServerFixture(fixtures.Fixture): self.plugin_cfg_fixture.filename] self.process_fixture = self.useFixture(ProcessFixture( - name=self.NEUTRON_SERVER, + test_name=self.test_name, + process_name=self.NEUTRON_SERVER, exec_name=self.NEUTRON_SERVER, config_filenames=config_filenames)) @@ -163,7 +180,8 @@ class OVSAgentFixture(fixtures.Fixture): NEUTRON_OVS_AGENT = "neutron-openvswitch-agent" - def __init__(self, neutron_cfg_fixture, ml2_cfg_fixture): + def __init__(self, test_name, neutron_cfg_fixture, ml2_cfg_fixture): + self.test_name = test_name self.neutron_cfg_fixture = neutron_cfg_fixture self.plugin_cfg_fixture = ml2_cfg_fixture @@ -180,7 +198,8 @@ class OVSAgentFixture(fixtures.Fixture): self.plugin_cfg_fixture.filename] self.process_fixture = self.useFixture(ProcessFixture( - name=self.NEUTRON_OVS_AGENT, + test_name=self.test_name, + process_name=self.NEUTRON_OVS_AGENT, exec_name=self.NEUTRON_OVS_AGENT, config_filenames=config_filenames)) @@ -195,7 +214,9 @@ class L3AgentFixture(fixtures.Fixture): NEUTRON_L3_AGENT = "neutron-l3-agent" - def __init__(self, temp_dir, neutron_cfg_fixture, integration_bridge_name): + def __init__(self, test_name, temp_dir, + neutron_cfg_fixture, integration_bridge_name): + self.test_name = test_name self.temp_dir = temp_dir self.neutron_cfg_fixture = neutron_cfg_fixture self.neutron_config = self.neutron_cfg_fixture.config @@ -215,7 +236,8 @@ class L3AgentFixture(fixtures.Fixture): self.plugin_cfg_fixture.filename] self.process_fixture = self.useFixture(ProcessFixture( - name=self.NEUTRON_L3_AGENT, + test_name=self.test_name, + process_name=self.NEUTRON_L3_AGENT, exec_name=spawn.find_executable( 'l3_agent.py', path=os.path.join(base.ROOTDIR, 'common', 'agents')), diff --git a/neutron/tests/fullstack/test_l3_agent.py b/neutron/tests/fullstack/test_l3_agent.py index 9b5e2476552..4bf86308bb9 100644 --- a/neutron/tests/fullstack/test_l3_agent.py +++ b/neutron/tests/fullstack/test_l3_agent.py @@ -30,10 +30,11 @@ class SingleNodeEnvironment(f_fixtures.FullstackFixture): self.ovs_agent = self.useFixture( f_fixtures.OVSAgentFixture( - neutron_config, ml2_config)) + self.test_name, neutron_config, ml2_config)) self.l3_agent = self.useFixture( f_fixtures.L3AgentFixture( + self.test_name, self.temp_dir, neutron_config, self.ovs_agent._get_br_int_name()))