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