Merge lp:~fcorrea/landscape-client/wait-for-valid-session-id-on-resynchronize into lp:~landscape/landscape-client/trunk

Proposed by Fernando Correa Neto
Status: Merged
Approved by: Fernando Correa Neto
Approved revision: 829
Merged at revision: 826
Proposed branch: lp:~fcorrea/landscape-client/wait-for-valid-session-id-on-resynchronize
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 249 lines (+64/-25)
4 files modified
landscape/broker/client.py (+2/-2)
landscape/broker/tests/test_client.py (+11/-0)
landscape/monitor/tests/test_usermonitor.py (+44/-20)
landscape/monitor/usermonitor.py (+7/-3)
To merge this branch: bzr merge lp:~fcorrea/landscape-client/wait-for-valid-session-id-on-resynchronize
Reviewer Review Type Date Requested Status
Chad Smith Approve
Free Ekanayaka (community) Approve
Benji York (community) Approve
Review via email: mp+282483@code.launchpad.net

Commit message

Changes the user monitor plugin to wait on a valid session id.

Description of the change

With the scope resync work, the user monitor plugin stopped working.
Since now we rely on a valid session id in order to send a message to the server, the user monitor plugin must wait until it gets a valid session.
The fix was provided by Free and a test and some cleanups were added as well.

To post a comment you must log in.
Revision history for this message
Benji York (benji) wrote :

Thanks for the branch, it looks good.

review: Approve
Revision history for this message
Free Ekanayaka (free.ekanayaka) :
review: Needs Fixing
828. By Fernando Correa Neto

- fix the unit test so it can actually fail if the fix is removed.
- improve test coveration for BrokerClientPlugin base class

Revision history for this message
Fernando Correa Neto (fcorrea) wrote :

Free

Thanks for reviewing it.
I've changed the test as we discussed to make sure it will fail when the fix is reverted. Please, take a look.

Revision history for this message
Free Ekanayaka (free.ekanayaka) wrote :

+1 with a nit

review: Approve
829. By Fernando Correa Neto

- rename test and address review comment

Revision history for this message
Fernando Correa Neto (fcorrea) :
Revision history for this message
Chad Smith (chad.smith) wrote :

Good work here and additional unit tests. It took a while for me to go through upgrade path testing w/ broken released client TO patched trunk client.

Looks like a plain upgrade of a broken existing released client will still sit missing the initial delta of all system users. But, those broken clients will properly send any users or groups that were modified after the initial registration of that client.

To truly "fix" the broken clients, the customer would have to upgrade landscape-client and click the resynch button for that computer as a support person.

+1. This was tough.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'landscape/broker/client.py'
2--- landscape/broker/client.py 2013-07-25 13:54:29 +0000
3+++ landscape/broker/client.py 2016-01-15 16:29:39 +0000
4@@ -1,6 +1,6 @@
5 from logging import info, exception
6
7-from twisted.internet.defer import maybeDeferred
8+from twisted.internet.defer import maybeDeferred, succeed
9
10 from landscape.log import format_object
11 from landscape.lib.twisted_util import gather_results
12@@ -67,7 +67,7 @@
13 """
14 if not (scopes is None or self.scope in scopes):
15 # This resynchronize event is out of scope for us. Do nothing
16- return
17+ return succeed(None)
18
19 # Because the broker will drop session IDs already associated to scope
20 # of the resynchronisation, it isn't safe to send messages until the
21
22=== modified file 'landscape/broker/tests/test_client.py'
23--- landscape/broker/tests/test_client.py 2013-07-19 09:57:57 +0000
24+++ landscape/broker/tests/test_client.py 2016-01-15 16:29:39 +0000
25@@ -47,6 +47,17 @@
26 self.client.add(plugin)
27 self.assertEqual(test_session_id, plugin._session_id)
28
29+ def test_resynchronizing_out_of_scope(self):
30+ """
31+ When a 'reysnchronize' event happens and the plugin scope is not part
32+ of the scopes that were passed, BrokerClientPlugin succeeds.
33+ """
34+ plugin = BrokerClientPlugin()
35+ plugin.scope = "foo"
36+ self.client.add(plugin)
37+ deferred = self.client_reactor.fire("resynchronize", scopes=["bar"])[0]
38+ self.assertIsNone(self.successResultOf(deferred))
39+
40 def test_resynchronizing_refreshes_session_id(self):
41 """
42 When a 'reysnchronize' event fires a new session ID is acquired as the
43
44=== modified file 'landscape/monitor/tests/test_usermonitor.py'
45--- landscape/monitor/tests/test_usermonitor.py 2016-01-11 18:34:49 +0000
46+++ landscape/monitor/tests/test_usermonitor.py 2016-01-15 16:29:39 +0000
47@@ -23,13 +23,13 @@
48 def got_result(result):
49 self.assertMessages(
50 self.broker_service.message_store.get_pending_messages(),
51- [{"create-group-members": {u"webdev":[u"jdoe"]},
52+ [{"create-group-members": {u"webdev": [u"jdoe"]},
53 "create-groups": [{"gid": 1000, "name": u"webdev"}],
54 "create-users": [{"enabled": True, "home-phone": None,
55 "location": None, "name": u"JD",
56 "primary-gid": 1000, "uid": 1000,
57 "username": u"jdoe", "work-phone": None}],
58- "type": "users"}])
59+ "type": "users"}])
60 plugin.stop()
61
62 users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/sh")]
63@@ -91,20 +91,20 @@
64 self.assertTrue(persist.get("groups"))
65 self.assertMessages(
66 self.broker_service.message_store.get_pending_messages(),
67- [{"create-group-members": {u"webdev":[u"jdoe"]},
68+ [{"create-group-members": {u"webdev": [u"jdoe"]},
69 "create-groups": [{"gid": 1000, "name": u"webdev"}],
70 "create-users": [{"enabled": True, "home-phone": None,
71 "location": None, "name": u"JD",
72 "primary-gid": 1000, "uid": 1000,
73 "username": u"jdoe", "work-phone": None}],
74- "type": "users"}])
75+ "type": "users"}])
76 self.broker_service.message_store.delete_all_messages()
77 deferred = self.monitor.reactor.fire(
78 "resynchronize", scopes=["users"])[0]
79 self.successResultOf(deferred)
80 self.assertMessages(
81 self.broker_service.message_store.get_pending_messages(),
82- [{"create-group-members": {u"webdev":[u"jdoe"]},
83+ [{"create-group-members": {u"webdev": [u"jdoe"]},
84 "create-groups": [{"gid": 1000, "name": u"webdev"}],
85 "create-users": [{"enabled": True, "home-phone": None,
86 "location": None, "name": u"JD",
87@@ -113,6 +113,29 @@
88 "work-phone": None}],
89 "type": "users"}])
90
91+ def test_new_message_after_resynchronize_event(self):
92+ """
93+ When a 'resynchronize' reactor event is fired, a new session is
94+ created and the UserMonitor creates a new message.
95+ """
96+ self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
97+ "/home/jdoe", "/bin/sh")]
98+ self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
99+ self.broker_service.message_store.set_accepted_types(["users"])
100+ self.monitor.add(self.plugin)
101+ self.plugin.client.broker.message_store.drop_session_ids()
102+ deferred = self.reactor.fire("resynchronize")[0]
103+ self.successResultOf(deferred)
104+ self.assertMessages(
105+ self.broker_service.message_store.get_pending_messages(),
106+ [{"create-group-members": {u"webdev": [u"jdoe"]},
107+ "create-groups": [{"gid": 1000, "name": u"webdev"}],
108+ "create-users": [{"enabled": True, "home-phone": None,
109+ "location": None, "name": u"JD",
110+ "primary-gid": 1000, "uid": 1000,
111+ "username": u"jdoe", "work-phone": None}],
112+ "type": "users"}])
113+
114 def test_wb_resynchronize_event_with_global_scope(self):
115 """
116 When a C{resynchronize} event, with global scope, occurs we act exactly
117@@ -129,19 +152,19 @@
118 self.assertTrue(persist.get("groups"))
119 self.assertMessages(
120 self.broker_service.message_store.get_pending_messages(),
121- [{"create-group-members": {u"webdev":[u"jdoe"]},
122+ [{"create-group-members": {u"webdev": [u"jdoe"]},
123 "create-groups": [{"gid": 1000, "name": u"webdev"}],
124 "create-users": [{"enabled": True, "home-phone": None,
125 "location": None, "name": u"JD",
126 "primary-gid": 1000, "uid": 1000,
127 "username": u"jdoe", "work-phone": None}],
128- "type": "users"}])
129+ "type": "users"}])
130 self.broker_service.message_store.delete_all_messages()
131 deferred = self.monitor.reactor.fire("resynchronize")[0]
132 self.successResultOf(deferred)
133 self.assertMessages(
134 self.broker_service.message_store.get_pending_messages(),
135- [{"create-group-members": {u"webdev":[u"jdoe"]},
136+ [{"create-group-members": {u"webdev": [u"jdoe"]},
137 "create-groups": [{"gid": 1000, "name": u"webdev"}],
138 "create-users": [{"enabled": True, "home-phone": None,
139 "location": None, "name": u"JD",
140@@ -166,7 +189,7 @@
141 self.assertTrue(persist.get("groups"))
142 self.assertMessages(
143 self.broker_service.message_store.get_pending_messages(),
144- [{"create-group-members": {u"webdev":[u"jdoe"]},
145+ [{"create-group-members": {u"webdev": [u"jdoe"]},
146 "create-groups": [{"gid": 1000, "name": u"webdev"}],
147 "create-users": [{"enabled": True, "home-phone": None,
148 "location": None, "name": u"JD",
149@@ -189,13 +212,13 @@
150 def got_result(result):
151 self.assertMessages(
152 self.broker_service.message_store.get_pending_messages(),
153- [{"create-group-members": {u"webdev":[u"jdoe"]},
154+ [{"create-group-members": {u"webdev": [u"jdoe"]},
155 "create-groups": [{"gid": 1000, "name": u"webdev"}],
156 "create-users": [{"enabled": True, "home-phone": None,
157 "location": None, "name": u"JD",
158 "primary-gid": 1000, "uid": 1000,
159 "username": u"jdoe", "work-phone": None}],
160- "type": "users"}])
161+ "type": "users"}])
162
163 self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
164 "/home/jdoe", "/bin/sh")]
165@@ -230,14 +253,14 @@
166 def got_result(result):
167 self.assertMessages(
168 self.broker_service.message_store.get_pending_messages(),
169- [{"create-group-members": {u"webdev":[u"jdoe"]},
170+ [{"create-group-members": {u"webdev": [u"jdoe"]},
171 "create-groups": [{"gid": 1000, "name": u"webdev"}],
172 "create-users": [{"enabled": True, "home-phone": None,
173 "location": None, "name": u"JD",
174 "primary-gid": 1000, "uid": 1000,
175 "username": u"jdoe", "work-phone": None}],
176- "operation-id": 1001,
177- "type": "users"}])
178+ "operation-id": 1001,
179+ "type": "users"}])
180
181 self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
182 "/home/jdoe", "/bin/sh")]
183@@ -253,12 +276,12 @@
184 def got_result(result):
185 self.assertMessages(
186 self.broker_service.message_store.get_pending_messages(),
187- [{"create-group-members": {u"webdev":[u"jdoe"]},
188+ [{"create-group-members": {u"webdev": [u"jdoe"]},
189 "create-groups": [{"gid": 1000, "name": u"webdev"}],
190 "create-users": [{"enabled": True, "home-phone": None,
191 "location": None, "name": u"JD",
192 "primary-gid": 1000, "uid": 1000,
193- "username": u"jdoe", "work-phone": None}],
194+ "username": u"jdoe", "work-phone": None}],
195 "type": "users"}])
196
197 self.broker_service.message_store.set_accepted_types(["users"])
198@@ -283,7 +306,7 @@
199 def got_result(result):
200 self.assertMessages(
201 self.broker_service.message_store.get_pending_messages(),
202- [{"create-group-members": {u"webdev":[u"jdoe"]},
203+ [{"create-group-members": {u"webdev": [u"jdoe"]},
204 "create-groups": [{"gid": 1000, "name": u"webdev"}],
205 "create-users": [{"enabled": True, "home-phone": None,
206 "location": None, "name": u"JD",
207@@ -332,8 +355,9 @@
208
209 def got_result(result):
210 mstore = self.broker_service.message_store
211- self.assertMessages(mstore.get_pending_messages(),
212- [{"create-group-members": {u"webdev":[u"jdoe"]},
213+ self.assertMessages(
214+ mstore.get_pending_messages(),
215+ [{"create-group-members": {u"webdev": [u"jdoe"]},
216 "create-groups": [{"gid": 1000, "name": u"webdev"}],
217 "create-users": [{"enabled": True, "home-phone": None,
218 "location": None, "name": u"JD",
219@@ -376,7 +400,7 @@
220 self.mocker.replay()
221
222 self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
223- "/home/jdoe", "/bin/sh")]
224+ "/home/jdoe", "/bin/sh")]
225 self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
226 self.monitor.add(self.plugin)
227 connector = RemoteUserMonitorConnector(self.reactor, self.config)
228
229=== modified file 'landscape/monitor/usermonitor.py'
230--- landscape/monitor/usermonitor.py 2016-01-11 18:34:49 +0000
231+++ landscape/monitor/usermonitor.py 2016-01-15 16:29:39 +0000
232@@ -39,10 +39,14 @@
233 self._publisher.stop()
234 self._publisher = None
235
236- def _reset(self):
237+ def _resynchronize(self, scopes=None):
238 """Reset user and group data."""
239- super(UserMonitor, self)._reset()
240- return self._run_detect_changes()
241+ deferred = super(UserMonitor, self)._resynchronize(scopes=scopes)
242+ # Wait for the superclass' asynchronous _resynchronize method to
243+ # complete, so we have a new session ID at hand and we can craft a
244+ # valid message (l.broker.client.BrokerClientPlugin._resynchronize).
245+ deferred.addCallback(lambda _: self._run_detect_changes())
246+ return deferred
247
248 @remote
249 def detect_changes(self, operation_id=None):

Subscribers

People subscribed via source and target branches

to all changes: