teuthology 1.1.0__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scripts/describe.py +1 -0
- scripts/dispatcher.py +55 -26
- scripts/exporter.py +18 -0
- scripts/lock.py +1 -1
- scripts/node_cleanup.py +58 -0
- scripts/openstack.py +9 -9
- scripts/results.py +12 -11
- scripts/schedule.py +4 -0
- scripts/suite.py +57 -16
- scripts/supervisor.py +44 -0
- scripts/update_inventory.py +10 -4
- teuthology/__init__.py +24 -26
- teuthology/beanstalk.py +4 -3
- teuthology/config.py +16 -6
- teuthology/contextutil.py +18 -14
- teuthology/describe_tests.py +25 -18
- teuthology/dispatcher/__init__.py +210 -35
- teuthology/dispatcher/supervisor.py +140 -58
- teuthology/exceptions.py +43 -0
- teuthology/exporter.py +347 -0
- teuthology/kill.py +76 -81
- teuthology/lock/cli.py +3 -3
- teuthology/lock/ops.py +135 -61
- teuthology/lock/query.py +61 -44
- teuthology/ls.py +1 -1
- teuthology/misc.py +61 -75
- teuthology/nuke/__init__.py +12 -353
- teuthology/openstack/__init__.py +4 -3
- teuthology/openstack/openstack-centos-7.0-user-data.txt +1 -1
- teuthology/openstack/openstack-centos-7.1-user-data.txt +1 -1
- teuthology/openstack/openstack-centos-7.2-user-data.txt +1 -1
- teuthology/openstack/openstack-debian-8.0-user-data.txt +1 -1
- teuthology/openstack/openstack-opensuse-42.1-user-data.txt +1 -1
- teuthology/openstack/openstack-teuthology.cron +0 -1
- teuthology/orchestra/cluster.py +49 -7
- teuthology/orchestra/connection.py +16 -5
- teuthology/orchestra/console.py +111 -50
- teuthology/orchestra/daemon/cephadmunit.py +17 -4
- teuthology/orchestra/daemon/state.py +8 -1
- teuthology/orchestra/daemon/systemd.py +4 -4
- teuthology/orchestra/opsys.py +30 -11
- teuthology/orchestra/remote.py +405 -338
- teuthology/orchestra/run.py +3 -3
- teuthology/packaging.py +19 -16
- teuthology/provision/__init__.py +30 -10
- teuthology/provision/cloud/openstack.py +12 -6
- teuthology/provision/cloud/util.py +1 -2
- teuthology/provision/downburst.py +4 -3
- teuthology/provision/fog.py +68 -20
- teuthology/provision/openstack.py +5 -4
- teuthology/provision/pelagos.py +1 -1
- teuthology/repo_utils.py +43 -13
- teuthology/report.py +57 -35
- teuthology/results.py +5 -3
- teuthology/run.py +13 -14
- teuthology/run_tasks.py +27 -43
- teuthology/schedule.py +4 -3
- teuthology/scrape.py +28 -22
- teuthology/suite/__init__.py +74 -45
- teuthology/suite/build_matrix.py +34 -24
- teuthology/suite/fragment-merge.lua +105 -0
- teuthology/suite/matrix.py +31 -2
- teuthology/suite/merge.py +175 -0
- teuthology/suite/placeholder.py +6 -9
- teuthology/suite/run.py +175 -100
- teuthology/suite/util.py +64 -218
- teuthology/task/__init__.py +1 -1
- teuthology/task/ansible.py +101 -32
- teuthology/task/buildpackages.py +2 -2
- teuthology/task/ceph_ansible.py +13 -6
- teuthology/task/cephmetrics.py +2 -1
- teuthology/task/clock.py +33 -14
- teuthology/task/exec.py +18 -0
- teuthology/task/hadoop.py +2 -2
- teuthology/task/install/__init__.py +29 -7
- teuthology/task/install/bin/adjust-ulimits +16 -0
- teuthology/task/install/bin/daemon-helper +114 -0
- teuthology/task/install/bin/stdin-killer +263 -0
- teuthology/task/install/deb.py +1 -1
- teuthology/task/install/rpm.py +17 -5
- teuthology/task/install/util.py +3 -3
- teuthology/task/internal/__init__.py +41 -10
- teuthology/task/internal/edit_sudoers.sh +10 -0
- teuthology/task/internal/lock_machines.py +2 -9
- teuthology/task/internal/redhat.py +31 -1
- teuthology/task/internal/syslog.py +31 -8
- teuthology/task/kernel.py +152 -145
- teuthology/task/lockfile.py +1 -1
- teuthology/task/mpi.py +10 -10
- teuthology/task/pcp.py +1 -1
- teuthology/task/selinux.py +16 -8
- teuthology/task/ssh_keys.py +4 -4
- teuthology/task/tests/__init__.py +137 -77
- teuthology/task/tests/test_fetch_coredumps.py +116 -0
- teuthology/task/tests/test_run.py +4 -4
- teuthology/timer.py +3 -3
- teuthology/util/loggerfile.py +19 -0
- teuthology/util/scanner.py +159 -0
- teuthology/util/sentry.py +52 -0
- teuthology/util/time.py +52 -0
- teuthology-1.2.0.data/scripts/adjust-ulimits +16 -0
- teuthology-1.2.0.data/scripts/daemon-helper +114 -0
- teuthology-1.2.0.data/scripts/stdin-killer +263 -0
- teuthology-1.2.0.dist-info/METADATA +89 -0
- teuthology-1.2.0.dist-info/RECORD +174 -0
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/WHEEL +1 -1
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/entry_points.txt +3 -2
- scripts/nuke.py +0 -47
- scripts/worker.py +0 -37
- teuthology/nuke/actions.py +0 -456
- teuthology/openstack/test/__init__.py +0 -0
- teuthology/openstack/test/openstack-integration.py +0 -286
- teuthology/openstack/test/test_config.py +0 -35
- teuthology/openstack/test/test_openstack.py +0 -1695
- teuthology/orchestra/test/__init__.py +0 -0
- teuthology/orchestra/test/integration/__init__.py +0 -0
- teuthology/orchestra/test/integration/test_integration.py +0 -94
- teuthology/orchestra/test/test_cluster.py +0 -240
- teuthology/orchestra/test/test_connection.py +0 -106
- teuthology/orchestra/test/test_console.py +0 -217
- teuthology/orchestra/test/test_opsys.py +0 -404
- teuthology/orchestra/test/test_remote.py +0 -185
- teuthology/orchestra/test/test_run.py +0 -286
- teuthology/orchestra/test/test_systemd.py +0 -54
- teuthology/orchestra/test/util.py +0 -12
- teuthology/test/__init__.py +0 -0
- teuthology/test/fake_archive.py +0 -107
- teuthology/test/fake_fs.py +0 -92
- teuthology/test/integration/__init__.py +0 -0
- teuthology/test/integration/test_suite.py +0 -86
- teuthology/test/task/__init__.py +0 -205
- teuthology/test/task/test_ansible.py +0 -624
- teuthology/test/task/test_ceph_ansible.py +0 -176
- teuthology/test/task/test_console_log.py +0 -88
- teuthology/test/task/test_install.py +0 -337
- teuthology/test/task/test_internal.py +0 -57
- teuthology/test/task/test_kernel.py +0 -243
- teuthology/test/task/test_pcp.py +0 -379
- teuthology/test/task/test_selinux.py +0 -35
- teuthology/test/test_config.py +0 -189
- teuthology/test/test_contextutil.py +0 -68
- teuthology/test/test_describe_tests.py +0 -316
- teuthology/test/test_email_sleep_before_teardown.py +0 -81
- teuthology/test/test_exit.py +0 -97
- teuthology/test/test_get_distro.py +0 -47
- teuthology/test/test_get_distro_version.py +0 -47
- teuthology/test/test_get_multi_machine_types.py +0 -27
- teuthology/test/test_job_status.py +0 -60
- teuthology/test/test_ls.py +0 -48
- teuthology/test/test_misc.py +0 -391
- teuthology/test/test_nuke.py +0 -290
- teuthology/test/test_packaging.py +0 -763
- teuthology/test/test_parallel.py +0 -28
- teuthology/test/test_repo_utils.py +0 -225
- teuthology/test/test_report.py +0 -77
- teuthology/test/test_results.py +0 -155
- teuthology/test/test_run.py +0 -239
- teuthology/test/test_safepath.py +0 -55
- teuthology/test/test_schedule.py +0 -45
- teuthology/test/test_scrape.py +0 -167
- teuthology/test/test_timer.py +0 -80
- teuthology/test/test_vps_os_vers_parameter_checking.py +0 -84
- teuthology/test/test_worker.py +0 -303
- teuthology/worker.py +0 -354
- teuthology-1.1.0.dist-info/METADATA +0 -76
- teuthology-1.1.0.dist-info/RECORD +0 -213
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/LICENSE +0 -0
- {teuthology-1.1.0.dist-info → teuthology-1.2.0.dist-info}/top_level.txt +0 -0
teuthology/test/test_config.py
DELETED
@@ -1,189 +0,0 @@
|
|
1
|
-
import pytest
|
2
|
-
|
3
|
-
from teuthology import config
|
4
|
-
|
5
|
-
|
6
|
-
class TestYamlConfig(object):
|
7
|
-
def setup(self):
|
8
|
-
self.test_class = config.YamlConfig
|
9
|
-
|
10
|
-
def test_set_multiple(self):
|
11
|
-
conf_obj = self.test_class()
|
12
|
-
conf_obj.foo = 'foo'
|
13
|
-
conf_obj.bar = 'bar'
|
14
|
-
assert conf_obj.foo == 'foo'
|
15
|
-
assert conf_obj.bar == 'bar'
|
16
|
-
assert conf_obj.to_dict()['foo'] == 'foo'
|
17
|
-
|
18
|
-
def test_from_dict(self):
|
19
|
-
in_dict = dict(foo='bar')
|
20
|
-
conf_obj = self.test_class.from_dict(in_dict)
|
21
|
-
assert conf_obj.foo == 'bar'
|
22
|
-
|
23
|
-
def test_contains(self):
|
24
|
-
in_dict = dict(foo='bar')
|
25
|
-
conf_obj = self.test_class.from_dict(in_dict)
|
26
|
-
conf_obj.bar = "foo"
|
27
|
-
assert "bar" in conf_obj
|
28
|
-
assert "foo" in conf_obj
|
29
|
-
assert "baz" not in conf_obj
|
30
|
-
|
31
|
-
def test_to_dict(self):
|
32
|
-
in_dict = dict(foo='bar')
|
33
|
-
conf_obj = self.test_class.from_dict(in_dict)
|
34
|
-
assert conf_obj.to_dict() == in_dict
|
35
|
-
|
36
|
-
def test_from_str(self):
|
37
|
-
in_str = "foo: bar"
|
38
|
-
conf_obj = self.test_class.from_str(in_str)
|
39
|
-
assert conf_obj.foo == 'bar'
|
40
|
-
|
41
|
-
def test_to_str(self):
|
42
|
-
in_str = "foo: bar"
|
43
|
-
conf_obj = self.test_class.from_str(in_str)
|
44
|
-
assert conf_obj.to_str() == in_str
|
45
|
-
|
46
|
-
def test_update(self):
|
47
|
-
conf_obj = self.test_class(dict())
|
48
|
-
conf_obj.foo = 'foo'
|
49
|
-
conf_obj.bar = 'bar'
|
50
|
-
conf_obj.update(dict(bar='baz'))
|
51
|
-
assert conf_obj.foo == 'foo'
|
52
|
-
assert conf_obj.bar == 'baz'
|
53
|
-
|
54
|
-
def test_delattr(self):
|
55
|
-
conf_obj = self.test_class()
|
56
|
-
conf_obj.foo = 'bar'
|
57
|
-
assert conf_obj.foo == 'bar'
|
58
|
-
del conf_obj.foo
|
59
|
-
assert conf_obj.foo is None
|
60
|
-
|
61
|
-
def test_assignment(self):
|
62
|
-
conf_obj = self.test_class()
|
63
|
-
conf_obj["foo"] = "bar"
|
64
|
-
assert conf_obj["foo"] == "bar"
|
65
|
-
assert conf_obj.foo == "bar"
|
66
|
-
|
67
|
-
def test_used_with_update(self):
|
68
|
-
d = dict()
|
69
|
-
conf_obj = self.test_class.from_dict({"foo": "bar"})
|
70
|
-
d.update(conf_obj)
|
71
|
-
assert d["foo"] == "bar"
|
72
|
-
|
73
|
-
def test_get(self):
|
74
|
-
conf_obj = self.test_class()
|
75
|
-
assert conf_obj.get('foo') is None
|
76
|
-
assert conf_obj.get('foo', 'bar') == 'bar'
|
77
|
-
conf_obj.foo = 'baz'
|
78
|
-
assert conf_obj.get('foo') == 'baz'
|
79
|
-
|
80
|
-
|
81
|
-
class TestTeuthologyConfig(TestYamlConfig):
|
82
|
-
def setup(self):
|
83
|
-
self.test_class = config.TeuthologyConfig
|
84
|
-
|
85
|
-
def test_get_ceph_git_base_default(self):
|
86
|
-
conf_obj = self.test_class()
|
87
|
-
conf_obj.yaml_path = ''
|
88
|
-
conf_obj.load()
|
89
|
-
assert conf_obj.ceph_git_base_url == "https://github.com/ceph/"
|
90
|
-
|
91
|
-
def test_set_ceph_git_base_via_private(self):
|
92
|
-
conf_obj = self.test_class()
|
93
|
-
conf_obj._conf['ceph_git_base_url'] = \
|
94
|
-
"git://git.ceph.com/"
|
95
|
-
assert conf_obj.ceph_git_base_url == "git://git.ceph.com/"
|
96
|
-
|
97
|
-
def test_get_reserve_machines_default(self):
|
98
|
-
conf_obj = self.test_class()
|
99
|
-
conf_obj.yaml_path = ''
|
100
|
-
conf_obj.load()
|
101
|
-
assert conf_obj.reserve_machines == 5
|
102
|
-
|
103
|
-
def test_set_reserve_machines_via_private(self):
|
104
|
-
conf_obj = self.test_class()
|
105
|
-
conf_obj._conf['reserve_machines'] = 2
|
106
|
-
assert conf_obj.reserve_machines == 2
|
107
|
-
|
108
|
-
def test_set_nonstandard(self):
|
109
|
-
conf_obj = self.test_class()
|
110
|
-
conf_obj.something = 'something else'
|
111
|
-
assert conf_obj.something == 'something else'
|
112
|
-
|
113
|
-
|
114
|
-
class TestJobConfig(TestYamlConfig):
|
115
|
-
def setup(self):
|
116
|
-
self.test_class = config.JobConfig
|
117
|
-
|
118
|
-
|
119
|
-
class TestFakeNamespace(TestYamlConfig):
|
120
|
-
def setup(self):
|
121
|
-
self.test_class = config.FakeNamespace
|
122
|
-
|
123
|
-
def test_docopt_dict(self):
|
124
|
-
"""
|
125
|
-
Tests if a dict in the format that docopt returns can
|
126
|
-
be parsed correctly.
|
127
|
-
"""
|
128
|
-
d = {
|
129
|
-
"--verbose": True,
|
130
|
-
"--an-option": "some_option",
|
131
|
-
"<an_arg>": "the_arg",
|
132
|
-
"something": "some_thing",
|
133
|
-
}
|
134
|
-
conf_obj = self.test_class(d)
|
135
|
-
assert conf_obj.verbose
|
136
|
-
assert conf_obj.an_option == "some_option"
|
137
|
-
assert conf_obj.an_arg == "the_arg"
|
138
|
-
assert conf_obj.something == "some_thing"
|
139
|
-
|
140
|
-
def test_config(self):
|
141
|
-
"""
|
142
|
-
Tests that a teuthology_config property is automatically added
|
143
|
-
to the conf_obj
|
144
|
-
"""
|
145
|
-
conf_obj = self.test_class(dict(foo="bar"))
|
146
|
-
assert conf_obj["foo"] == "bar"
|
147
|
-
assert conf_obj.foo == "bar"
|
148
|
-
assert conf_obj.teuthology_config.get("fake key") is None
|
149
|
-
|
150
|
-
def test_getattr(self):
|
151
|
-
conf_obj = self.test_class.from_dict({"foo": "bar"})
|
152
|
-
result = getattr(conf_obj, "not_there", "default")
|
153
|
-
assert result == "default"
|
154
|
-
result = getattr(conf_obj, "foo")
|
155
|
-
assert result == "bar"
|
156
|
-
|
157
|
-
def test_none(self):
|
158
|
-
conf_obj = self.test_class.from_dict(dict(null=None))
|
159
|
-
assert conf_obj.null is None
|
160
|
-
|
161
|
-
def test_delattr(self):
|
162
|
-
conf_obj = self.test_class()
|
163
|
-
conf_obj.foo = 'bar'
|
164
|
-
assert conf_obj.foo == 'bar'
|
165
|
-
del conf_obj.foo
|
166
|
-
with pytest.raises(AttributeError):
|
167
|
-
conf_obj.foo
|
168
|
-
|
169
|
-
def test_to_str(self):
|
170
|
-
in_str = "foo: bar"
|
171
|
-
conf_obj = self.test_class.from_str(in_str)
|
172
|
-
assert conf_obj.to_str() == "{'foo': 'bar'}"
|
173
|
-
|
174
|
-
def test_multiple_access(self):
|
175
|
-
"""
|
176
|
-
Test that config.config and FakeNamespace.teuthology_config reflect
|
177
|
-
each others' modifications
|
178
|
-
"""
|
179
|
-
in_str = "foo: bar"
|
180
|
-
conf_obj = self.test_class.from_str(in_str)
|
181
|
-
assert config.config.get('test_key_1') is None
|
182
|
-
assert conf_obj.teuthology_config.get('test_key_1') is None
|
183
|
-
config.config.test_key_1 = 'test value'
|
184
|
-
assert conf_obj.teuthology_config['test_key_1'] == 'test value'
|
185
|
-
|
186
|
-
assert config.config.get('test_key_2') is None
|
187
|
-
assert conf_obj.teuthology_config.get('test_key_2') is None
|
188
|
-
conf_obj.teuthology_config['test_key_2'] = 'test value'
|
189
|
-
assert config.config['test_key_2'] == 'test value'
|
@@ -1,68 +0,0 @@
|
|
1
|
-
from pytest import raises
|
2
|
-
from teuthology import contextutil
|
3
|
-
from logging import ERROR
|
4
|
-
|
5
|
-
|
6
|
-
class TestSafeWhile(object):
|
7
|
-
|
8
|
-
def setup(self):
|
9
|
-
contextutil.log.setLevel(ERROR)
|
10
|
-
self.fake_sleep = lambda s: True
|
11
|
-
self.s_while = contextutil.safe_while
|
12
|
-
|
13
|
-
def test_6_5_10_deal(self):
|
14
|
-
with raises(contextutil.MaxWhileTries):
|
15
|
-
with self.s_while(_sleeper=self.fake_sleep) as proceed:
|
16
|
-
while proceed():
|
17
|
-
pass
|
18
|
-
|
19
|
-
def test_6_0_1_deal(self):
|
20
|
-
with raises(contextutil.MaxWhileTries) as error:
|
21
|
-
with self.s_while(
|
22
|
-
tries=1,
|
23
|
-
_sleeper=self.fake_sleep
|
24
|
-
) as proceed:
|
25
|
-
while proceed():
|
26
|
-
pass
|
27
|
-
|
28
|
-
assert 'waiting for 6 seconds' in str(error)
|
29
|
-
|
30
|
-
def test_1_0_10_deal(self):
|
31
|
-
with raises(contextutil.MaxWhileTries) as error:
|
32
|
-
with self.s_while(
|
33
|
-
sleep=1,
|
34
|
-
_sleeper=self.fake_sleep
|
35
|
-
) as proceed:
|
36
|
-
while proceed():
|
37
|
-
pass
|
38
|
-
|
39
|
-
assert 'waiting for 10 seconds' in str(error)
|
40
|
-
|
41
|
-
def test_6_1_10_deal(self):
|
42
|
-
with raises(contextutil.MaxWhileTries) as error:
|
43
|
-
with self.s_while(
|
44
|
-
increment=1,
|
45
|
-
_sleeper=self.fake_sleep
|
46
|
-
) as proceed:
|
47
|
-
while proceed():
|
48
|
-
pass
|
49
|
-
|
50
|
-
assert 'waiting for 105 seconds' in str(error)
|
51
|
-
|
52
|
-
def test_action(self):
|
53
|
-
with raises(contextutil.MaxWhileTries) as error:
|
54
|
-
with self.s_while(
|
55
|
-
action='doing the thing',
|
56
|
-
_sleeper=self.fake_sleep
|
57
|
-
) as proceed:
|
58
|
-
while proceed():
|
59
|
-
pass
|
60
|
-
|
61
|
-
assert "'doing the thing' reached maximum tries" in str(error)
|
62
|
-
|
63
|
-
def test_no_raise(self):
|
64
|
-
with self.s_while(_raise=False, _sleeper=self.fake_sleep) as proceed:
|
65
|
-
while proceed():
|
66
|
-
pass
|
67
|
-
|
68
|
-
assert True
|
@@ -1,316 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
import pytest
|
3
|
-
|
4
|
-
from teuthology.test.fake_fs import make_fake_fstools
|
5
|
-
from teuthology.describe_tests import (tree_with_info, extract_info,
|
6
|
-
get_combinations)
|
7
|
-
from teuthology.exceptions import ParseError
|
8
|
-
from mock import MagicMock, patch
|
9
|
-
|
10
|
-
realistic_fs = {
|
11
|
-
'basic': {
|
12
|
-
'%': None,
|
13
|
-
'base': {
|
14
|
-
'install.yaml':
|
15
|
-
"""meta:
|
16
|
-
- desc: install ceph
|
17
|
-
install:
|
18
|
-
"""
|
19
|
-
},
|
20
|
-
'clusters': {
|
21
|
-
'fixed-1.yaml':
|
22
|
-
"""meta:
|
23
|
-
- desc: single node cluster
|
24
|
-
roles:
|
25
|
-
- [osd.0, osd.1, osd.2, mon.a, mon.b, mon.c, client.0]
|
26
|
-
""",
|
27
|
-
'fixed-2.yaml':
|
28
|
-
"""meta:
|
29
|
-
- desc: couple node cluster
|
30
|
-
roles:
|
31
|
-
- [osd.0, osd.1, osd.2, mon.a, mon.b, mon.c]
|
32
|
-
- [client.0]
|
33
|
-
""",
|
34
|
-
'fixed-3.yaml':
|
35
|
-
"""meta:
|
36
|
-
- desc: triple node cluster
|
37
|
-
roles:
|
38
|
-
- [osd.0, osd.1, osd.2, mon.a, mon.b, mon.c]
|
39
|
-
- [client.0]
|
40
|
-
- [client.1]
|
41
|
-
"""
|
42
|
-
},
|
43
|
-
'workloads': {
|
44
|
-
'rbd_api_tests_old_format.yaml':
|
45
|
-
"""meta:
|
46
|
-
- desc: c/c++ librbd api tests with format 1 images
|
47
|
-
rbd_features: none
|
48
|
-
overrides:
|
49
|
-
ceph:
|
50
|
-
conf:
|
51
|
-
client:
|
52
|
-
rbd default format: 1
|
53
|
-
tasks:
|
54
|
-
- workunit:
|
55
|
-
env:
|
56
|
-
RBD_FEATURES: 0
|
57
|
-
clients:
|
58
|
-
client.0:
|
59
|
-
- rbd/test_librbd.sh
|
60
|
-
""",
|
61
|
-
'rbd_api_tests.yaml':
|
62
|
-
"""meta:
|
63
|
-
- desc: c/c++ librbd api tests with default settings
|
64
|
-
rbd_features: default
|
65
|
-
tasks:
|
66
|
-
- workunit:
|
67
|
-
clients:
|
68
|
-
client.0:
|
69
|
-
- rbd/test_librbd.sh
|
70
|
-
""",
|
71
|
-
},
|
72
|
-
},
|
73
|
-
}
|
74
|
-
|
75
|
-
|
76
|
-
expected_tree = """├── %
|
77
|
-
├── base
|
78
|
-
│ └── install.yaml
|
79
|
-
├── clusters
|
80
|
-
│ ├── fixed-1.yaml
|
81
|
-
│ ├── fixed-2.yaml
|
82
|
-
│ └── fixed-3.yaml
|
83
|
-
└── workloads
|
84
|
-
├── rbd_api_tests.yaml
|
85
|
-
└── rbd_api_tests_old_format.yaml""".split('\n')
|
86
|
-
|
87
|
-
|
88
|
-
expected_facets = [
|
89
|
-
'',
|
90
|
-
'',
|
91
|
-
'base',
|
92
|
-
'',
|
93
|
-
'clusters',
|
94
|
-
'clusters',
|
95
|
-
'clusters',
|
96
|
-
'',
|
97
|
-
'workloads',
|
98
|
-
'workloads',
|
99
|
-
]
|
100
|
-
|
101
|
-
|
102
|
-
expected_desc = [
|
103
|
-
'',
|
104
|
-
'',
|
105
|
-
'install ceph',
|
106
|
-
'',
|
107
|
-
'single node cluster',
|
108
|
-
'couple node cluster',
|
109
|
-
'triple node cluster',
|
110
|
-
'',
|
111
|
-
'c/c++ librbd api tests with default settings',
|
112
|
-
'c/c++ librbd api tests with format 1 images',
|
113
|
-
]
|
114
|
-
|
115
|
-
|
116
|
-
expected_rbd_features = [
|
117
|
-
'',
|
118
|
-
'',
|
119
|
-
'',
|
120
|
-
'',
|
121
|
-
'',
|
122
|
-
'',
|
123
|
-
'',
|
124
|
-
'',
|
125
|
-
'default',
|
126
|
-
'none',
|
127
|
-
]
|
128
|
-
|
129
|
-
|
130
|
-
class TestDescribeTests(object):
|
131
|
-
|
132
|
-
def setup(self):
|
133
|
-
self.mocks = dict()
|
134
|
-
self.patchers = dict()
|
135
|
-
exists, listdir, isfile, isdir, open = make_fake_fstools(realistic_fs)
|
136
|
-
for ppoint, fn in {
|
137
|
-
'os.listdir': listdir,
|
138
|
-
'os.path.isdir': isdir,
|
139
|
-
'teuthology.describe_tests.open': open,
|
140
|
-
'os.path.exists': exists,
|
141
|
-
'os.listdir': listdir,
|
142
|
-
'os.path.isfile': isfile,
|
143
|
-
}.items():
|
144
|
-
mockobj = MagicMock()
|
145
|
-
patcher = patch(ppoint, mockobj)
|
146
|
-
mockobj.side_effect = fn
|
147
|
-
patcher.start()
|
148
|
-
self.mocks[ppoint] = mockobj
|
149
|
-
self.patchers[ppoint] = patcher
|
150
|
-
|
151
|
-
def stop_patchers(self):
|
152
|
-
for patcher in self.patchers.values():
|
153
|
-
patcher.stop()
|
154
|
-
|
155
|
-
def teardown(self):
|
156
|
-
self.stop_patchers()
|
157
|
-
|
158
|
-
@staticmethod
|
159
|
-
def assert_expected_combo_headers(headers):
|
160
|
-
assert headers == (['subsuite depth 0'] +
|
161
|
-
sorted(set(filter(bool, expected_facets))))
|
162
|
-
|
163
|
-
def test_no_filters(self):
|
164
|
-
rows = tree_with_info('basic', [], False, '', [])
|
165
|
-
assert rows == [[x] for x in expected_tree]
|
166
|
-
|
167
|
-
def test_single_filter(self):
|
168
|
-
rows = tree_with_info('basic', ['desc'], False, '', [])
|
169
|
-
assert rows == [list(_) for _ in zip(expected_tree, expected_desc)]
|
170
|
-
|
171
|
-
rows = tree_with_info('basic', ['rbd_features'], False, '', [])
|
172
|
-
assert rows == [list(_) for _ in zip(expected_tree, expected_rbd_features)]
|
173
|
-
|
174
|
-
def test_single_filter_with_facets(self):
|
175
|
-
rows = tree_with_info('basic', ['desc'], True, '', [])
|
176
|
-
assert rows == [list(_) for _ in zip(expected_tree, expected_facets,
|
177
|
-
expected_desc)]
|
178
|
-
|
179
|
-
rows = tree_with_info('basic', ['rbd_features'], True, '', [])
|
180
|
-
assert rows == [list(_) for _ in zip(expected_tree, expected_facets,
|
181
|
-
expected_rbd_features)]
|
182
|
-
|
183
|
-
def test_no_matching(self):
|
184
|
-
rows = tree_with_info('basic', ['extra'], False, '', [])
|
185
|
-
assert rows == [list(_) for _ in zip(expected_tree, [''] * len(expected_tree))]
|
186
|
-
|
187
|
-
rows = tree_with_info('basic', ['extra'], True, '', [])
|
188
|
-
assert rows == [list(_) for _ in zip(expected_tree, expected_facets,
|
189
|
-
[''] * len(expected_tree))]
|
190
|
-
|
191
|
-
def test_multiple_filters(self):
|
192
|
-
rows = tree_with_info('basic', ['desc', 'rbd_features'], False, '', [])
|
193
|
-
assert rows == [list(_) for _ in zip(expected_tree,
|
194
|
-
expected_desc,
|
195
|
-
expected_rbd_features)]
|
196
|
-
|
197
|
-
rows = tree_with_info('basic', ['rbd_features', 'desc'], False, '', [])
|
198
|
-
assert rows == [list(_) for _ in zip(expected_tree,
|
199
|
-
expected_rbd_features,
|
200
|
-
expected_desc)]
|
201
|
-
|
202
|
-
def test_multiple_filters_with_facets(self):
|
203
|
-
rows = tree_with_info('basic', ['desc', 'rbd_features'], True, '', [])
|
204
|
-
assert rows == [list(_) for _ in zip(expected_tree,
|
205
|
-
expected_facets,
|
206
|
-
expected_desc,
|
207
|
-
expected_rbd_features)]
|
208
|
-
|
209
|
-
rows = tree_with_info('basic', ['rbd_features', 'desc'], True, '', [])
|
210
|
-
assert rows == [list(_) for _ in zip(expected_tree,
|
211
|
-
expected_facets,
|
212
|
-
expected_rbd_features,
|
213
|
-
expected_desc)]
|
214
|
-
|
215
|
-
def test_combinations_only_facets(self):
|
216
|
-
headers, rows = get_combinations('basic',
|
217
|
-
fields=[], subset=None, limit=1,
|
218
|
-
filter_in=None, filter_out=None, filter_all=None,
|
219
|
-
include_facet=True)
|
220
|
-
self.assert_expected_combo_headers(headers)
|
221
|
-
assert rows == [['basic', 'install', 'fixed-1', 'rbd_api_tests']]
|
222
|
-
|
223
|
-
def test_combinations_desc_features(self):
|
224
|
-
headers, rows = get_combinations('basic',
|
225
|
-
fields=['desc', 'rbd_features'], subset=None, limit=1,
|
226
|
-
filter_in=None, filter_out=None, filter_all=None,
|
227
|
-
include_facet=False)
|
228
|
-
assert headers == ['desc', 'rbd_features']
|
229
|
-
descriptions = '\n'.join([
|
230
|
-
'install ceph',
|
231
|
-
'single node cluster',
|
232
|
-
'c/c++ librbd api tests with default settings',
|
233
|
-
])
|
234
|
-
assert rows == [[descriptions, 'default']]
|
235
|
-
|
236
|
-
def test_combinations_filter_in(self):
|
237
|
-
headers, rows = get_combinations('basic',
|
238
|
-
fields=[], subset=None, limit=0,
|
239
|
-
filter_in=['old_format'], filter_out=None, filter_all=None,
|
240
|
-
include_facet=True)
|
241
|
-
self.assert_expected_combo_headers(headers)
|
242
|
-
assert rows == [
|
243
|
-
['basic', 'install', 'fixed-1', 'rbd_api_tests_old_format'],
|
244
|
-
['basic', 'install', 'fixed-2', 'rbd_api_tests_old_format'],
|
245
|
-
['basic', 'install', 'fixed-3', 'rbd_api_tests_old_format'],
|
246
|
-
]
|
247
|
-
|
248
|
-
def test_combinations_filter_out(self):
|
249
|
-
headers, rows = get_combinations('basic',
|
250
|
-
fields=[], subset=None, limit=0,
|
251
|
-
filter_in=None, filter_out=['old_format'], filter_all=None,
|
252
|
-
include_facet=True)
|
253
|
-
self.assert_expected_combo_headers(headers)
|
254
|
-
assert rows == [
|
255
|
-
['basic', 'install', 'fixed-1', 'rbd_api_tests'],
|
256
|
-
['basic', 'install', 'fixed-2', 'rbd_api_tests'],
|
257
|
-
['basic', 'install', 'fixed-3', 'rbd_api_tests'],
|
258
|
-
]
|
259
|
-
|
260
|
-
def test_combinations_filter_all(self):
|
261
|
-
headers, rows = get_combinations('basic',
|
262
|
-
fields=[], subset=None, limit=0,
|
263
|
-
filter_in=None, filter_out=None,
|
264
|
-
filter_all=['fixed-2', 'old_format'],
|
265
|
-
include_facet=True)
|
266
|
-
self.assert_expected_combo_headers(headers)
|
267
|
-
assert rows == [
|
268
|
-
['basic', 'install', 'fixed-2', 'rbd_api_tests_old_format']
|
269
|
-
]
|
270
|
-
|
271
|
-
|
272
|
-
@patch('teuthology.describe_tests.open')
|
273
|
-
@patch('os.path.isdir')
|
274
|
-
def test_extract_info_dir(m_isdir, m_open):
|
275
|
-
simple_fs = {'a': {'b.yaml': 'meta: [{foo: c}]'}}
|
276
|
-
_, _, _, m_isdir.side_effect, m_open.side_effect = \
|
277
|
-
make_fake_fstools(simple_fs)
|
278
|
-
info = extract_info('a', [])
|
279
|
-
assert info == {}
|
280
|
-
|
281
|
-
info = extract_info('a', ['foo', 'bar'])
|
282
|
-
assert info == {'foo': '', 'bar': ''}
|
283
|
-
|
284
|
-
info = extract_info('a/b.yaml', ['foo', 'bar'])
|
285
|
-
assert info == {'foo': 'c', 'bar': ''}
|
286
|
-
|
287
|
-
|
288
|
-
@patch('teuthology.describe_tests.open')
|
289
|
-
@patch('os.path.isdir')
|
290
|
-
def check_parse_error(fs, m_isdir, m_open):
|
291
|
-
_, _, _, m_isdir.side_effect, m_open.side_effect = make_fake_fstools(fs)
|
292
|
-
with pytest.raises(ParseError):
|
293
|
-
a = extract_info('a.yaml', ['a'])
|
294
|
-
raise Exception(str(a))
|
295
|
-
|
296
|
-
|
297
|
-
def test_extract_info_too_many_elements():
|
298
|
-
check_parse_error({'a.yaml': 'meta: [{a: b}, {b: c}]'})
|
299
|
-
|
300
|
-
|
301
|
-
def test_extract_info_not_a_list():
|
302
|
-
check_parse_error({'a.yaml': 'meta: {a: b}'})
|
303
|
-
|
304
|
-
|
305
|
-
def test_extract_info_not_a_dict():
|
306
|
-
check_parse_error({'a.yaml': 'meta: [[a, b]]'})
|
307
|
-
|
308
|
-
|
309
|
-
@patch('teuthology.describe_tests.open')
|
310
|
-
@patch('os.path.isdir')
|
311
|
-
def test_extract_info_empty_file(m_isdir, m_open):
|
312
|
-
simple_fs = {'a.yaml': ''}
|
313
|
-
_, _, _, m_isdir.side_effect, m_open.side_effect = \
|
314
|
-
make_fake_fstools(simple_fs)
|
315
|
-
info = extract_info('a.yaml', [])
|
316
|
-
assert info == {}
|
@@ -1,81 +0,0 @@
|
|
1
|
-
from humanfriendly import format_timespan
|
2
|
-
from mock import Mock, patch
|
3
|
-
from pytest import mark
|
4
|
-
from teuthology.config import config
|
5
|
-
from teuthology.run_tasks import build_email_body as email_body
|
6
|
-
from textwrap import dedent
|
7
|
-
|
8
|
-
class TestSleepBeforeTeardownEmail(object):
|
9
|
-
def setup(self):
|
10
|
-
config.results_ui_server = "http://example.com/"
|
11
|
-
config.archive_server = "http://qa-proxy.ceph.com/teuthology/"
|
12
|
-
|
13
|
-
@mark.parametrize(
|
14
|
-
['status', 'owner', 'suite_name', 'run_name', 'job_id', 'dura'],
|
15
|
-
[
|
16
|
-
[
|
17
|
-
'pass',
|
18
|
-
'noreply@host',
|
19
|
-
'dummy',
|
20
|
-
'run-name',
|
21
|
-
123,
|
22
|
-
3600,
|
23
|
-
],
|
24
|
-
[
|
25
|
-
'fail',
|
26
|
-
'noname',
|
27
|
-
'yummy',
|
28
|
-
'next-run',
|
29
|
-
1000,
|
30
|
-
99999,
|
31
|
-
],
|
32
|
-
]
|
33
|
-
)
|
34
|
-
@patch("teuthology.run_tasks.time.time")
|
35
|
-
def test_sleep_before_teardown_email_body(self, m_time, status, owner,
|
36
|
-
suite_name, run_name, job_id, dura):
|
37
|
-
ctx = Mock()
|
38
|
-
archive_path='archive/path'
|
39
|
-
archive_dir='/archive/dir'
|
40
|
-
date_sec=3661
|
41
|
-
date_str='1970-01-01 01:01:01'
|
42
|
-
m_time.return_value=float(date_sec)
|
43
|
-
duration_sec=dura
|
44
|
-
duration_str=format_timespan(duration_sec)
|
45
|
-
ref_body=dedent("""
|
46
|
-
Teuthology job {run}/{job} has fallen asleep at {date} for {duration_str}
|
47
|
-
|
48
|
-
Owner: {owner}
|
49
|
-
Suite Name: {suite}
|
50
|
-
Sleep Date: {date}
|
51
|
-
Sleep Time: {duration_sec} seconds ({duration_str})
|
52
|
-
Job Info: http://example.com/{run}/
|
53
|
-
Job Logs: http://qa-proxy.ceph.com/teuthology/path/{job}/
|
54
|
-
Task Stack: a/b/c
|
55
|
-
Current Status: {status}"""
|
56
|
-
.format(duration_sec=duration_sec, duration_str=duration_str,
|
57
|
-
owner=owner, suite=suite_name, run=run_name,
|
58
|
-
job=job_id, status=status, date=date_str))
|
59
|
-
print(ref_body)
|
60
|
-
ctx.config = dict(
|
61
|
-
archive_path=archive_path,
|
62
|
-
job_id=job_id,
|
63
|
-
suite=suite_name,
|
64
|
-
)
|
65
|
-
if status == 'pass':
|
66
|
-
ctx.summary = dict(
|
67
|
-
success=True,
|
68
|
-
)
|
69
|
-
elif status == 'fail':
|
70
|
-
ctx.summary = dict(
|
71
|
-
success=False,
|
72
|
-
)
|
73
|
-
else:
|
74
|
-
ctx.summary = dict()
|
75
|
-
|
76
|
-
ctx.owner = owner
|
77
|
-
ctx.name = run_name
|
78
|
-
ctx.archive_dir = archive_dir
|
79
|
-
tasks = [('a', None), ('b', None), ('c', None)]
|
80
|
-
(subj, body) = email_body(ctx, tasks, dura)
|
81
|
-
assert body == ref_body.lstrip('\n')
|