Merge ~adam-collard/maas:busy-wait-rack-controller-on-secret into maas:master

Proposed by Adam Collard
Status: Merged
Merge reported by: Alberto Donato
Merged at revision: 761d02c51b30e2fc8f15dd1c1ce5f43626fbb875
Proposed branch: ~adam-collard/maas:busy-wait-rack-controller-on-secret
Merge into: maas:master
Diff against target: 109 lines (+46/-3)
2 files modified
src/provisioningserver/plugin.py (+10/-2)
src/provisioningserver/tests/test_plugin.py (+36/-1)
Reviewer Review Type Date Requested Status
Lee Trager (community) Needs Information
MAAS Lander Needs Fixing
Review via email: mp+393461@code.launchpad.net

Commit message

LP: #1903318 - Sleep for up to 5 minutes waiting for the secret

When there's no secret on disk, block for up to 5 minutes waiting for
it before falling back on starting no services.

To post a comment you must log in.
Revision history for this message
Lee Trager (ltrager) wrote :

LGTM!

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

LANDING
-b busy-wait-rack-controller-on-secret lp:~adam-collard/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED BUILD
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/8640/consoleText

Revision history for this message
MAAS Lander (maas-lander) wrote :

UNIT TESTS
-b busy-wait-rack-controller-on-secret lp:~adam-collard/maas/+git/maas into -b master lp:~maas-committers/maas

STATUS: FAILED
LOG: http://maas-ci.internal:8080/job/maas/job/branch-tester/8641/console
COMMIT: 761d02c51b30e2fc8f15dd1c1ce5f43626fbb875

review: Needs Fixing
Revision history for this message
Lee Trager (ltrager) wrote :

See email

review: Needs Information
Revision history for this message
Lee Trager (ltrager) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/provisioningserver/plugin.py b/src/provisioningserver/plugin.py
2index 9bdda73..a38e279 100644
3--- a/src/provisioningserver/plugin.py
4+++ b/src/provisioningserver/plugin.py
5@@ -8,6 +8,7 @@ __all__ = ["Options", "ProvisioningServiceMaker"]
6 from errno import ENOPROTOOPT
7 import socket
8 from socket import error as socket_error
9+from time import sleep
10
11 from twisted.application.service import IServiceMaker
12 from twisted.internet import reactor
13@@ -23,6 +24,7 @@ from provisioningserver.monkey import (
14 )
15 from provisioningserver.prometheus.utils import clean_prometheus_dir
16 from provisioningserver.security import get_shared_secret_from_filesystem
17+from provisioningserver.utils.twisted import retries
18 from provisioningserver.utils.debug import (
19 register_sigusr1_toggle_cprofile,
20 register_sigusr2_thread_dump_handler,
21@@ -230,7 +232,7 @@ class ProvisioningServiceMaker:
22 # Get something going with the logs.
23 logger.configure(verbosity, logger.LoggingMode.TWISTD)
24
25- def makeService(self, options, clock=reactor):
26+ def makeService(self, options, clock=reactor, sleep=sleep):
27 """Construct the MAAS Cluster service."""
28 register_sigusr1_toggle_cprofile("rackd")
29 register_sigusr2_thread_dump_handler()
30@@ -252,7 +254,13 @@ class ProvisioningServiceMaker:
31
32 from provisioningserver import services
33
34- if get_shared_secret_from_filesystem():
35+ secret = None
36+ for elapsed, remaining, wait in retries(timeout=5 * 60, clock=clock):
37+ secret = get_shared_secret_from_filesystem()
38+ if secret is not None:
39+ break
40+ sleep(wait)
41+ if secret is not None:
42 # only setup services if the shared secret is configured
43 for service in self._makeServices(
44 tftp_root, tftp_port, clock=clock
45diff --git a/src/provisioningserver/tests/test_plugin.py b/src/provisioningserver/tests/test_plugin.py
46index db186e2..63e3c64 100644
47--- a/src/provisioningserver/tests/test_plugin.py
48+++ b/src/provisioningserver/tests/test_plugin.py
49@@ -6,6 +6,7 @@
50 __all__ = []
51
52 import os
53+from itertools import count
54 from pathlib import Path
55 from subprocess import Popen
56
57@@ -23,6 +24,7 @@ from testtools.matchers import (
58 )
59 from twisted.application.internet import StreamServerEndpointService
60 from twisted.application.service import MultiService
61+from twisted.internet.task import Clock
62
63 from maastesting.fixtures import TempDirectory
64 from maastesting.matchers import MockCalledOnceWith
65@@ -107,10 +109,43 @@ class TestProvisioningServiceMaker(MAASTestCase):
66 self.mock_get_shared_secret.return_value = None
67 service_maker = ProvisioningServiceMaker("foo", "bar")
68 self.patch(service_maker, "_loadSettings")
69- service = service_maker.makeService(Options(), clock=None)
70+ clock = Clock()
71+
72+ attempts = count()
73+
74+ def advance(seconds):
75+ next(attempts)
76+ clock.advance(seconds)
77+
78+ service = service_maker.makeService(
79+ Options(), clock=clock, sleep=advance
80+ )
81 self.assertIsInstance(service, MultiService)
82 self.assertEqual(service.namedServices, {})
83 self.mock_generate_certificate.assert_not_called()
84+ # All 300 attempts (e.g. 5 minutes) fail, next is 301
85+ self.assertEqual(next(attempts), 301)
86+
87+ def test_makeService_eventual_shared_secret(self):
88+ # First two times we look, there's no secret
89+ self.mock_get_shared_secret.side_effect = [None, None, "secret"]
90+ service_maker = ProvisioningServiceMaker("foo", "bar")
91+ self.patch(service_maker, "_loadSettings")
92+ clock = Clock()
93+
94+ attempts = count(1)
95+
96+ def advance(seconds):
97+ next(attempts)
98+ clock.advance(60)
99+
100+ service = service_maker.makeService(
101+ Options(), clock=clock, sleep=advance
102+ )
103+ self.assertIsInstance(service, MultiService)
104+ self.assertNotEqual(service.namedServices, {})
105+ # First two fail, the third one succeeds
106+ self.assertEqual(next(attempts), 3)
107
108 def test_makeService_not_in_debug(self):
109 """

Subscribers

People subscribed via source and target branches