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
File without changes
|
File without changes
|
@@ -1,94 +0,0 @@
|
|
1
|
-
from teuthology.orchestra import monkey
|
2
|
-
monkey.patch_all()
|
3
|
-
|
4
|
-
from io import StringIO
|
5
|
-
|
6
|
-
import os
|
7
|
-
from teuthology.orchestra import connection, remote, run
|
8
|
-
from teuthology.orchestra.test.util import assert_raises
|
9
|
-
from teuthology.exceptions import CommandCrashedError, ConnectionLostError
|
10
|
-
|
11
|
-
from pytest import skip
|
12
|
-
|
13
|
-
HOST = None
|
14
|
-
|
15
|
-
|
16
|
-
class TestIntegration():
|
17
|
-
def setup(self):
|
18
|
-
try:
|
19
|
-
host = os.environ['ORCHESTRA_TEST_HOST']
|
20
|
-
except KeyError:
|
21
|
-
skip('To run integration tests, set environment ' +
|
22
|
-
'variable ORCHESTRA_TEST_HOST to user@host to use.')
|
23
|
-
global HOST
|
24
|
-
HOST = host
|
25
|
-
|
26
|
-
def test_crash(self):
|
27
|
-
ssh = connection.connect(HOST)
|
28
|
-
e = assert_raises(
|
29
|
-
CommandCrashedError,
|
30
|
-
run.run,
|
31
|
-
client=ssh,
|
32
|
-
args=['sh', '-c', 'kill -ABRT $$'],
|
33
|
-
)
|
34
|
-
assert e.command == "sh -c 'kill -ABRT $$'"
|
35
|
-
assert str(e) == "Command crashed: \"sh -c 'kill -ABRT $$'\""
|
36
|
-
|
37
|
-
def test_lost(self):
|
38
|
-
ssh = connection.connect(HOST)
|
39
|
-
e = assert_raises(
|
40
|
-
ConnectionLostError,
|
41
|
-
run.run,
|
42
|
-
client=ssh,
|
43
|
-
args=['sh', '-c', 'kill -ABRT $PPID'],
|
44
|
-
name=HOST,
|
45
|
-
)
|
46
|
-
assert e.command == "sh -c 'kill -ABRT $PPID'"
|
47
|
-
assert str(e) == \
|
48
|
-
"SSH connection to {host} was lost: ".format(host=HOST) + \
|
49
|
-
"\"sh -c 'kill -ABRT $PPID'\""
|
50
|
-
|
51
|
-
def test_pipe(self):
|
52
|
-
ssh = connection.connect(HOST)
|
53
|
-
r = run.run(
|
54
|
-
client=ssh,
|
55
|
-
args=['cat'],
|
56
|
-
stdin=run.PIPE,
|
57
|
-
stdout=StringIO(),
|
58
|
-
wait=False,
|
59
|
-
)
|
60
|
-
assert r.stdout.getvalue() == ''
|
61
|
-
r.stdin.write('foo\n')
|
62
|
-
r.stdin.write('bar\n')
|
63
|
-
r.stdin.close()
|
64
|
-
|
65
|
-
r.wait()
|
66
|
-
got = r.exitstatus
|
67
|
-
assert got == 0
|
68
|
-
assert r.stdout.getvalue() == 'foo\nbar\n'
|
69
|
-
|
70
|
-
def test_and(self):
|
71
|
-
ssh = connection.connect(HOST)
|
72
|
-
r = run.run(
|
73
|
-
client=ssh,
|
74
|
-
args=['true', run.Raw('&&'), 'echo', 'yup'],
|
75
|
-
stdout=StringIO(),
|
76
|
-
)
|
77
|
-
assert r.stdout.getvalue() == 'yup\n'
|
78
|
-
|
79
|
-
def test_os(self):
|
80
|
-
rem = remote.Remote(HOST)
|
81
|
-
assert rem.os.name
|
82
|
-
assert rem.os.version
|
83
|
-
|
84
|
-
def test_17102(self, caplog):
|
85
|
-
# http://tracker.ceph.com/issues/17102
|
86
|
-
rem = remote.Remote(HOST)
|
87
|
-
interval = 3
|
88
|
-
rem.run(args="echo before; sleep %s; echo after" % interval)
|
89
|
-
for record in caplog.records:
|
90
|
-
if record.msg == 'before':
|
91
|
-
before_time = record.created
|
92
|
-
elif record.msg == 'after':
|
93
|
-
after_time = record.created
|
94
|
-
assert int(round(after_time - before_time)) == interval
|
@@ -1,240 +0,0 @@
|
|
1
|
-
import fudge
|
2
|
-
import pytest
|
3
|
-
|
4
|
-
from mock import patch, Mock
|
5
|
-
|
6
|
-
from teuthology.orchestra import cluster, remote
|
7
|
-
|
8
|
-
|
9
|
-
class TestCluster(object):
|
10
|
-
@fudge.with_fakes
|
11
|
-
def test_init_empty(self):
|
12
|
-
fudge.clear_expectations()
|
13
|
-
c = cluster.Cluster()
|
14
|
-
assert c.remotes == {}
|
15
|
-
|
16
|
-
@fudge.with_fakes
|
17
|
-
def test_init(self):
|
18
|
-
fudge.clear_expectations()
|
19
|
-
r1 = fudge.Fake('Remote')
|
20
|
-
r2 = fudge.Fake('Remote')
|
21
|
-
c = cluster.Cluster(
|
22
|
-
remotes=[
|
23
|
-
(r1, ['foo', 'bar']),
|
24
|
-
(r2, ['baz']),
|
25
|
-
],
|
26
|
-
)
|
27
|
-
r3 = fudge.Fake('Remote')
|
28
|
-
c.add(r3, ['xyzzy', 'thud', 'foo'])
|
29
|
-
assert c.remotes == {
|
30
|
-
r1: ['foo', 'bar'],
|
31
|
-
r2: ['baz'],
|
32
|
-
r3: ['xyzzy', 'thud', 'foo'],
|
33
|
-
}
|
34
|
-
|
35
|
-
@fudge.with_fakes
|
36
|
-
def test_repr(self):
|
37
|
-
fudge.clear_expectations()
|
38
|
-
r1 = remote.Remote('r1', ssh=fudge.Fake('SSH'))
|
39
|
-
r2 = remote.Remote('r2', ssh=fudge.Fake('SSH'))
|
40
|
-
c = cluster.Cluster(
|
41
|
-
remotes=[
|
42
|
-
(r1, ['foo', 'bar']),
|
43
|
-
(r2, ['baz']),
|
44
|
-
],
|
45
|
-
)
|
46
|
-
assert repr(c) == "Cluster(remotes=[[Remote(name='r1'), ['foo', 'bar']], [Remote(name='r2'), ['baz']]])" # noqa
|
47
|
-
|
48
|
-
@fudge.with_fakes
|
49
|
-
def test_str(self):
|
50
|
-
fudge.clear_expectations()
|
51
|
-
r1 = remote.Remote('r1', ssh=fudge.Fake('SSH'))
|
52
|
-
r2 = remote.Remote('r2', ssh=fudge.Fake('SSH'))
|
53
|
-
c = cluster.Cluster(
|
54
|
-
remotes=[
|
55
|
-
(r1, ['foo', 'bar']),
|
56
|
-
(r2, ['baz']),
|
57
|
-
],
|
58
|
-
)
|
59
|
-
assert str(c) == "r1[foo,bar] r2[baz]"
|
60
|
-
|
61
|
-
@fudge.with_fakes
|
62
|
-
def test_run_all(self):
|
63
|
-
fudge.clear_expectations()
|
64
|
-
r1 = fudge.Fake('Remote').has_attr(name='r1')
|
65
|
-
ret1 = fudge.Fake('RemoteProcess')
|
66
|
-
r1.expects('run').with_args(args=['test']).returns(ret1)
|
67
|
-
r2 = fudge.Fake('Remote').has_attr(name='r2')
|
68
|
-
ret2 = fudge.Fake('RemoteProcess')
|
69
|
-
r2.expects('run').with_args(args=['test']).returns(ret2)
|
70
|
-
c = cluster.Cluster(
|
71
|
-
remotes=[
|
72
|
-
(r1, ['foo', 'bar']),
|
73
|
-
(r2, ['baz']),
|
74
|
-
],
|
75
|
-
)
|
76
|
-
got = c.run(args=['test'])
|
77
|
-
assert len(got) == 2
|
78
|
-
assert got, [ret1 == ret2]
|
79
|
-
# check identity not equality
|
80
|
-
assert got[0] is ret1
|
81
|
-
assert got[1] is ret2
|
82
|
-
|
83
|
-
@fudge.with_fakes
|
84
|
-
def test_only_one(self):
|
85
|
-
fudge.clear_expectations()
|
86
|
-
r1 = fudge.Fake('r1')
|
87
|
-
r2 = fudge.Fake('r2')
|
88
|
-
r3 = fudge.Fake('r3')
|
89
|
-
c = cluster.Cluster(
|
90
|
-
remotes=[
|
91
|
-
(r1, ['foo', 'bar']),
|
92
|
-
(r2, ['bar']),
|
93
|
-
(r3, ['foo']),
|
94
|
-
],
|
95
|
-
)
|
96
|
-
c_foo = c.only('foo')
|
97
|
-
assert c_foo.remotes == {r1: ['foo', 'bar'], r3: ['foo']}
|
98
|
-
|
99
|
-
@fudge.with_fakes
|
100
|
-
def test_only_two(self):
|
101
|
-
fudge.clear_expectations()
|
102
|
-
r1 = fudge.Fake('r1')
|
103
|
-
r2 = fudge.Fake('r2')
|
104
|
-
r3 = fudge.Fake('r3')
|
105
|
-
c = cluster.Cluster(
|
106
|
-
remotes=[
|
107
|
-
(r1, ['foo', 'bar']),
|
108
|
-
(r2, ['bar']),
|
109
|
-
(r3, ['foo']),
|
110
|
-
],
|
111
|
-
)
|
112
|
-
c_both = c.only('foo', 'bar')
|
113
|
-
assert c_both.remotes, {r1: ['foo' == 'bar']}
|
114
|
-
|
115
|
-
@fudge.with_fakes
|
116
|
-
def test_only_none(self):
|
117
|
-
fudge.clear_expectations()
|
118
|
-
r1 = fudge.Fake('r1')
|
119
|
-
r2 = fudge.Fake('r2')
|
120
|
-
r3 = fudge.Fake('r3')
|
121
|
-
c = cluster.Cluster(
|
122
|
-
remotes=[
|
123
|
-
(r1, ['foo', 'bar']),
|
124
|
-
(r2, ['bar']),
|
125
|
-
(r3, ['foo']),
|
126
|
-
],
|
127
|
-
)
|
128
|
-
c_none = c.only('impossible')
|
129
|
-
assert c_none.remotes == {}
|
130
|
-
|
131
|
-
@fudge.with_fakes
|
132
|
-
def test_only_match(self):
|
133
|
-
fudge.clear_expectations()
|
134
|
-
r1 = fudge.Fake('r1')
|
135
|
-
r2 = fudge.Fake('r2')
|
136
|
-
r3 = fudge.Fake('r3')
|
137
|
-
c = cluster.Cluster(
|
138
|
-
remotes=[
|
139
|
-
(r1, ['foo', 'bar']),
|
140
|
-
(r2, ['bar']),
|
141
|
-
(r3, ['foo']),
|
142
|
-
],
|
143
|
-
)
|
144
|
-
c_foo = c.only('foo', lambda role: role.startswith('b'))
|
145
|
-
assert c_foo.remotes, {r1: ['foo' == 'bar']}
|
146
|
-
|
147
|
-
@fudge.with_fakes
|
148
|
-
def test_exclude_one(self):
|
149
|
-
fudge.clear_expectations()
|
150
|
-
r1 = fudge.Fake('r1')
|
151
|
-
r2 = fudge.Fake('r2')
|
152
|
-
r3 = fudge.Fake('r3')
|
153
|
-
c = cluster.Cluster(
|
154
|
-
remotes=[
|
155
|
-
(r1, ['foo', 'bar']),
|
156
|
-
(r2, ['bar']),
|
157
|
-
(r3, ['foo']),
|
158
|
-
],
|
159
|
-
)
|
160
|
-
c_foo = c.exclude('foo')
|
161
|
-
assert c_foo.remotes == {r2: ['bar']}
|
162
|
-
|
163
|
-
@fudge.with_fakes
|
164
|
-
def test_exclude_two(self):
|
165
|
-
fudge.clear_expectations()
|
166
|
-
r1 = fudge.Fake('r1')
|
167
|
-
r2 = fudge.Fake('r2')
|
168
|
-
r3 = fudge.Fake('r3')
|
169
|
-
c = cluster.Cluster(
|
170
|
-
remotes=[
|
171
|
-
(r1, ['foo', 'bar']),
|
172
|
-
(r2, ['bar']),
|
173
|
-
(r3, ['foo']),
|
174
|
-
],
|
175
|
-
)
|
176
|
-
c_both = c.exclude('foo', 'bar')
|
177
|
-
assert c_both.remotes == {r2: ['bar'], r3: ['foo']}
|
178
|
-
|
179
|
-
@fudge.with_fakes
|
180
|
-
def test_exclude_none(self):
|
181
|
-
fudge.clear_expectations()
|
182
|
-
r1 = fudge.Fake('r1')
|
183
|
-
r2 = fudge.Fake('r2')
|
184
|
-
r3 = fudge.Fake('r3')
|
185
|
-
c = cluster.Cluster(
|
186
|
-
remotes=[
|
187
|
-
(r1, ['foo', 'bar']),
|
188
|
-
(r2, ['bar']),
|
189
|
-
(r3, ['foo']),
|
190
|
-
],
|
191
|
-
)
|
192
|
-
c_none = c.exclude('impossible')
|
193
|
-
assert c_none.remotes == {r1: ['foo', 'bar'], r2: ['bar'], r3: ['foo']}
|
194
|
-
|
195
|
-
@fudge.with_fakes
|
196
|
-
def test_exclude_match(self):
|
197
|
-
fudge.clear_expectations()
|
198
|
-
r1 = fudge.Fake('r1')
|
199
|
-
r2 = fudge.Fake('r2')
|
200
|
-
r3 = fudge.Fake('r3')
|
201
|
-
c = cluster.Cluster(
|
202
|
-
remotes=[
|
203
|
-
(r1, ['foo', 'bar']),
|
204
|
-
(r2, ['bar']),
|
205
|
-
(r3, ['foo']),
|
206
|
-
],
|
207
|
-
)
|
208
|
-
c_foo = c.exclude('foo', lambda role: role.startswith('b'))
|
209
|
-
assert c_foo.remotes == {r2: ['bar'], r3: ['foo']}
|
210
|
-
|
211
|
-
|
212
|
-
class TestWriteFile(object):
|
213
|
-
""" Tests for cluster.write_file """
|
214
|
-
def setup(self):
|
215
|
-
self.r1 = remote.Remote('r1', ssh=Mock())
|
216
|
-
self.c = cluster.Cluster(
|
217
|
-
remotes=[
|
218
|
-
(self.r1, ['foo', 'bar']),
|
219
|
-
],
|
220
|
-
)
|
221
|
-
|
222
|
-
@patch("teuthology.misc.write_file")
|
223
|
-
def test_write_file(self, m_write_file):
|
224
|
-
self.c.write_file("filename", "content")
|
225
|
-
m_write_file.assert_called_with(self.r1, "filename", "content")
|
226
|
-
|
227
|
-
@patch("teuthology.misc.write_file")
|
228
|
-
def test_fails_with_invalid_perms(self, m_write_file):
|
229
|
-
with pytest.raises(ValueError):
|
230
|
-
self.c.write_file("filename", "content", sudo=False, perms="invalid")
|
231
|
-
|
232
|
-
@patch("teuthology.misc.write_file")
|
233
|
-
def test_fails_with_invalid_owner(self, m_write_file):
|
234
|
-
with pytest.raises(ValueError):
|
235
|
-
self.c.write_file("filename", "content", sudo=False, owner="invalid")
|
236
|
-
|
237
|
-
@patch("teuthology.misc.sudo_write_file")
|
238
|
-
def test_with_sudo(self, m_sudo_write_file):
|
239
|
-
self.c.write_file("filename", "content", sudo=True)
|
240
|
-
m_sudo_write_file.assert_called_with(self.r1, "filename", "content", owner=None, perms=None)
|
@@ -1,106 +0,0 @@
|
|
1
|
-
import fudge
|
2
|
-
|
3
|
-
from teuthology import config
|
4
|
-
from teuthology.orchestra import connection
|
5
|
-
from teuthology.orchestra.test.util import assert_raises
|
6
|
-
|
7
|
-
|
8
|
-
class TestConnection(object):
|
9
|
-
def setup(self):
|
10
|
-
import time
|
11
|
-
time.sleep = lambda s: True
|
12
|
-
|
13
|
-
def clear_config(self):
|
14
|
-
config.config.teuthology_yaml = ''
|
15
|
-
config.config.load()
|
16
|
-
|
17
|
-
def test_split_user_just_host(self):
|
18
|
-
got = connection.split_user('somehost.example.com')
|
19
|
-
assert got == (None, 'somehost.example.com')
|
20
|
-
|
21
|
-
def test_split_user_both(self):
|
22
|
-
got = connection.split_user('jdoe@somehost.example.com')
|
23
|
-
assert got == ('jdoe', 'somehost.example.com')
|
24
|
-
|
25
|
-
def test_split_user_empty_user(self):
|
26
|
-
s = '@somehost.example.com'
|
27
|
-
e = assert_raises(AssertionError, connection.split_user, s)
|
28
|
-
assert str(e) == 'Bad input to split_user: {s!r}'.format(s=s)
|
29
|
-
|
30
|
-
@fudge.with_fakes
|
31
|
-
def test_connect(self):
|
32
|
-
self.clear_config()
|
33
|
-
config.config.verify_host_keys = True
|
34
|
-
fudge.clear_expectations()
|
35
|
-
ssh = fudge.Fake('SSHClient')
|
36
|
-
ssh.expects_call().with_args().returns(ssh)
|
37
|
-
ssh.expects('set_missing_host_key_policy')
|
38
|
-
ssh.expects('load_system_host_keys').with_args()
|
39
|
-
ssh.expects('connect').with_args(
|
40
|
-
hostname='orchestra.test.newdream.net.invalid',
|
41
|
-
username='jdoe',
|
42
|
-
timeout=60,
|
43
|
-
)
|
44
|
-
transport = ssh.expects('get_transport').with_args().returns_fake()
|
45
|
-
transport.remember_order()
|
46
|
-
transport.expects('set_keepalive').with_args(False)
|
47
|
-
got = connection.connect(
|
48
|
-
'jdoe@orchestra.test.newdream.net.invalid',
|
49
|
-
_SSHClient=ssh,
|
50
|
-
)
|
51
|
-
assert got is ssh
|
52
|
-
|
53
|
-
@fudge.with_fakes
|
54
|
-
def test_connect_no_verify_host_keys(self):
|
55
|
-
self.clear_config()
|
56
|
-
config.config.verify_host_keys = False
|
57
|
-
fudge.clear_expectations()
|
58
|
-
ssh = fudge.Fake('SSHClient')
|
59
|
-
ssh.expects_call().with_args().returns(ssh)
|
60
|
-
ssh.expects('set_missing_host_key_policy')
|
61
|
-
ssh.expects('connect').with_args(
|
62
|
-
hostname='orchestra.test.newdream.net.invalid',
|
63
|
-
username='jdoe',
|
64
|
-
timeout=60,
|
65
|
-
)
|
66
|
-
transport = ssh.expects('get_transport').with_args().returns_fake()
|
67
|
-
transport.remember_order()
|
68
|
-
transport.expects('set_keepalive').with_args(False)
|
69
|
-
got = connection.connect(
|
70
|
-
'jdoe@orchestra.test.newdream.net.invalid',
|
71
|
-
_SSHClient=ssh,
|
72
|
-
)
|
73
|
-
assert got is ssh
|
74
|
-
|
75
|
-
@fudge.with_fakes
|
76
|
-
def test_connect_override_hostkeys(self):
|
77
|
-
self.clear_config()
|
78
|
-
fudge.clear_expectations()
|
79
|
-
sshclient = fudge.Fake('SSHClient')
|
80
|
-
ssh = sshclient.expects_call().with_args().returns_fake()
|
81
|
-
ssh.remember_order()
|
82
|
-
host_keys = fudge.Fake('HostKeys')
|
83
|
-
host_keys.expects('add').with_args(
|
84
|
-
hostname='orchestra.test.newdream.net.invalid',
|
85
|
-
keytype='ssh-rsa',
|
86
|
-
key='frobnitz',
|
87
|
-
)
|
88
|
-
ssh.expects('get_host_keys').with_args().returns(host_keys)
|
89
|
-
ssh.expects('connect').with_args(
|
90
|
-
hostname='orchestra.test.newdream.net.invalid',
|
91
|
-
username='jdoe',
|
92
|
-
timeout=60,
|
93
|
-
)
|
94
|
-
transport = ssh.expects('get_transport').with_args().returns_fake()
|
95
|
-
transport.remember_order()
|
96
|
-
transport.expects('set_keepalive').with_args(False)
|
97
|
-
create_key = fudge.Fake('create_key')
|
98
|
-
create_key.expects_call().with_args('ssh-rsa',
|
99
|
-
'testkey').returns('frobnitz')
|
100
|
-
got = connection.connect(
|
101
|
-
'jdoe@orchestra.test.newdream.net.invalid',
|
102
|
-
host_key='ssh-rsa testkey',
|
103
|
-
_SSHClient=sshclient,
|
104
|
-
_create_key=create_key,
|
105
|
-
)
|
106
|
-
assert got is ssh
|
@@ -1,217 +0,0 @@
|
|
1
|
-
from mock import patch
|
2
|
-
|
3
|
-
from teuthology.config import config as teuth_config
|
4
|
-
|
5
|
-
from teuthology.orchestra import console
|
6
|
-
|
7
|
-
|
8
|
-
class TestConsole(object):
|
9
|
-
pass
|
10
|
-
|
11
|
-
|
12
|
-
class TestPhysicalConsole(TestConsole):
|
13
|
-
klass = console.PhysicalConsole
|
14
|
-
ipmi_cmd_templ = 'ipmitool -H {h}.{d} -I lanplus -U {u} -P {p} {c}'
|
15
|
-
conserver_cmd_templ = 'console -M {m} -p {p} {mode} {h}'
|
16
|
-
|
17
|
-
def setup(self):
|
18
|
-
self.hostname = 'host'
|
19
|
-
teuth_config.ipmi_domain = 'ipmi_domain'
|
20
|
-
teuth_config.ipmi_user = 'ipmi_user'
|
21
|
-
teuth_config.ipmi_password = 'ipmi_pass'
|
22
|
-
teuth_config.conserver_master = 'conserver_master'
|
23
|
-
teuth_config.conserver_port = 3109
|
24
|
-
teuth_config.use_conserver = True
|
25
|
-
|
26
|
-
def test_has_ipmi_creds(self):
|
27
|
-
cons = self.klass(self.hostname)
|
28
|
-
assert cons.has_ipmi_credentials is True
|
29
|
-
teuth_config.ipmi_domain = None
|
30
|
-
cons = self.klass(self.hostname)
|
31
|
-
assert cons.has_ipmi_credentials is False
|
32
|
-
|
33
|
-
def test_console_command_conserver(self):
|
34
|
-
cons = self.klass(
|
35
|
-
self.hostname,
|
36
|
-
teuth_config.ipmi_user,
|
37
|
-
teuth_config.ipmi_password,
|
38
|
-
teuth_config.ipmi_domain,
|
39
|
-
)
|
40
|
-
cons.has_conserver = True
|
41
|
-
console_cmd = cons._console_command()
|
42
|
-
assert console_cmd == self.conserver_cmd_templ.format(
|
43
|
-
m=teuth_config.conserver_master,
|
44
|
-
p=teuth_config.conserver_port,
|
45
|
-
mode='-s',
|
46
|
-
h=self.hostname,
|
47
|
-
)
|
48
|
-
console_cmd = cons._console_command(readonly=False)
|
49
|
-
assert console_cmd == self.conserver_cmd_templ.format(
|
50
|
-
m=teuth_config.conserver_master,
|
51
|
-
p=teuth_config.conserver_port,
|
52
|
-
mode='-f',
|
53
|
-
h=self.hostname,
|
54
|
-
)
|
55
|
-
|
56
|
-
def test_console_command_ipmi(self):
|
57
|
-
teuth_config.conserver_master = None
|
58
|
-
cons = self.klass(
|
59
|
-
self.hostname,
|
60
|
-
teuth_config.ipmi_user,
|
61
|
-
teuth_config.ipmi_password,
|
62
|
-
teuth_config.ipmi_domain,
|
63
|
-
)
|
64
|
-
sol_cmd = cons._console_command()
|
65
|
-
assert sol_cmd == self.ipmi_cmd_templ.format(
|
66
|
-
h=self.hostname,
|
67
|
-
d=teuth_config.ipmi_domain,
|
68
|
-
u=teuth_config.ipmi_user,
|
69
|
-
p=teuth_config.ipmi_password,
|
70
|
-
c='sol activate',
|
71
|
-
)
|
72
|
-
|
73
|
-
def test_ipmi_command_ipmi(self):
|
74
|
-
cons = self.klass(
|
75
|
-
self.hostname,
|
76
|
-
teuth_config.ipmi_user,
|
77
|
-
teuth_config.ipmi_password,
|
78
|
-
teuth_config.ipmi_domain,
|
79
|
-
)
|
80
|
-
pc_cmd = cons._ipmi_command('power cycle')
|
81
|
-
assert pc_cmd == self.ipmi_cmd_templ.format(
|
82
|
-
h=self.hostname,
|
83
|
-
d=teuth_config.ipmi_domain,
|
84
|
-
u=teuth_config.ipmi_user,
|
85
|
-
p=teuth_config.ipmi_password,
|
86
|
-
c='power cycle',
|
87
|
-
)
|
88
|
-
|
89
|
-
def test_spawn_log_conserver(self):
|
90
|
-
with patch(
|
91
|
-
'teuthology.orchestra.console.psutil.subprocess.Popen',
|
92
|
-
autospec=True,
|
93
|
-
) as m_popen:
|
94
|
-
m_popen.return_value.pid = 42
|
95
|
-
m_popen.return_value.returncode = 0
|
96
|
-
m_popen.return_value.wait.return_value = 0
|
97
|
-
cons = self.klass(self.hostname)
|
98
|
-
assert cons.has_conserver is True
|
99
|
-
m_popen.reset_mock()
|
100
|
-
m_popen.return_value.poll.return_value = None
|
101
|
-
cons.spawn_sol_log('/fake/path')
|
102
|
-
assert m_popen.call_count == 1
|
103
|
-
call_args = m_popen.call_args_list[0][0][0]
|
104
|
-
assert any(
|
105
|
-
[teuth_config.conserver_master in arg for arg in call_args]
|
106
|
-
)
|
107
|
-
|
108
|
-
def test_spawn_log_ipmi(self):
|
109
|
-
with patch(
|
110
|
-
'teuthology.orchestra.console.psutil.subprocess.Popen',
|
111
|
-
autospec=True,
|
112
|
-
) as m_popen:
|
113
|
-
m_popen.return_value.pid = 42
|
114
|
-
m_popen.return_value.returncode = 1
|
115
|
-
m_popen.return_value.wait.return_value = 1
|
116
|
-
cons = self.klass(self.hostname)
|
117
|
-
assert cons.has_conserver is False
|
118
|
-
m_popen.reset_mock()
|
119
|
-
m_popen.return_value.poll.return_value = 1
|
120
|
-
cons.spawn_sol_log('/fake/path')
|
121
|
-
assert m_popen.call_count == 1
|
122
|
-
call_args = m_popen.call_args_list[0][0][0]
|
123
|
-
assert any(
|
124
|
-
['ipmitool' in arg for arg in call_args]
|
125
|
-
)
|
126
|
-
|
127
|
-
def test_spawn_log_fallback(self):
|
128
|
-
with patch(
|
129
|
-
'teuthology.orchestra.console.psutil.subprocess.Popen',
|
130
|
-
autospec=True,
|
131
|
-
) as m_popen:
|
132
|
-
m_popen.return_value.pid = 42
|
133
|
-
m_popen.return_value.returncode = 0
|
134
|
-
m_popen.return_value.wait.return_value = 0
|
135
|
-
cons = self.klass(self.hostname)
|
136
|
-
assert cons.has_conserver is True
|
137
|
-
m_popen.reset_mock()
|
138
|
-
m_popen.return_value.poll.return_value = 1
|
139
|
-
cons.spawn_sol_log('/fake/path')
|
140
|
-
assert cons.has_conserver is False
|
141
|
-
assert m_popen.call_count == 2
|
142
|
-
call_args = m_popen.call_args_list[1][0][0]
|
143
|
-
assert any(
|
144
|
-
['ipmitool' in arg for arg in call_args]
|
145
|
-
)
|
146
|
-
|
147
|
-
def test_get_console_conserver(self):
|
148
|
-
with patch(
|
149
|
-
'teuthology.orchestra.console.psutil.subprocess.Popen',
|
150
|
-
autospec=True,
|
151
|
-
) as m_popen:
|
152
|
-
m_popen.return_value.pid = 42
|
153
|
-
m_popen.return_value.returncode = 0
|
154
|
-
m_popen.return_value.wait.return_value = 0
|
155
|
-
cons = self.klass(self.hostname)
|
156
|
-
assert cons.has_conserver is True
|
157
|
-
with patch(
|
158
|
-
'teuthology.orchestra.console.pexpect.spawn',
|
159
|
-
autospec=True,
|
160
|
-
) as m_spawn:
|
161
|
-
cons._get_console()
|
162
|
-
assert m_spawn.call_count == 1
|
163
|
-
assert teuth_config.conserver_master in \
|
164
|
-
m_spawn.call_args_list[0][0][0]
|
165
|
-
|
166
|
-
def test_get_console_ipmitool(self):
|
167
|
-
with patch(
|
168
|
-
'teuthology.orchestra.console.psutil.subprocess.Popen',
|
169
|
-
autospec=True,
|
170
|
-
) as m_popen:
|
171
|
-
m_popen.return_value.pid = 42
|
172
|
-
m_popen.return_value.returncode = 0
|
173
|
-
m_popen.return_value.wait.return_value = 0
|
174
|
-
cons = self.klass(self.hostname)
|
175
|
-
assert cons.has_conserver is True
|
176
|
-
with patch(
|
177
|
-
'teuthology.orchestra.console.pexpect.spawn',
|
178
|
-
autospec=True,
|
179
|
-
) as m_spawn:
|
180
|
-
cons.has_conserver = False
|
181
|
-
cons._get_console()
|
182
|
-
assert m_spawn.call_count == 1
|
183
|
-
assert 'ipmitool' in m_spawn.call_args_list[0][0][0]
|
184
|
-
|
185
|
-
def test_get_console_fallback(self):
|
186
|
-
with patch(
|
187
|
-
'teuthology.orchestra.console.psutil.subprocess.Popen',
|
188
|
-
autospec=True,
|
189
|
-
) as m_popen:
|
190
|
-
m_popen.return_value.pid = 42
|
191
|
-
m_popen.return_value.returncode = 0
|
192
|
-
m_popen.return_value.wait.return_value = 0
|
193
|
-
cons = self.klass(self.hostname)
|
194
|
-
assert cons.has_conserver is True
|
195
|
-
with patch(
|
196
|
-
'teuthology.orchestra.console.pexpect.spawn',
|
197
|
-
autospec=True,
|
198
|
-
) as m_spawn:
|
199
|
-
cons.has_conserver = True
|
200
|
-
m_spawn.return_value.isalive.return_value = False
|
201
|
-
cons._get_console()
|
202
|
-
assert m_spawn.return_value.isalive.call_count == 1
|
203
|
-
assert m_spawn.call_count == 2
|
204
|
-
assert cons.has_conserver is False
|
205
|
-
assert 'ipmitool' in m_spawn.call_args_list[1][0][0]
|
206
|
-
|
207
|
-
def test_disable_conserver(self):
|
208
|
-
with patch(
|
209
|
-
'teuthology.orchestra.console.psutil.subprocess.Popen',
|
210
|
-
autospec=True,
|
211
|
-
) as m_popen:
|
212
|
-
m_popen.return_value.pid = 42
|
213
|
-
m_popen.return_value.returncode = 0
|
214
|
-
m_popen.return_value.wait.return_value = 0
|
215
|
-
teuth_config.use_conserver = False
|
216
|
-
cons = self.klass(self.hostname)
|
217
|
-
assert cons.has_conserver is False
|