Merge lp:~tealeg/landscape-client/package-monitor-scoped-resynch into lp:~landscape/landscape-client/trunk

Proposed by Geoff Teale
Status: Merged
Approved by: Geoff Teale
Approved revision: 723
Merged at revision: 713
Proposed branch: lp:~tealeg/landscape-client/package-monitor-scoped-resynch
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 178 lines (+76/-56)
3 files modified
landscape/monitor/packagemonitor.py (+1/-0)
landscape/monitor/tests/test_packagemonitor.py (+75/-15)
landscape/monitor/tests/test_usermonitor.py (+0/-41)
To merge this branch: bzr merge lp:~tealeg/landscape-client/package-monitor-scoped-resynch
Reviewer Review Type Date Requested Status
Björn Tillenius (community) Approve
Jerry Seutter (community) Approve
Review via email: mp+175014@code.launchpad.net

This proposal supersedes a proposal from 2013-07-12.

Commit message

This branch makes the PackageMonitor plugin only respond to resynchronize-clients events when they are either "package" or global scope.

Description of the change

This branch makes the PackageMonitor plugin only respond to resynchronize-clients events when they are either "package" or global scope.

To post a comment you must log in.
Revision history for this message
Jerry Seutter (jseutter) wrote : Posted in a previous version of this proposal

+1, looks good.

landscape/monitor/tests/test_packagemonitor.py:233:80: E501 line too long (80 characters)

review: Approve
Revision history for this message
Jerry Seutter (jseutter) wrote : Posted in a previous version of this proposal

In other branches the call signature for _resynchronize uses scopes:
def _resynchronize(self, scopes):

Can you update this changeset to use scopes instead of scope?

Revision history for this message
Geoff Teale (tealeg) wrote : Posted in a previous version of this proposal

> +1, looks good.
>
> landscape/monitor/tests/test_packagemonitor.py:233:80: E501 line too long (80
> characters)

Done.

Revision history for this message
Geoff Teale (tealeg) wrote : Posted in a previous version of this proposal

> In other branches the call signature for _resynchronize uses scopes:
> def _resynchronize(self, scopes):
>
> Can you update this changeset to use scopes instead of scope?

Done.

Revision history for this message
Björn Tillenius (bjornt) wrote : Posted in a previous version of this proposal

[1]

+ if len(scopes) == 0 or self.scope in scopes:

This makes me a bit sad. Having this in every _resynchronize() doesn't
doesn't look good.

I see that we register the resynchronize method with something like
this:

  self.registry.reactor.call_on("resynchronize", self._resynchronize)

I'd suggest doing something like this instead:

  self.registry.register_resynchronize(self.scope, self._resynchronize)

That way self._resynchronize would be called only for the relevant
scope, which makes the method easier to read.

review: Needs Fixing
Revision history for this message
Geoff Teale (tealeg) wrote : Posted in a previous version of this proposal

> [1]
>
> + if len(scopes) == 0 or self.scope in scopes:
>
> This makes me a bit sad. Having this in every _resynchronize() doesn't
> doesn't look good.
>
> I see that we register the resynchronize method with something like
> this:
>
> self.registry.reactor.call_on("resynchronize", self._resynchronize)
>
> I'd suggest doing something like this instead:
>
> self.registry.register_resynchronize(self.scope, self._resynchronize)
>
> That way self._resynchronize would be called only for the relevant
> scope, which makes the method easier to read.

Hi Bjorn, would you be happy for me to make that change as a follow on branch? It effects multiple branches here and it would be cleaner to tidy it all up in one swoop.

Revision history for this message
Björn Tillenius (bjornt) wrote : Posted in a previous version of this proposal

On Wed, Jul 10, 2013 at 05:37:53PM -0000, Geoff Teale wrote:
> > [1]
> >
> > + if len(scopes) == 0 or self.scope in scopes:
> >
> > This makes me a bit sad. Having this in every _resynchronize() doesn't
> > doesn't look good.
> >
> > I see that we register the resynchronize method with something like
> > this:
> >
> > self.registry.reactor.call_on("resynchronize", self._resynchronize)
> >
> > I'd suggest doing something like this instead:
> >
> > self.registry.register_resynchronize(self.scope, self._resynchronize)
> >
> > That way self._resynchronize would be called only for the relevant
> > scope, which makes the method easier to read.
>
> Hi Bjorn, would you be happy for me to make that change as a follow on
> branch? It effects multiple branches here and it would be cleaner to
> tidy it all up in one swoop.

Sure, that would be fine, if it's easier.

Revision history for this message
Geoff Teale (tealeg) wrote : Posted in a previous version of this proposal

> > Hi Bjorn, would you be happy for me to make that change as a follow on
> > branch? It effects multiple branches here and it would be cleaner to
> > tidy it all up in one swoop.
>
> Sure, that would be fine, if it's easier.

