1
3
from twisted.internet.defer import maybeDeferred
3
5
from landscape.lib.log import log_failure
6
from landscape.lib.amp import RemoteObject
7
from landscape.amp import (
8
ComponentProtocol, ComponentProtocolFactory, RemoteComponentConnector)
5
from landscape.lib.dbus_util import method, get_object, Object
6
from landscape.monitor.monitor import (MonitorPlugin, BUS_NAME, OBJECT_PATH,
10
from landscape.monitor.plugin import MonitorPlugin
8
11
from landscape.user.changes import UserChanges
9
12
from landscape.user.provider import UserProvider
12
class UserMonitorDBusObject(Object):
14
A DBUS object which exposes an API for getting the monitor to detect user
15
changes and upload them to the Landscape server.
17
object_path = OBJECT_PATH + "/UserMonitor"
18
iface_name = IFACE_NAME + ".UserMonitor"
21
def __init__(self, bus, plugin):
22
super(UserMonitorDBusObject, self).__init__(bus)
26
def detect_changes(self, operation_id=None):
27
return self._plugin.run(operation_id)
30
15
class UserMonitor(MonitorPlugin):
32
17
A plugin which monitors the system user databases.
35
20
persist_name = "users"
36
21
run_interval = 3600 # 1 hour
38
24
def __init__(self, provider=None):
39
25
if provider is None:
40
26
provider = UserProvider()
41
27
self._provider = provider
43
30
def register(self, registry):
44
31
super(UserMonitor, self).register(registry)
45
33
self.registry.reactor.call_on("resynchronize", self._resynchronize)
46
34
self.call_on_accepted("users", self._run_detect_changes, None)
47
self._dbus_object = UserMonitorDBusObject(registry.bus, self)
36
factory = UserMonitorProtocolFactory(object=self)
37
socket = os.path.join(self.registry.config.sockets_path,
39
self._port = self.registry.reactor.listen_unix(socket, factory)
40
from landscape.manager.usermanager import RemoteUserManagerConnector
41
self._user_manager_connector = RemoteUserManagerConnector(
42
self.registry.reactor, self.registry.config)
45
"""Stop listening for incoming AMP connections."""
47
self._port.stopListening()
49
50
def _resynchronize(self):
50
51
"""Resynchronize user and group data."""
56
57
return self.registry.broker.call_if_accepted(
57
58
"users", self._run_detect_changes, operation_id)
59
62
def _run_detect_changes(self, operation_id=None):
61
64
If changes are detected an C{urgent-exchange} is fired to send
64
67
@param operation_id: When present it will be included in the
65
68
C{operation-id} field.
67
from landscape.manager.usermanager import UserManagerDBusObject
68
70
# We'll skip checking the locked users if we're in monitor-only mode.
69
71
if getattr(self.registry.config, "monitor_only", False):
70
72
result = maybeDeferred(self._detect_changes,
73
remote_service = get_object(self.registry.bus,
74
UserManagerDBusObject.bus_name,
75
UserManagerDBusObject.object_path)
77
result = remote_service.get_locked_usernames()
76
def get_locked_usernames(user_manager):
77
return user_manager.get_locked_usernames()
79
def disconnect(locked_usernames):
80
self._user_manager_connector.disconnect()
81
return locked_usernames
83
result = self._user_manager_connector.connect()
84
result.addCallback(get_locked_usernames)
85
result.addCallback(disconnect)
78
86
result.addCallback(self._detect_changes, operation_id)
79
87
result.addErrback(lambda f: self._detect_changes([], operation_id))
82
90
def _detect_changes(self, locked_users, operation_id=None):
83
92
def update_snapshot(result):
91
100
self._provider.locked_users = locked_users
92
101
changes = UserChanges(self._persist, self._provider)
93
102
message = changes.create_diff()
95
105
message["type"] = "users"
99
109
result.addCallback(update_snapshot)
100
110
result.addErrback(log_error)
114
class UserMonitorProtocol(ComponentProtocol):
115
"""L{AMP}-based protocol for calling L{UserMonitor}'s methods remotely."""
117
methods = ["detect_changes"]
120
class UserMonitorProtocolFactory(ComponentProtocolFactory):
122
protocol = UserMonitorProtocol
125
class RemoteUserMonitor(RemoteObject):
126
"""A connected remote L{UserMonitor}."""
129
class RemoteUserMonitorConnector(RemoteComponentConnector):
131
factory = ComponentProtocolFactory
132
remote = RemoteUserMonitor
133
component = UserMonitor