teuthology 1.0.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.
Files changed (172) hide show
  1. scripts/describe.py +1 -0
  2. scripts/dispatcher.py +62 -0
  3. scripts/exporter.py +18 -0
  4. scripts/lock.py +1 -1
  5. scripts/node_cleanup.py +58 -0
  6. scripts/openstack.py +9 -9
  7. scripts/results.py +12 -11
  8. scripts/run.py +4 -0
  9. scripts/schedule.py +4 -0
  10. scripts/suite.py +61 -16
  11. scripts/supervisor.py +44 -0
  12. scripts/update_inventory.py +10 -4
  13. scripts/wait.py +31 -0
  14. teuthology/__init__.py +24 -21
  15. teuthology/beanstalk.py +4 -3
  16. teuthology/config.py +17 -6
  17. teuthology/contextutil.py +18 -14
  18. teuthology/describe_tests.py +25 -18
  19. teuthology/dispatcher/__init__.py +365 -0
  20. teuthology/dispatcher/supervisor.py +374 -0
  21. teuthology/exceptions.py +54 -0
  22. teuthology/exporter.py +347 -0
  23. teuthology/kill.py +76 -75
  24. teuthology/lock/cli.py +16 -7
  25. teuthology/lock/ops.py +276 -70
  26. teuthology/lock/query.py +61 -44
  27. teuthology/ls.py +9 -18
  28. teuthology/misc.py +152 -137
  29. teuthology/nuke/__init__.py +12 -351
  30. teuthology/openstack/__init__.py +4 -3
  31. teuthology/openstack/openstack-centos-7.0-user-data.txt +1 -1
  32. teuthology/openstack/openstack-centos-7.1-user-data.txt +1 -1
  33. teuthology/openstack/openstack-centos-7.2-user-data.txt +1 -1
  34. teuthology/openstack/openstack-debian-8.0-user-data.txt +1 -1
  35. teuthology/openstack/openstack-opensuse-42.1-user-data.txt +1 -1
  36. teuthology/openstack/openstack-teuthology.cron +0 -1
  37. teuthology/orchestra/cluster.py +51 -9
  38. teuthology/orchestra/connection.py +23 -16
  39. teuthology/orchestra/console.py +111 -50
  40. teuthology/orchestra/daemon/cephadmunit.py +23 -5
  41. teuthology/orchestra/daemon/state.py +10 -3
  42. teuthology/orchestra/daemon/systemd.py +10 -8
  43. teuthology/orchestra/opsys.py +32 -11
  44. teuthology/orchestra/remote.py +369 -152
  45. teuthology/orchestra/run.py +21 -12
  46. teuthology/packaging.py +54 -15
  47. teuthology/provision/__init__.py +30 -10
  48. teuthology/provision/cloud/openstack.py +12 -6
  49. teuthology/provision/cloud/util.py +1 -2
  50. teuthology/provision/downburst.py +83 -29
  51. teuthology/provision/fog.py +68 -20
  52. teuthology/provision/openstack.py +5 -4
  53. teuthology/provision/pelagos.py +13 -5
  54. teuthology/repo_utils.py +91 -44
  55. teuthology/report.py +57 -35
  56. teuthology/results.py +5 -3
  57. teuthology/run.py +21 -15
  58. teuthology/run_tasks.py +114 -40
  59. teuthology/schedule.py +4 -3
  60. teuthology/scrape.py +28 -22
  61. teuthology/suite/__init__.py +75 -46
  62. teuthology/suite/build_matrix.py +34 -24
  63. teuthology/suite/fragment-merge.lua +105 -0
  64. teuthology/suite/matrix.py +31 -2
  65. teuthology/suite/merge.py +175 -0
  66. teuthology/suite/placeholder.py +8 -8
  67. teuthology/suite/run.py +204 -102
  68. teuthology/suite/util.py +67 -211
  69. teuthology/task/__init__.py +1 -1
  70. teuthology/task/ansible.py +101 -31
  71. teuthology/task/buildpackages.py +2 -2
  72. teuthology/task/ceph_ansible.py +13 -6
  73. teuthology/task/cephmetrics.py +2 -1
  74. teuthology/task/clock.py +33 -14
  75. teuthology/task/exec.py +18 -0
  76. teuthology/task/hadoop.py +2 -2
  77. teuthology/task/install/__init__.py +51 -22
  78. teuthology/task/install/bin/adjust-ulimits +16 -0
  79. teuthology/task/install/bin/daemon-helper +114 -0
  80. teuthology/task/install/bin/stdin-killer +263 -0
  81. teuthology/task/install/deb.py +24 -4
  82. teuthology/task/install/redhat.py +36 -32
  83. teuthology/task/install/rpm.py +41 -14
  84. teuthology/task/install/util.py +48 -22
  85. teuthology/task/internal/__init__.py +69 -11
  86. teuthology/task/internal/edit_sudoers.sh +10 -0
  87. teuthology/task/internal/lock_machines.py +3 -133
  88. teuthology/task/internal/redhat.py +48 -28
  89. teuthology/task/internal/syslog.py +31 -8
  90. teuthology/task/kernel.py +155 -147
  91. teuthology/task/lockfile.py +1 -1
  92. teuthology/task/mpi.py +10 -10
  93. teuthology/task/pcp.py +1 -1
  94. teuthology/task/selinux.py +17 -8
  95. teuthology/task/ssh_keys.py +6 -6
  96. teuthology/task/tests/__init__.py +137 -77
  97. teuthology/task/tests/test_fetch_coredumps.py +116 -0
  98. teuthology/task/tests/test_run.py +4 -4
  99. teuthology/timer.py +3 -3
  100. teuthology/util/loggerfile.py +19 -0
  101. teuthology/util/scanner.py +159 -0
  102. teuthology/util/sentry.py +52 -0
  103. teuthology/util/time.py +52 -0
  104. teuthology-1.2.0.data/scripts/adjust-ulimits +16 -0
  105. teuthology-1.2.0.data/scripts/daemon-helper +114 -0
  106. teuthology-1.2.0.data/scripts/stdin-killer +263 -0
  107. teuthology-1.2.0.dist-info/METADATA +89 -0
  108. teuthology-1.2.0.dist-info/RECORD +174 -0
  109. {teuthology-1.0.0.dist-info → teuthology-1.2.0.dist-info}/WHEEL +1 -1
  110. {teuthology-1.0.0.dist-info → teuthology-1.2.0.dist-info}/entry_points.txt +5 -2
  111. scripts/nuke.py +0 -45
  112. scripts/worker.py +0 -37
  113. teuthology/nuke/actions.py +0 -456
  114. teuthology/openstack/test/__init__.py +0 -0
  115. teuthology/openstack/test/openstack-integration.py +0 -286
  116. teuthology/openstack/test/test_config.py +0 -35
  117. teuthology/openstack/test/test_openstack.py +0 -1695
  118. teuthology/orchestra/test/__init__.py +0 -0
  119. teuthology/orchestra/test/integration/__init__.py +0 -0
  120. teuthology/orchestra/test/integration/test_integration.py +0 -94
  121. teuthology/orchestra/test/test_cluster.py +0 -240
  122. teuthology/orchestra/test/test_connection.py +0 -106
  123. teuthology/orchestra/test/test_console.py +0 -217
  124. teuthology/orchestra/test/test_opsys.py +0 -404
  125. teuthology/orchestra/test/test_remote.py +0 -185
  126. teuthology/orchestra/test/test_run.py +0 -286
  127. teuthology/orchestra/test/test_systemd.py +0 -54
  128. teuthology/orchestra/test/util.py +0 -12
  129. teuthology/sentry.py +0 -18
  130. teuthology/test/__init__.py +0 -0
  131. teuthology/test/fake_archive.py +0 -107
  132. teuthology/test/fake_fs.py +0 -92
  133. teuthology/test/integration/__init__.py +0 -0
  134. teuthology/test/integration/test_suite.py +0 -86
  135. teuthology/test/task/__init__.py +0 -205
  136. teuthology/test/task/test_ansible.py +0 -624
  137. teuthology/test/task/test_ceph_ansible.py +0 -176
  138. teuthology/test/task/test_console_log.py +0 -88
  139. teuthology/test/task/test_install.py +0 -337
  140. teuthology/test/task/test_internal.py +0 -57
  141. teuthology/test/task/test_kernel.py +0 -243
  142. teuthology/test/task/test_pcp.py +0 -379
  143. teuthology/test/task/test_selinux.py +0 -35
  144. teuthology/test/test_config.py +0 -189
  145. teuthology/test/test_contextutil.py +0 -68
  146. teuthology/test/test_describe_tests.py +0 -316
  147. teuthology/test/test_email_sleep_before_teardown.py +0 -81
  148. teuthology/test/test_exit.py +0 -97
  149. teuthology/test/test_get_distro.py +0 -47
  150. teuthology/test/test_get_distro_version.py +0 -47
  151. teuthology/test/test_get_multi_machine_types.py +0 -27
  152. teuthology/test/test_job_status.py +0 -60
  153. teuthology/test/test_ls.py +0 -48
  154. teuthology/test/test_misc.py +0 -368
  155. teuthology/test/test_nuke.py +0 -232
  156. teuthology/test/test_packaging.py +0 -763
  157. teuthology/test/test_parallel.py +0 -28
  158. teuthology/test/test_repo_utils.py +0 -204
  159. teuthology/test/test_report.py +0 -77
  160. teuthology/test/test_results.py +0 -155
  161. teuthology/test/test_run.py +0 -238
  162. teuthology/test/test_safepath.py +0 -55
  163. teuthology/test/test_schedule.py +0 -45
  164. teuthology/test/test_scrape.py +0 -167
  165. teuthology/test/test_timer.py +0 -80
  166. teuthology/test/test_vps_os_vers_parameter_checking.py +0 -84
  167. teuthology/test/test_worker.py +0 -303
  168. teuthology/worker.py +0 -339
  169. teuthology-1.0.0.dist-info/METADATA +0 -76
  170. teuthology-1.0.0.dist-info/RECORD +0 -210
  171. {teuthology-1.0.0.dist-info → teuthology-1.2.0.dist-info}/LICENSE +0 -0
  172. {teuthology-1.0.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