3
from twisted.internet.defer import fail
5
from landscape.monitor.usermonitor import (
6
UserMonitor, RemoteUserMonitorConnector)
7
from landscape.manager.usermanager import (
8
UserManager, UserManagerProtocolFactory)
9
from landscape.user.tests.helpers import FakeUserProvider
10
from landscape.tests.helpers import LandscapeTest, MonitorHelper
11
from landscape.tests.mocker import ANY
14
class UserMonitorNoManagerTest(LandscapeTest):
16
helpers = [MonitorHelper]
18
def test_no_fetch_users_in_monitor_only_mode(self):
20
If we're in monitor_only mode, then all users are assumed to be
23
self.config.monitor_only = True
25
def got_result(result):
27
self.broker_service.message_store.get_pending_messages(),
28
[{"create-group-members": {u"webdev":[u"jdoe"]},
29
"create-groups": [{"gid": 1000, "name": u"webdev"}],
30
"create-users": [{"enabled": True, "home-phone": None,
31
"location": None, "name": u"JD",
32
"primary-gid": 1000, "uid": 1000,
33
"username": u"jdoe", "work-phone": None}],
37
users = [("jdoe", "x", 1000, 1000, "JD,,,,", "/home/jdoe", "/bin/sh")]
38
groups = [("webdev", "x", 1000, ["jdoe"])]
39
provider = FakeUserProvider(users=users, groups=groups)
40
plugin = UserMonitor(provider=provider)
41
plugin.register(self.monitor)
42
self.broker_service.message_store.set_accepted_types(["users"])
44
result.addCallback(got_result)
48
class UserMonitorTest(LandscapeTest):
50
helpers = [MonitorHelper]
53
super(UserMonitorTest, self).setUp()
54
self.shadow_file = self.makeFile(
55
"jdoe:$1$xFlQvTqe$cBtrNEDOIKMy/BuJoUdeG0:13348:0:99999:7:::\n"
56
"psmith:!:13348:0:99999:7:::\n"
57
"sam:$1$q7sz09uw$q.A3526M/SHu8vUb.Jo1A/:13349:0:99999:7:::\n")
58
self.user_manager = UserManager(shadow_file=self.shadow_file)
59
factory = UserManagerProtocolFactory(object=self.user_manager)
60
socket = os.path.join(self.config.sockets_path,
61
UserManager.name + ".sock")
62
self.port = self.reactor.listen_unix(socket, factory)
63
self.provider = FakeUserProvider()
64
self.plugin = UserMonitor(self.provider)
67
self.port.stopListening()
69
return super(UserMonitorTest, self).tearDown()
71
def test_constants(self):
73
L{UserMonitor.persist_name} and
74
L{UserMonitor.run_interval} need to be present for
75
L{Plugin} to work properly.
77
self.assertEquals(self.plugin.persist_name, "users")
78
self.assertEquals(self.plugin.run_interval, 3600)
80
def test_wb_resynchronize_event(self):
82
When a C{resynchronize} event occurs any cached L{UserChange}
83
snapshots should be cleared and a new message with users generated.
86
def resynchronize_complete(result, plugin):
88
def resynchronization_new_messages(result):
90
self.broker_service.message_store.get_pending_messages(),
91
[{"create-group-members": {u"webdev":[u"jdoe"]},
92
"create-groups": [{"gid": 1000, "name": u"webdev"}],
93
"create-users": [{"enabled": True, "home-phone": None,
94
"location": None, "name": u"JD",
95
"primary-gid": 1000, "uid": 1000,
100
persist = plugin._persist
101
self.assertTrue(persist.get("users"))
102
self.assertTrue(persist.get("groups"))
104
self.broker_service.message_store.get_pending_messages(),
105
[{"create-group-members": {u"webdev":[u"jdoe"]},
106
"create-groups": [{"gid": 1000, "name": u"webdev"}],
107
"create-users": [{"enabled": True, "home-phone": None,
108
"location": None, "name": u"JD",
109
"primary-gid": 1000, "uid": 1000,
110
"username": u"jdoe", "work-phone": None}],
112
# Clear all the messages from the message store
113
self.broker_service.message_store.delete_all_messages()
114
deferred = self.monitor.reactor.fire("resynchronize")[0]
115
deferred.addCallback(resynchronization_new_messages)
118
self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
119
"/home/jdoe", "/bin/sh")]
120
self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
121
self.broker_service.message_store.set_accepted_types(["users"])
122
self.monitor.add(self.plugin)
123
deferred = self.plugin.run()
124
deferred.addCallback(resynchronize_complete, self.plugin)
129
The L{UserMonitor} should have message run which should enqueue a
130
message with a diff-like representation of changes since the last
134
def got_result(result):
136
self.broker_service.message_store.get_pending_messages(),
137
[{"create-group-members": {u"webdev":[u"jdoe"]},
138
"create-groups": [{"gid": 1000, "name": u"webdev"}],
139
"create-users": [{"enabled": True, "home-phone": None,
140
"location": None, "name": u"JD",
141
"primary-gid": 1000, "uid": 1000,
142
"username": u"jdoe", "work-phone": None}],
145
self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
146
"/home/jdoe", "/bin/sh")]
147
self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
148
self.broker_service.message_store.set_accepted_types(["users"])
149
self.monitor.add(self.plugin)
150
result = self.plugin.run()
151
result.addCallback(got_result)
154
def test_run_interval(self):
156
L{UserMonitor.register} calls the C{register} method on it's
157
super class, which sets up a looping call to run the plugin
158
every L{UserMonitor.run_interval} seconds.
160
self.plugin.run = self.mocker.mock()
161
self.expect(self.plugin.run()).count(5)
163
self.monitor.add(self.plugin)
165
self.broker_service.message_store.set_accepted_types(["users"])
166
self.reactor.advance(self.plugin.run_interval * 5)
168
def test_run_with_operation_id(self):
170
The L{UserMonitor} should have message run which should enqueue a
171
message with a diff-like representation of changes since the last
175
def got_result(result):
177
self.broker_service.message_store.get_pending_messages(),
178
[{"create-group-members": {u"webdev":[u"jdoe"]},
179
"create-groups": [{"gid": 1000, "name": u"webdev"}],
180
"create-users": [{"enabled": True, "home-phone": None,
181
"location": None, "name": u"JD",
182
"primary-gid": 1000, "uid": 1000,
183
"username": u"jdoe", "work-phone": None}],
184
"operation-id": 1001,
188
self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
189
"/home/jdoe", "/bin/sh")]
190
self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
191
self.monitor.add(self.plugin)
192
self.broker_service.message_store.set_accepted_types(["users"])
193
result = self.plugin.run(1001)
194
result.addCallback(got_result)
197
def test_detect_changes(self):
199
def got_result(result):
201
self.broker_service.message_store.get_pending_messages(),
202
[{"create-group-members": {u"webdev":[u"jdoe"]},
203
"create-groups": [{"gid": 1000, "name": u"webdev"}],
204
"create-users": [{"enabled": True, "home-phone": None,
205
"location": None, "name": u"JD",
206
"primary-gid": 1000, "uid": 1000,
207
"username": u"jdoe", "work-phone": None}],
210
self.broker_service.message_store.set_accepted_types(["users"])
211
self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
212
"/home/jdoe", "/bin/sh")]
213
self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
215
self.monitor.add(self.plugin)
216
connector = RemoteUserMonitorConnector(self.reactor, self.config)
217
result = connector.connect()
218
result.addCallback(lambda remote: remote.detect_changes())
219
result.addCallback(got_result)
220
result.addCallback(lambda x: connector.disconnect())
223
def test_detect_changes_with_operation_id(self):
225
The L{UserMonitor} should expose a remote
226
C{remote_run} method which should call the remote
229
def got_result(result):
231
self.broker_service.message_store.get_pending_messages(),
232
[{"create-group-members": {u"webdev":[u"jdoe"]},
233
"create-groups": [{"gid": 1000, "name": u"webdev"}],
234
"create-users": [{"enabled": True, "home-phone": None,
235
"location": None, "name": u"JD",
236
"primary-gid": 1000, "uid": 1000,
237
"username": u"jdoe", "work-phone": None}],
238
"operation-id": 1001,
241
self.broker_service.message_store.set_accepted_types(["users"])
242
self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
243
"/home/jdoe", "/bin/sh")]
244
self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
245
self.monitor.add(self.plugin)
246
connector = RemoteUserMonitorConnector(self.reactor, self.config)
247
result = connector.connect()
248
result.addCallback(lambda remote: remote.detect_changes(1001))
249
result.addCallback(got_result)
250
result.addCallback(lambda x: connector.disconnect())
253
def test_no_message_if_not_accepted(self):
255
Don't add any messages at all if the broker isn't currently
256
accepting their type.
259
def got_result(result):
260
mstore = self.broker_service.message_store
261
self.assertMessages(list(mstore.get_pending_messages()), [])
262
mstore.set_accepted_types(["users"])
263
self.assertMessages(list(mstore.get_pending_messages()), [])
265
self.broker_service.message_store.set_accepted_types([])
266
self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
267
"/home/jdoe", "/bin/sh")]
268
self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
269
self.monitor.add(self.plugin)
270
connector = RemoteUserMonitorConnector(self.reactor, self.config)
271
result = connector.connect()
272
result.addCallback(lambda remote: remote.detect_changes(1001))
273
result.addCallback(got_result)
274
result.addCallback(lambda x: connector.disconnect())
277
def test_call_on_accepted(self):
279
def got_result(result):
280
mstore = self.broker_service.message_store
281
self.assertMessages(mstore.get_pending_messages(),
282
[{"create-group-members": {u"webdev":[u"jdoe"]},
283
"create-groups": [{"gid": 1000, "name": u"webdev"}],
284
"create-users": [{"enabled": True, "home-phone": None,
285
"location": None, "name": u"JD",
286
"primary-gid": 1000, "uid": 1000,
287
"username": u"jdoe", "work-phone": None}],
290
self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
291
"/home/jdoe", "/bin/sh")]
292
self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
293
self.monitor.add(self.plugin)
295
self.broker_service.message_store.set_accepted_types(["users"])
296
result = self.reactor.fire(
297
("message-type-acceptance-changed", "users"), True)
298
result = [x for x in result if x][0]
299
result.addCallback(got_result)
302
def test_do_not_persist_changes_when_send_message_fails(self):
304
When the plugin is run it persists data that it uses on
305
subsequent checks to calculate the delta to send. It should
306
only persist data when the broker confirms that the message
307
sent by the plugin has been sent.
309
self.log_helper.ignore_errors(RuntimeError)
311
def got_result(result):
312
persist = self.plugin._persist
313
mstore = self.broker_service.message_store
314
self.assertMessages(mstore.get_pending_messages(), [])
315
self.assertFalse(persist.get("users"))
316
self.assertFalse(persist.get("groups"))
318
self.broker_service.message_store.set_accepted_types(["users"])
319
self.monitor.broker.send_message = self.mocker.mock()
320
self.monitor.broker.send_message(ANY, urgent=True)
321
self.mocker.result(fail(RuntimeError()))
324
self.provider.users = [("jdoe", "x", 1000, 1000, "JD,,,,",
325
"/home/jdoe", "/bin/sh")]
326
self.provider.groups = [("webdev", "x", 1000, ["jdoe"])]
327
self.monitor.add(self.plugin)
328
connector = RemoteUserMonitorConnector(self.reactor, self.config)
329
result = connector.connect()
330
result.addCallback(lambda remote: remote.detect_changes(1001))
331
result.addCallback(got_result)
332
result.addCallback(lambda x: connector.disconnect())