OK, I'll add a clean up branch at the end, I have some other calls to tidy up across all branches too.

722. By Geoff Teale

merge forwards and resolve conflicts.

Revision history for this message
Jerry Seutter (jseutter) wrote :

+1

review: Approve
Revision history for this message
Björn Tillenius (bjornt) wrote :

Looks good, +1

[1]

+ def test_not_resynchronize_with_other_scope(self):
+ """
+ If a 'resynchronize' reactor event is fired with an irrelevant scope,
+ the package monitor should not respond to this.
+ """
+ self.monitor.add(self.package_monitor)
+ self.createReporterTask()
+
+ disk_scope = ["disk"]
+ self.monitor.reactor.fire("resynchronize", disk_scope)
+
+ # The next task should *not* be the resynchronize message.
+ self.assertSingleReporterTask(
+ {'ids': [None], 'request-id': 1, 'type': 'package-ids'}, 1)

Where does that dict on the last line come from? Ok, after reading the
diff I can see that it's from createReporterTask(), but if someone looks
at the test only, it's hard to see.

It would be better to either explicitly add that task you expect to be
there, or make createReportTask() return the task and id, so that it's
clear that you expect the existing task to still be there, and no a new
one.

review: Approve
723. By Geoff Teale

Make test more readable by returning the task from createReporterTask.

Revision history for this message
Geoff Teale (tealeg) wrote :

> Looks good, +1
>
> [1]
>

