~ahasenack/landscape-client/landscape-client-1.5.5-0ubuntu0.9.04.0

« back to all changes in this revision

Viewing changes to landscape/monitor/hardwareinventory.py

  • Committer: Bazaar Package Importer
  • Author(s): Rick Clark
  • Date: 2008-09-08 16:35:57 UTC
  • mto: This revision was merged to the branch mainline in revision 2.
  • Revision ID: james.westby@ubuntu.com-20080908163557-fl0d2oc35hur473w
Tags: upstream-1.0.18
ImportĀ upstreamĀ versionĀ 1.0.18

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import logging
 
2
 
 
3
from twisted.internet.defer import succeed
 
4
 
 
5
from landscape.lib.log import log_failure
 
6
 
 
7
from landscape.diff import diff
 
8
from landscape.hal import HALManager
 
9
from landscape.monitor.monitor import MonitorPlugin
 
10
 
 
11
 
 
12
class HardwareInventory(MonitorPlugin):
 
13
 
 
14
    persist_name = "hardware-inventory"
 
15
 
 
16
    def __init__(self, hal_manager=None):
 
17
        super(HardwareInventory, self).__init__()
 
18
        self._persist_sets = []
 
19
        self._persist_removes = []
 
20
        self._hal_manager = hal_manager or HALManager()
 
21
 
 
22
    def register(self, manager):
 
23
        super(HardwareInventory, self).register(manager)
 
24
        manager.reactor.call_on("resynchronize", self._resynchronize)
 
25
        self.call_on_accepted("hardware-inventory", self.exchange, True)
 
26
 
 
27
    def _resynchronize(self):
 
28
        self._persist.remove("devices")
 
29
 
 
30
    def send_message(self, urgent):
 
31
        devices = self.create_message()
 
32
        if devices:
 
33
            message = {"type": "hardware-inventory", "devices": devices}
 
34
            result = self.registry.broker.send_message(message, urgent=urgent)
 
35
            result.addCallback(self.persist_data)
 
36
            result.addErrback(log_failure)
 
37
            logging.info("Queueing a message with hardware-inventory "
 
38
                         "information.")
 
39
        else:
 
40
            result = succeed(None)
 
41
        return result
 
42
 
 
43
    def exchange(self, urgent=False):
 
44
        return self.registry.broker.call_if_accepted("hardware-inventory",
 
45
                                                     self.send_message, urgent)
 
46
 
 
47
    def persist_data(self, message_id):
 
48
        for key, udi, value in self._persist_sets:
 
49
            self._persist.set((key, udi), value)
 
50
        for key in self._persist_removes:
 
51
            self._persist.remove(key)
 
52
        del self._persist_sets[:]
 
53
        del self._persist_removes[:]
 
54
 
 
55
    def create_message(self):
 
56
        # FIXME Using persist to keep track of changes here uses a
 
57
        # fair amount of memory.  On my machine a rough test seemed to
 
58
        # indicate that memory usage grew by 1.3mb, about 12% of the
 
59
        # overall process size.  Look here to save memory.
 
60
        del self._persist_sets[:]
 
61
        del self._persist_removes[:]
 
62
        devices = []
 
63
        previous_devices = self._persist.get("devices", {})
 
64
        current_devices = set()
 
65
 
 
66
        for device in self._hal_manager.get_devices():
 
67
            previous_properties = previous_devices.get(device.udi)
 
68
            if not previous_properties:
 
69
                devices.append(("create", device.properties))
 
70
            elif previous_properties != device.properties:
 
71
                creates, updates, deletes = diff(previous_properties,
 
72
                                                 device.properties)
 
73
                devices.append(("update", device.udi,
 
74
                                creates, updates, deletes))
 
75
            current_devices.add(device.udi)
 
76
            self._persist_sets.append(
 
77
                ("devices", device.udi, device.properties))
 
78
 
 
79
        items_with_parents = {}
 
80
        deleted_devices = set()
 
81
        for udi,value in previous_devices.iteritems():
 
82
            if udi not in current_devices:
 
83
                if value.has_key("info.parent"):
 
84
                    items_with_parents[udi] = value["info.parent"]
 
85
                deleted_devices.add(udi)
 
86
 
 
87
        # We remove the deleted devices from our persistent store it's
 
88
        # only the information we're sending to the server that we're
 
89
        # compressing.
 
90
        for udi in deleted_devices:
 
91
            self._persist_removes.append(("devices", udi))
 
92
 
 
93
        # We can now flatten the list of devices we send to the server
 
94
        # For each of the items_with_parents, if both the item and it's parent
 
95
        # are in the deleted_devices set, then we can remove this item from the
 
96
        # set.
 
97
        minimal_deleted_devices = deleted_devices.copy()
 
98
        for child, parent in items_with_parents.iteritems():
 
99
            if child in deleted_devices and parent in deleted_devices:
 
100
                minimal_deleted_devices.remove(child)
 
101
        # We now build the deleted devices message
 
102
        for udi in minimal_deleted_devices:
 
103
            devices.append(("delete", udi))
 
104
 
 
105
        return devices