Merge lp:~julian-edwards/maas/revert-2819 into lp:~maas-committers/maas/trunk
- revert-2819
- Merge into trunk
Proposed by
Julian Edwards
Status: | Merged |
---|---|
Approved by: | Julian Edwards |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2822 |
Proposed branch: | lp:~julian-edwards/maas/revert-2819 |
Merge into: | lp:~maas-committers/maas/trunk |
Diff against target: |
468 lines (+62/-254) 8 files modified
etc/celeryconfig_cluster.py (+8/-0) src/provisioningserver/dhcp/detect.py (+26/-8) src/provisioningserver/dhcp/dhcp_probe_service.py (+0/-85) src/provisioningserver/dhcp/tests/test_detect.py (+13/-4) src/provisioningserver/dhcp/tests/test_dhcp_probe_service.py (+0/-128) src/provisioningserver/plugin.py (+0/-12) src/provisioningserver/tasks.py (+12/-1) src/provisioningserver/tests/test_plugin.py (+3/-16) |
To merge this branch: | bzr merge lp:~julian-edwards/maas/revert-2819 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Julian Edwards (community) | selfie | Approve | |
Review via email:
|
Commit message
Revert r2819 (pserv-based dhcp probing service), which could never work as it was using API credentials that are not sent to pserv.
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Julian Edwards (julian-edwards) : | # |
review:
Approve
(selfie)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'etc/celeryconfig_cluster.py' | |||
2 | --- etc/celeryconfig_cluster.py 2014-08-22 14:47:15 +0000 | |||
3 | +++ etc/celeryconfig_cluster.py 2014-08-26 23:57:04 +0000 | |||
4 | @@ -56,4 +56,12 @@ | |||
5 | 56 | 'expires': int(REPORT_BOOT_IMAGES_SCHEDULE.total_seconds()), | 56 | 'expires': int(REPORT_BOOT_IMAGES_SCHEDULE.total_seconds()), |
6 | 57 | }, | 57 | }, |
7 | 58 | }, | 58 | }, |
8 | 59 | 'probe-dhcp-servers': { | ||
9 | 60 | 'task': 'provisioningserver.tasks.periodic_probe_dhcp', | ||
10 | 61 | 'schedule': PROBE_DHCP_SERVERS_SCHEDULE, | ||
11 | 62 | 'options': { | ||
12 | 63 | 'queue': CLUSTER_UUID, | ||
13 | 64 | 'expires': int(PROBE_DHCP_SERVERS_SCHEDULE.total_seconds()), | ||
14 | 65 | }, | ||
15 | 66 | }, | ||
16 | 59 | } | 67 | } |
17 | 60 | 68 | ||
18 | === modified file 'src/provisioningserver/dhcp/detect.py' | |||
19 | --- src/provisioningserver/dhcp/detect.py 2014-08-26 10:19:58 +0000 | |||
20 | +++ src/provisioningserver/dhcp/detect.py 2014-08-26 23:57:04 +0000 | |||
21 | @@ -33,6 +33,11 @@ | |||
22 | 33 | MAASDispatcher, | 33 | MAASDispatcher, |
23 | 34 | MAASOAuth, | 34 | MAASOAuth, |
24 | 35 | ) | 35 | ) |
25 | 36 | from provisioningserver.auth import ( | ||
26 | 37 | get_recorded_api_credentials, | ||
27 | 38 | get_recorded_nodegroup_uuid, | ||
28 | 39 | ) | ||
29 | 40 | from provisioningserver.cluster_config import get_maas_url | ||
30 | 36 | from provisioningserver.logger import get_maas_logger | 41 | from provisioningserver.logger import get_maas_logger |
31 | 37 | 42 | ||
32 | 38 | 43 | ||
33 | @@ -316,7 +321,7 @@ | |||
34 | 316 | client.post, api_path, 'report_foreign_dhcp', foreign_dhcp_ip=server) | 321 | client.post, api_path, 'report_foreign_dhcp', foreign_dhcp_ip=server) |
35 | 317 | 322 | ||
36 | 318 | 323 | ||
38 | 319 | def periodic_probe_task(api_knowledge): | 324 | def periodic_probe_task(): |
39 | 320 | """Probe for DHCP servers and set NodeGroupInterface.foriegn_dhcp. | 325 | """Probe for DHCP servers and set NodeGroupInterface.foriegn_dhcp. |
40 | 321 | 326 | ||
41 | 322 | This should be run periodically so that the database has an up-to-date | 327 | This should be run periodically so that the database has an up-to-date |
42 | @@ -325,12 +330,26 @@ | |||
43 | 325 | NOTE: This uses blocking I/O with sequential polling of interfaces, and | 330 | NOTE: This uses blocking I/O with sequential polling of interfaces, and |
44 | 326 | hence doesn't scale well. It's a future improvement to make | 331 | hence doesn't scale well. It's a future improvement to make |
45 | 327 | to throw it in parallel threads or async I/O. | 332 | to throw it in parallel threads or async I/O. |
46 | 328 | |||
47 | 329 | :param api_knowledge: A dict of the information needed to be able to | ||
48 | 330 | make requests to the region's REST API. | ||
49 | 331 | """ | 333 | """ |
50 | 334 | # Items that the server must have sent us before we can do this. | ||
51 | 335 | knowledge = { | ||
52 | 336 | 'maas_url': get_maas_url(), | ||
53 | 337 | 'api_credentials': get_recorded_api_credentials(), | ||
54 | 338 | 'nodegroup_uuid': get_recorded_nodegroup_uuid(), | ||
55 | 339 | } | ||
56 | 340 | |||
57 | 341 | if None in knowledge.values(): | ||
58 | 342 | # The MAAS server hasn't sent us enough information for us to do | ||
59 | 343 | # this yet. Leave it for another time. | ||
60 | 344 | maaslog.info( | ||
61 | 345 | "Not probing for rogue DHCP servers; not all required knowledge " | ||
62 | 346 | "received from server yet. " | ||
63 | 347 | "Missing: %s" % ', '.join(sorted( | ||
64 | 348 | name for name, value in knowledge.items() if value is None))) | ||
65 | 349 | return | ||
66 | 350 | |||
67 | 332 | # Determine all the active interfaces on this cluster (nodegroup). | 351 | # Determine all the active interfaces on this cluster (nodegroup). |
69 | 333 | interfaces = determine_cluster_interfaces(api_knowledge) | 352 | interfaces = determine_cluster_interfaces(knowledge) |
70 | 334 | if interfaces is None: | 353 | if interfaces is None: |
71 | 335 | maaslog.info("No interfaces on cluster, not probing DHCP.") | 354 | maaslog.info("No interfaces on cluster, not probing DHCP.") |
72 | 336 | return | 355 | return |
73 | @@ -349,7 +368,6 @@ | |||
74 | 349 | # Only send one, if it gets cleared out then the | 368 | # Only send one, if it gets cleared out then the |
75 | 350 | # next detection pass will send a different one, if it | 369 | # next detection pass will send a different one, if it |
76 | 351 | # still exists. | 370 | # still exists. |
79 | 352 | update_region_controller( | 371 | update_region_controller(knowledge, interface, servers.pop()) |
78 | 353 | api_knowledge, interface, servers.pop()) | ||
80 | 354 | else: | 372 | else: |
82 | 355 | update_region_controller(api_knowledge, interface, None) | 373 | update_region_controller(knowledge, interface, None) |
83 | 356 | 374 | ||
84 | === removed file 'src/provisioningserver/dhcp/dhcp_probe_service.py' | |||
85 | --- src/provisioningserver/dhcp/dhcp_probe_service.py 2014-08-26 15:47:52 +0000 | |||
86 | +++ src/provisioningserver/dhcp/dhcp_probe_service.py 1970-01-01 00:00:00 +0000 | |||
87 | @@ -1,85 +0,0 @@ | |||
88 | 1 | # Copyright 2014 Canonical Ltd. This software is licensed under the | ||
89 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
90 | 3 | |||
91 | 4 | """Periodic DHCP probing service.""" | ||
92 | 5 | |||
93 | 6 | from __future__ import ( | ||
94 | 7 | absolute_import, | ||
95 | 8 | print_function, | ||
96 | 9 | unicode_literals, | ||
97 | 10 | ) | ||
98 | 11 | |||
99 | 12 | str = None | ||
100 | 13 | |||
101 | 14 | __metaclass__ = type | ||
102 | 15 | __all__ = [ | ||
103 | 16 | "PeriodicDHCPProbeService", | ||
104 | 17 | ] | ||
105 | 18 | |||
106 | 19 | |||
107 | 20 | from datetime import timedelta | ||
108 | 21 | |||
109 | 22 | from provisioningserver.auth import get_recorded_api_credentials | ||
110 | 23 | from provisioningserver.cluster_config import get_maas_url | ||
111 | 24 | from provisioningserver.dhcp import detect | ||
112 | 25 | from provisioningserver.logger.log import get_maas_logger | ||
113 | 26 | from twisted.application.internet import TimerService | ||
114 | 27 | from twisted.internet.defer import inlineCallbacks | ||
115 | 28 | from twisted.internet.threads import deferToThread | ||
116 | 29 | |||
117 | 30 | |||
118 | 31 | maaslog = get_maas_logger("dhcp.probe") | ||
119 | 32 | |||
120 | 33 | |||
121 | 34 | class PeriodicDHCPProbeService(TimerService, object): | ||
122 | 35 | """Service to probe for DHCP servers on this cluster's network. | ||
123 | 36 | |||
124 | 37 | Built on top of Twisted's `TimerService`. | ||
125 | 38 | |||
126 | 39 | :param reactor: An `IReactor` instance. | ||
127 | 40 | :param cluster_uuid: This cluster's UUID. | ||
128 | 41 | """ | ||
129 | 42 | |||
130 | 43 | check_interval = timedelta(minutes=1).total_seconds() | ||
131 | 44 | |||
132 | 45 | def __init__(self, reactor, cluster_uuid): | ||
133 | 46 | # Call self.check() every self.check_interval. | ||
134 | 47 | super(PeriodicDHCPProbeService, self).__init__( | ||
135 | 48 | self.check_interval, self.try_probe_dhcp) | ||
136 | 49 | self.clock = reactor | ||
137 | 50 | self.uuid = cluster_uuid | ||
138 | 51 | |||
139 | 52 | def _probe_dhcp(self, knowledge): | ||
140 | 53 | """Probe for DHCP servers.""" | ||
141 | 54 | return deferToThread(detect.periodic_probe_task, knowledge) | ||
142 | 55 | |||
143 | 56 | @inlineCallbacks | ||
144 | 57 | def try_probe_dhcp(self): | ||
145 | 58 | # Items that the server must have sent us before we can do | ||
146 | 59 | # this. | ||
147 | 60 | knowledge = { | ||
148 | 61 | 'api_credentials': get_recorded_api_credentials(), | ||
149 | 62 | 'maas_url': get_maas_url(), | ||
150 | 63 | 'nodegroup_uuid': self.uuid, | ||
151 | 64 | } | ||
152 | 65 | |||
153 | 66 | if None in knowledge.values(): | ||
154 | 67 | # The MAAS server hasn't sent us enough information for | ||
155 | 68 | # us to do this yet. Leave it for another time. | ||
156 | 69 | maaslog.info( | ||
157 | 70 | "Not probing for rogue DHCP servers; not all " | ||
158 | 71 | "required knowledge received from server yet. " | ||
159 | 72 | "Missing: %s" % ', '.join(sorted( | ||
160 | 73 | name for name, value in knowledge.items() | ||
161 | 74 | if value is None))) | ||
162 | 75 | return | ||
163 | 76 | else: | ||
164 | 77 | maaslog.debug("Running periodic DHCP probe.") | ||
165 | 78 | try: | ||
166 | 79 | d = self._probe_dhcp(knowledge) | ||
167 | 80 | yield d | ||
168 | 81 | maaslog.debug("Finished periodic DHCP probe.") | ||
169 | 82 | except Exception as error: | ||
170 | 83 | maaslog.error( | ||
171 | 84 | "Unable to probe for rogue DHCP servers: %s" | ||
172 | 85 | % unicode(error)) | ||
173 | 86 | 0 | ||
174 | === modified file 'src/provisioningserver/dhcp/tests/test_detect.py' | |||
175 | --- src/provisioningserver/dhcp/tests/test_detect.py 2014-08-26 10:19:58 +0000 | |||
176 | +++ src/provisioningserver/dhcp/tests/test_detect.py 2014-08-26 23:57:04 +0000 | |||
177 | @@ -30,7 +30,10 @@ | |||
178 | 30 | from maastesting.testcase import MAASTestCase | 30 | from maastesting.testcase import MAASTestCase |
179 | 31 | import mock | 31 | import mock |
180 | 32 | from provisioningserver import cache | 32 | from provisioningserver import cache |
182 | 33 | from provisioningserver.auth import NODEGROUP_UUID_CACHE_KEY | 33 | from provisioningserver.auth import ( |
183 | 34 | NODEGROUP_UUID_CACHE_KEY, | ||
184 | 35 | record_api_credentials, | ||
185 | 36 | ) | ||
186 | 34 | from provisioningserver.dhcp.detect import ( | 37 | from provisioningserver.dhcp.detect import ( |
187 | 35 | BOOTP_CLIENT_PORT, | 38 | BOOTP_CLIENT_PORT, |
188 | 36 | BOOTP_SERVER_PORT, | 39 | BOOTP_SERVER_PORT, |
189 | @@ -510,11 +513,17 @@ | |||
190 | 510 | "Failed talking to region controller, it returned:", | 513 | "Failed talking to region controller, it returned:", |
191 | 511 | self.maaslog.output) | 514 | self.maaslog.output) |
192 | 512 | 515 | ||
193 | 516 | def test_periodic_probe_task_exits_with_not_enough_knowledge(self): | ||
194 | 517 | mocked = self.patch(detect_module, 'determine_cluster_interfaces') | ||
195 | 518 | record_api_credentials(None) | ||
196 | 519 | periodic_probe_task() | ||
197 | 520 | self.assertFalse(mocked.called) | ||
198 | 521 | |||
199 | 513 | def test_periodic_probe_task_exits_if_no_interfaces(self): | 522 | def test_periodic_probe_task_exits_if_no_interfaces(self): |
200 | 514 | mocked = self.patch(detect_module, 'probe_interface') | 523 | mocked = self.patch(detect_module, 'probe_interface') |
201 | 515 | self.patch( | 524 | self.patch( |
202 | 516 | detect_module, 'determine_cluster_interfaces').return_value = None | 525 | detect_module, 'determine_cluster_interfaces').return_value = None |
204 | 517 | periodic_probe_task(self.knowledge) | 526 | periodic_probe_task() |
205 | 518 | self.assertFalse(mocked.called) | 527 | self.assertFalse(mocked.called) |
206 | 519 | 528 | ||
207 | 520 | def test_periodic_probe_task_updates_region_with_detected_server(self): | 529 | def test_periodic_probe_task_updates_region_with_detected_server(self): |
208 | @@ -526,7 +535,7 @@ | |||
209 | 526 | self.patch( | 535 | self.patch( |
210 | 527 | detect_module, 'probe_dhcp').return_value = {detected_server} | 536 | detect_module, 'probe_dhcp').return_value = {detected_server} |
211 | 528 | mocked_update = self.patch(detect_module, 'update_region_controller') | 537 | mocked_update = self.patch(detect_module, 'update_region_controller') |
213 | 529 | periodic_probe_task(self.knowledge) | 538 | periodic_probe_task() |
214 | 530 | calls = [ | 539 | calls = [ |
215 | 531 | mock.call(self.knowledge, 'eth0', detected_server), | 540 | mock.call(self.knowledge, 'eth0', detected_server), |
216 | 532 | mock.call(self.knowledge, 'wlan0', detected_server), | 541 | mock.call(self.knowledge, 'wlan0', detected_server), |
217 | @@ -541,7 +550,7 @@ | |||
218 | 541 | self.patch( | 550 | self.patch( |
219 | 542 | detect_module, 'probe_dhcp').return_value = set() | 551 | detect_module, 'probe_dhcp').return_value = set() |
220 | 543 | mocked_update = self.patch(detect_module, 'update_region_controller') | 552 | mocked_update = self.patch(detect_module, 'update_region_controller') |
222 | 544 | periodic_probe_task(self.knowledge) | 553 | periodic_probe_task() |
223 | 545 | calls = [ | 554 | calls = [ |
224 | 546 | mock.call(self.knowledge, 'eth0', None), | 555 | mock.call(self.knowledge, 'eth0', None), |
225 | 547 | mock.call(self.knowledge, 'wlan0', None), | 556 | mock.call(self.knowledge, 'wlan0', None), |
226 | 548 | 557 | ||
227 | === removed file 'src/provisioningserver/dhcp/tests/test_dhcp_probe_service.py' | |||
228 | --- src/provisioningserver/dhcp/tests/test_dhcp_probe_service.py 2014-08-26 15:45:21 +0000 | |||
229 | +++ src/provisioningserver/dhcp/tests/test_dhcp_probe_service.py 1970-01-01 00:00:00 +0000 | |||
230 | @@ -1,128 +0,0 @@ | |||
231 | 1 | # Copyright 2014 Canonical Ltd. This software is licensed under the | ||
232 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
233 | 3 | |||
234 | 4 | """Tests for periodic DHCP prober.""" | ||
235 | 5 | |||
236 | 6 | from __future__ import ( | ||
237 | 7 | absolute_import, | ||
238 | 8 | print_function, | ||
239 | 9 | unicode_literals, | ||
240 | 10 | ) | ||
241 | 11 | |||
242 | 12 | str = None | ||
243 | 13 | |||
244 | 14 | __metaclass__ = type | ||
245 | 15 | __all__ = [] | ||
246 | 16 | |||
247 | 17 | import os | ||
248 | 18 | |||
249 | 19 | from apiclient.testing.credentials import make_api_credentials | ||
250 | 20 | from maastesting.factory import factory | ||
251 | 21 | from maastesting.matchers import ( | ||
252 | 22 | get_mock_calls, | ||
253 | 23 | HasLength, | ||
254 | 24 | MockCalledOnceWith, | ||
255 | 25 | MockNotCalled, | ||
256 | 26 | ) | ||
257 | 27 | from mock import ANY | ||
258 | 28 | from provisioningserver import cache | ||
259 | 29 | from provisioningserver.auth import ( | ||
260 | 30 | NODEGROUP_UUID_CACHE_KEY, | ||
261 | 31 | record_api_credentials, | ||
262 | 32 | ) | ||
263 | 33 | from provisioningserver.dhcp import dhcp_probe_service | ||
264 | 34 | from provisioningserver.dhcp.dhcp_probe_service import ( | ||
265 | 35 | PeriodicDHCPProbeService, | ||
266 | 36 | ) | ||
267 | 37 | from provisioningserver.testing.testcase import PservTestCase | ||
268 | 38 | from testtools.deferredruntest import AsynchronousDeferredRunTest | ||
269 | 39 | from twisted.internet import defer | ||
270 | 40 | from twisted.internet.task import Clock | ||
271 | 41 | |||
272 | 42 | |||
273 | 43 | class TestDHCPProbeService(PservTestCase): | ||
274 | 44 | |||
275 | 45 | run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=5) | ||
276 | 46 | |||
277 | 47 | def setUp(self): | ||
278 | 48 | super(TestDHCPProbeService, self).setUp() | ||
279 | 49 | self.cluster_uuid = factory.make_UUID() | ||
280 | 50 | maas_url = 'http://%s.example.com/%s/' % ( | ||
281 | 51 | factory.make_name('host'), | ||
282 | 52 | factory.make_string(), | ||
283 | 53 | ) | ||
284 | 54 | api_credentials = make_api_credentials() | ||
285 | 55 | |||
286 | 56 | cache.cache.set(NODEGROUP_UUID_CACHE_KEY, self.cluster_uuid) | ||
287 | 57 | os.environ["MAAS_URL"] = maas_url | ||
288 | 58 | cache.cache.set('api_credentials', ':'.join(api_credentials)) | ||
289 | 59 | |||
290 | 60 | self.knowledge = dict( | ||
291 | 61 | api_credentials=api_credentials, | ||
292 | 62 | maas_url=maas_url, | ||
293 | 63 | nodegroup_uuid=self.cluster_uuid) | ||
294 | 64 | |||
295 | 65 | def test_is_called_every_interval(self): | ||
296 | 66 | clock = Clock() | ||
297 | 67 | service = PeriodicDHCPProbeService(clock, self.cluster_uuid) | ||
298 | 68 | |||
299 | 69 | # Avoid actually probing | ||
300 | 70 | _probe_dhcp = self.patch(service, '_probe_dhcp') | ||
301 | 71 | |||
302 | 72 | # Until the service has started, periodic_probe_dhcp() won't | ||
303 | 73 | # be called. | ||
304 | 74 | self.assertThat(_probe_dhcp, MockNotCalled()) | ||
305 | 75 | |||
306 | 76 | # The first call is issued at startup. | ||
307 | 77 | service.startService() | ||
308 | 78 | self.assertThat(_probe_dhcp, MockCalledOnceWith(ANY)) | ||
309 | 79 | |||
310 | 80 | # Wind clock forward one second less than the desired interval. | ||
311 | 81 | clock.advance(service.check_interval - 1) | ||
312 | 82 | |||
313 | 83 | # No more periodic calls made. | ||
314 | 84 | self.assertEqual(1, len(get_mock_calls(_probe_dhcp))) | ||
315 | 85 | |||
316 | 86 | # Wind clock forward one second, past the interval. | ||
317 | 87 | clock.advance(1) | ||
318 | 88 | |||
319 | 89 | # Now there were two calls. | ||
320 | 90 | self.assertThat(get_mock_calls(_probe_dhcp), HasLength(2)) | ||
321 | 91 | |||
322 | 92 | def test_download_is_initiated_in_new_thread(self): | ||
323 | 93 | clock = Clock() | ||
324 | 94 | |||
325 | 95 | # We could patch out 'periodic_probe_task' instead here but this | ||
326 | 96 | # is better because: | ||
327 | 97 | # 1. The former requires spinning the reactor again before being | ||
328 | 98 | # able to test the result. | ||
329 | 99 | # 2. This way there's no thread to clean up after the test. | ||
330 | 100 | deferToThread = self.patch(dhcp_probe_service, 'deferToThread') | ||
331 | 101 | deferToThread.return_value = defer.succeed(None) | ||
332 | 102 | service = PeriodicDHCPProbeService(clock, self.cluster_uuid) | ||
333 | 103 | service.startService() | ||
334 | 104 | self.assertThat( | ||
335 | 105 | deferToThread, MockCalledOnceWith( | ||
336 | 106 | dhcp_probe_service.detect.periodic_probe_task, | ||
337 | 107 | self.knowledge)) | ||
338 | 108 | |||
339 | 109 | def test_no_probe_if_api_credentials_not_set(self): | ||
340 | 110 | record_api_credentials(None) | ||
341 | 111 | clock = Clock() | ||
342 | 112 | service = PeriodicDHCPProbeService(clock, self.cluster_uuid) | ||
343 | 113 | _probe_dhcp = self.patch(service, '_probe_dhcp') | ||
344 | 114 | service.startService() | ||
345 | 115 | self.assertThat(_probe_dhcp, MockNotCalled()) | ||
346 | 116 | |||
347 | 117 | def test_logs_errors(self): | ||
348 | 118 | clock = Clock() | ||
349 | 119 | maaslog = self.patch(dhcp_probe_service, 'maaslog') | ||
350 | 120 | service = PeriodicDHCPProbeService(clock, self.cluster_uuid) | ||
351 | 121 | error_message = factory.make_string() | ||
352 | 122 | self.patch(service, '_probe_dhcp').side_effect = Exception( | ||
353 | 123 | error_message) | ||
354 | 124 | service.startService() | ||
355 | 125 | self.assertThat( | ||
356 | 126 | maaslog.error, MockCalledOnceWith( | ||
357 | 127 | "Unable to probe for rogue DHCP servers: %s" % | ||
358 | 128 | error_message)) | ||
359 | 129 | 0 | ||
360 | === modified file 'src/provisioningserver/plugin.py' | |||
361 | --- src/provisioningserver/plugin.py 2014-08-26 17:23:16 +0000 | |||
362 | +++ src/provisioningserver/plugin.py 2014-08-26 23:57:04 +0000 | |||
363 | @@ -31,9 +31,6 @@ | |||
364 | 31 | import provisioningserver | 31 | import provisioningserver |
365 | 32 | from provisioningserver.cluster_config import get_cluster_uuid | 32 | from provisioningserver.cluster_config import get_cluster_uuid |
366 | 33 | from provisioningserver.config import Config | 33 | from provisioningserver.config import Config |
367 | 34 | from provisioningserver.dhcp.dhcp_probe_service import ( | ||
368 | 35 | PeriodicDHCPProbeService, | ||
369 | 36 | ) | ||
370 | 37 | from provisioningserver.rpc.boot_images import PeriodicImageDownloadService | 34 | from provisioningserver.rpc.boot_images import PeriodicImageDownloadService |
371 | 38 | from provisioningserver.rpc.clusterservice import ClusterClientService | 35 | from provisioningserver.rpc.clusterservice import ClusterClientService |
372 | 39 | from provisioningserver.rpc.power import NodePowerMonitorService | 36 | from provisioningserver.rpc.power import NodePowerMonitorService |
373 | @@ -242,12 +239,6 @@ | |||
374 | 242 | rpc_service.setName("rpc") | 239 | rpc_service.setName("rpc") |
375 | 243 | return rpc_service | 240 | return rpc_service |
376 | 244 | 241 | ||
377 | 245 | def _makePeriodicDHCPProbeService(self, rpc_service): | ||
378 | 246 | dhcp_probe_service = PeriodicDHCPProbeService( | ||
379 | 247 | reactor, get_cluster_uuid()) | ||
380 | 248 | dhcp_probe_service.setName("dhcp_probe") | ||
381 | 249 | return dhcp_probe_service | ||
382 | 250 | |||
383 | 251 | def makeService(self, options): | 242 | def makeService(self, options): |
384 | 252 | """Construct a service.""" | 243 | """Construct a service.""" |
385 | 253 | services = provisioningserver.services | 244 | services = provisioningserver.services |
386 | @@ -272,7 +263,4 @@ | |||
387 | 272 | rpc_service) | 263 | rpc_service) |
388 | 273 | image_download_service.setServiceParent(services) | 264 | image_download_service.setServiceParent(services) |
389 | 274 | 265 | ||
390 | 275 | dhcp_probe_service = self._makePeriodicDHCPProbeService(rpc_service) | ||
391 | 276 | dhcp_probe_service.setServiceParent(services) | ||
392 | 277 | |||
393 | 278 | return services | 266 | return services |
394 | 279 | 267 | ||
395 | === modified file 'src/provisioningserver/tasks.py' | |||
396 | --- src/provisioningserver/tasks.py 2014-08-26 10:23:23 +0000 | |||
397 | +++ src/provisioningserver/tasks.py 2014-08-26 23:57:04 +0000 | |||
398 | @@ -43,7 +43,10 @@ | |||
399 | 43 | record_api_credentials, | 43 | record_api_credentials, |
400 | 44 | record_nodegroup_uuid, | 44 | record_nodegroup_uuid, |
401 | 45 | ) | 45 | ) |
403 | 46 | from provisioningserver.dhcp import config | 46 | from provisioningserver.dhcp import ( |
404 | 47 | config, | ||
405 | 48 | detect, | ||
406 | 49 | ) | ||
407 | 47 | from provisioningserver.dhcp.control import ( | 50 | from provisioningserver.dhcp.control import ( |
408 | 48 | restart_dhcpv4, | 51 | restart_dhcpv4, |
409 | 49 | stop_dhcpv4, | 52 | stop_dhcpv4, |
410 | @@ -445,6 +448,14 @@ | |||
411 | 445 | raise | 448 | raise |
412 | 446 | 449 | ||
413 | 447 | 450 | ||
414 | 451 | @task | ||
415 | 452 | @log_task_events(level=logging.DEBUG) | ||
416 | 453 | @log_exception_text | ||
417 | 454 | def periodic_probe_dhcp(): | ||
418 | 455 | """Probe for foreign DHCP servers.""" | ||
419 | 456 | detect.periodic_probe_task() | ||
420 | 457 | |||
421 | 458 | |||
422 | 448 | # ===================================================================== | 459 | # ===================================================================== |
423 | 449 | # Boot images-related tasks | 460 | # Boot images-related tasks |
424 | 450 | # ===================================================================== | 461 | # ===================================================================== |
425 | 451 | 462 | ||
426 | === modified file 'src/provisioningserver/tests/test_plugin.py' | |||
427 | --- src/provisioningserver/tests/test_plugin.py 2014-08-26 17:23:16 +0000 | |||
428 | +++ src/provisioningserver/tests/test_plugin.py 2014-08-26 23:57:04 +0000 | |||
429 | @@ -21,9 +21,6 @@ | |||
430 | 21 | from maastesting.testcase import MAASTestCase | 21 | from maastesting.testcase import MAASTestCase |
431 | 22 | import provisioningserver | 22 | import provisioningserver |
432 | 23 | from provisioningserver import plugin as plugin_module | 23 | from provisioningserver import plugin as plugin_module |
433 | 24 | from provisioningserver.dhcp.dhcp_probe_service import ( | ||
434 | 25 | PeriodicDHCPProbeService, | ||
435 | 26 | ) | ||
436 | 27 | from provisioningserver.plugin import ( | 24 | from provisioningserver.plugin import ( |
437 | 28 | Options, | 25 | Options, |
438 | 29 | ProvisioningRealm, | 26 | ProvisioningRealm, |
439 | @@ -112,11 +109,9 @@ | |||
440 | 112 | service_maker = ProvisioningServiceMaker("Harry", "Hill") | 109 | service_maker = ProvisioningServiceMaker("Harry", "Hill") |
441 | 113 | service = service_maker.makeService(options) | 110 | service = service_maker.makeService(options) |
442 | 114 | self.assertIsInstance(service, MultiService) | 111 | self.assertIsInstance(service, MultiService) |
448 | 115 | expected_services = [ | 112 | self.assertSequenceEqual( |
449 | 116 | "dhcp_probe", "image_download", "log", "node_monitor", | 113 | ["image_download", "log", "node_monitor", "oops", "rpc", "tftp"], |
450 | 117 | "oops", "rpc", "tftp", | 114 | sorted(service.namedServices)) |
446 | 118 | ] | ||
447 | 119 | self.assertItemsEqual(expected_services, service.namedServices) | ||
451 | 120 | self.assertEqual( | 115 | self.assertEqual( |
452 | 121 | len(service.namedServices), len(service.services), | 116 | len(service.namedServices), len(service.services), |
453 | 122 | "Not all services are named.") | 117 | "Not all services are named.") |
454 | @@ -138,14 +133,6 @@ | |||
455 | 138 | node_monitor = service.getServiceNamed("node_monitor") | 133 | node_monitor = service.getServiceNamed("node_monitor") |
456 | 139 | self.assertIsInstance(node_monitor, NodePowerMonitorService) | 134 | self.assertIsInstance(node_monitor, NodePowerMonitorService) |
457 | 140 | 135 | ||
458 | 141 | def test_dhcp_probe_service(self): | ||
459 | 142 | options = Options() | ||
460 | 143 | options["config-file"] = self.write_config({}) | ||
461 | 144 | service_maker = ProvisioningServiceMaker("Spike", "Milligan") | ||
462 | 145 | service = service_maker.makeService(options) | ||
463 | 146 | dhcp_probe = service.getServiceNamed("dhcp_probe") | ||
464 | 147 | self.assertIsInstance(dhcp_probe, PeriodicDHCPProbeService) | ||
465 | 148 | |||
466 | 149 | def test_tftp_service(self): | 136 | def test_tftp_service(self): |
467 | 150 | # A TFTP service is configured and added to the top-level service. | 137 | # A TFTP service is configured and added to the top-level service. |
468 | 151 | config = { | 138 | config = { |