Agreed, I've tidied that up.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'landscape/monitor/packagemonitor.py'
--- landscape/monitor/packagemonitor.py 2013-07-12 08:18:35 +0000
+++ landscape/monitor/packagemonitor.py 2013-07-25 13:19:26 +0000
@@ -11,6 +11,7 @@
11class PackageMonitor(MonitorPlugin):11class PackageMonitor(MonitorPlugin):
1212
13 run_interval = 180013 run_interval = 1800
14 scope = "package"
1415
15 def __init__(self, package_store_filename=None):16 def __init__(self, package_store_filename=None):
16 super(PackageMonitor, self).__init__()17 super(PackageMonitor, self).__init__()
1718
=== modified file 'landscape/monitor/tests/test_packagemonitor.py'
--- landscape/monitor/tests/test_packagemonitor.py 2013-07-16 08:30:55 +0000
+++ landscape/monitor/tests/test_packagemonitor.py 2013-07-25 13:19:26 +0000
@@ -23,6 +23,33 @@
2323
24 self.package_monitor = PackageMonitor(self.package_store_filename)24 self.package_monitor = PackageMonitor(self.package_store_filename)
2525
26 def createReporterTask(self):
27 """
28 Put a task for the package reported into the package store.
29 """
30 message = {"type": "package-ids", "ids": [None], "request-id": 1}
31 return self.package_store.add_task("reporter", message)
32
33 def assertSingleReporterTask(self, data, task_id):
34 """
35 Check that we have exactly one task, that it contains the right data
36 and that it's ID matches our expectation.
37 """
38 # The next task should contain the passed data.
39 task = self.package_store.get_next_task("reporter")
40 self.assertEqual(task.data, data)
41
42 # We want to make sure it has the correct id of 2 so that we
43 # know it's not a new task that the reporter could possibly
44 # remove by accident.
45 self.assertEqual(task.id, task_id)
46
47 # Let's remove that task and make sure there are no more tasks
48 # in the queue.
49 task.remove()
50 task = self.package_store.get_next_task("reporter")
51 self.assertEqual(task, None)
52
26 def test_create_default_store_upon_message_handling(self):53 def test_create_default_store_upon_message_handling(self):
27 """54 """
28 If the package sqlite database file doesn't exist yet, it is created55 If the package sqlite database file doesn't exist yet, it is created
@@ -200,28 +227,61 @@
200227
201 def test_resynchronize(self):228 def test_resynchronize(self):
202 """229 """
203 If a 'resynchronize' reactor event is fired, the package230 If a 'resynchronize' reactor event is fired with 'package' scope, the
204 monitor should clear all queued tasks and queue a task that231 package monitor should clear all queued tasks and queue a task that
205 tells the report to clear out the rest of the package data.232 tells the report to clear out the rest of the package data.
206 """233 """
207 self.monitor.add(self.package_monitor)234 self.monitor.add(self.package_monitor)
208 message = {"type": "package-ids", "ids": [None], "request-id": 1}235 self.createReporterTask()
209 self.package_store.add_task("reporter", message)236
237 # The server doesn't currently send 'package' scope, but we should
238 # support it in case we change that in the future.
239 package_scope = ["package"]
240 self.monitor.reactor.fire("resynchronize", package_scope)
241
242 self.assertSingleReporterTask({"type": "resynchronize"}, 2)
243
244 def test_resynchronize_gets_new_session_id(self):
245 """
246 When a 'resynchronize' reactor event is fired, the C{PackageMonitor}
247 acquires a new session ID (as the old one will be blocked).
248 """
249 self.monitor.add(self.package_monitor)
250 session_id = self.package_monitor._session_id
251 self.createReporterTask()
252
253 self.package_monitor.client.broker.message_store.drop_session_ids()
254 self.monitor.reactor.fire("resynchronize")
255 self.assertNotEqual(session_id, self.package_monitor._session_id)
256
257 def test_resynchronize_on_global_scope(self):
258 """
259 If a 'resynchronize' reactor event is fired with global scope (the
260 empty list) , the package monitor should act as if it were an event
261 with 'package' scope.
262 """
263 self.monitor.add(self.package_monitor)
264 self.createReporterTask()
210265
211 self.monitor.reactor.fire("resynchronize")266 self.monitor.reactor.fire("resynchronize")
212267
213 # The next task should be the resynchronize message.268 # The next task should be the resynchronize message.
214 task = self.package_store.get_next_task("reporter")269 self.assertSingleReporterTask({"type": "resynchronize"}, 2)
215 self.assertEqual(task.data, {"type": "resynchronize"})270
216271 def test_not_resynchronize_with_other_scope(self):
217 # We want to make sure it is not the first message272 """
218 self.assertNotEqual(task.id, 1)273 If a 'resynchronize' reactor event is fired with an irrelevant scope,
219274 the package monitor should not respond to this.
220 # Let's remove that task and make sure there are no more tasks275 """
221 # in the queue.276 self.monitor.add(self.package_monitor)
222 task.remove()277 task = self.createReporterTask()
223 task = self.package_store.get_next_task("reporter")278
224 self.assertEqual(task, None)279 disk_scope = ["disk"]
280 self.monitor.reactor.fire("resynchronize", disk_scope)
281
282 # The next task should *not* be the resynchronize message, but instead
283 # the original task we created.
284 self.assertSingleReporterTask(task.data, task.id)
225285
226 def test_spawn_reporter_doesnt_chdir(self):286 def test_spawn_reporter_doesnt_chdir(self):
227 command = self.makeFile("#!/bin/sh\necho RUN\n")287 command = self.makeFile("#!/bin/sh\necho RUN\n")
228288
=== modified file 'landscape/monitor/tests/test_usermonitor.py'
--- landscape/monitor/tests/test_usermonitor.py 2013-07-16 09:01:54 +0000
+++ landscape/monitor/tests/test_usermonitor.py 2013-07-25 13:19:26 +0000
@@ -178,47 +178,6 @@
178 self.assertMessages(178 self.assertMessages(
179 self.broker_service.message_store.get_pending_messages(),179 self.broker_service.message_store.get_pending_messages(),
180 [])180 [])
181# =======
182# When a C{resynchronize} event occurs any cached L{UserChange}
183# snapshots should be cleared and a new message with users generated.
184# """
185# self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
186# "/home/jdoe", "/bin/sh")]
187# self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
188# self.broker_service.message_store.set_accepted_types(["users"])
189# self.monitor.add(self.plugin)
190# self.successResultOf(self.plugin.run())
191
192# persist = self.plugin._persist
193# self.assertTrue(persist.get("users"))
194# self.assertTrue(persist.get("groups"))
195# self.assertMessages(
196# self.broker_service.message_store.get_pending_messages(),
197# [{"create-group-members": {u"webdev":[u"jdoe"]},
198# "create-groups": [{"gid": 1000, "name": u"webdev"}],
199# "create-users": [{"enabled": True, "home-phone": None,
200# "location": None, "name": u"JD",
201# "primary-gid": 1000, "uid": 1000,
202# "username": u"jdoe", "work-phone": None}],
203# "type": "users"}])
204
205# # Clear all the messages from the message store
206# self.broker_service.message_store.delete_all_messages()
207
208# self.monitor.reactor.fire("resynchronize")
209
210# self.successResultOf(self.plugin.run())
211# self.assertMessages(
212# self.broker_service.message_store.get_pending_messages(),
213# [{"create-group-members": {u"webdev":[u"jdoe"]},
214# "create-groups": [{"gid": 1000, "name": u"webdev"}],
215# "create-users": [{"enabled": True, "home-phone": None,
216# "location": None, "name": u"JD",
217# "primary-gid": 1000, "uid": 1000,
218# "username": u"jdoe",
219# "work-phone": None}],
220# "type": "users"}])
221# >>>>>>> MERGE-SOURCE
222181
223 def test_run(self):182 def test_run(self):
224 """183 """

Subscribers

People subscribed via source and target branches

to all changes: