Logo Search packages:      
Sourcecode: landscape-client version File versions

processorinfo.py

import logging
import os
import re

from landscape.plugin import PluginConfigError
from landscape.monitor.monitor import MonitorPlugin


00009 class ProcessorInfo(MonitorPlugin):
    """Plugin captures information about the processor(s) in this machine.

    This plugin runs once per client session.  When processor
    information is retrieved it's compared against the last known
    processor information, which is saved in persistent storage.  A
    message is only put on the message queue if the latest processor
    information differs from the last known processor information.

    The information available from /proc/cpuinfo varies per platform.
    For example, an Apple PowerMac Dual G5 doesn't contain a vendor ID
    and provides the processor name in the 'cpu' field, as opposed to
    the 'model name' field used on x86-based hardware.  For reasons
    such as this, the schema of the data reported by this plugin is
    flexible.  Only 'processor-id' and 'model' are guaranteed to be
    present.

    In order to deal with the vagaries of parsing /proc/cpu
    information on the various platforms we support, message
    generation is deferred to per-platform message factories.
    """

    persist_name = "processor-info"
    # Prevent the Plugin base-class from scheduling looping calls.
    run_interval = None

00035     def __init__(self, delay=2, machine_name=None,
                 source_filename="/proc/cpuinfo"):
        """Initialize plugin with starting delay and source filename."""
        self._delay = delay
        self._source_filename = source_filename

        if machine_name is None:
            machine_name = os.uname()[4]

        self._cpu_info_reader = self._create_cpu_info_reader(machine_name,
                                                             source_filename)

00047     def _create_cpu_info_reader(self, machine_name, source_filename):
        """Return a message factory suitable for the specified machine name."""
        for pair in message_factories:
            regexp = re.compile(pair[0])

            if regexp.match(machine_name):
                return pair[1](source_filename)

        raise PluginConfigError("A processor info reader for '%s' is not "
                                "available." % machine_name)

00058     def register(self, registry):
        """Register this plugin with the specified plugin registry."""
        super(ProcessorInfo, self).register(registry)
        self.registry.reactor.call_later(self._delay, self.run)
        self.registry.reactor.call_on("resynchronize", self._resynchronize)
        self.call_on_accepted("processor-info", self.send_message, True)

    def _resynchronize(self):
        self.registry.persist.remove(self.persist_name)

00068     def create_message(self):
        """Retrieve processor information and generate a message."""
        return {"type": "processor-info",
                "processors": self._cpu_info_reader.create_message()}

    def send_message(self, urgent=False):
        dirty = False
        message = self.create_message()

        for processor in message["processors"]:
            key = ("processor", str(processor["processor-id"]))
            cached_processor = self._persist.get(key)
            if cached_processor is None:
                cached_processor = {}
                self._update(cached_processor, processor)
                dirty = True
            else:
                if self._has_changed(cached_processor, processor):
                    self._update(cached_processor, processor)
                    dirty = True

        if dirty:
            logging.info("Queueing message with updated processor info.")
            self.registry.broker.send_message(message, urgent=urgent)

00093     def run(self, urgent=False):
        """Create a message and put it on the message queue."""
        self.registry.broker.call_if_accepted("processor-info",
                                              self.send_message, urgent)

00098     def _has_changed(self, processor, message):
        """Returns true if processor details changed since the last read."""
        if processor["model"] != message["model"]:
            return True

        if processor["vendor"] != message.get("vendor", ""):
            return True

        if processor["cache_size"] != message.get("cache-size", -1):
            return True

        return False

00111     def _update(self, processor, message):
        """Update the processor details with current values."""
        processor["id"] = message["processor-id"]
        processor["model"] = message["model"]
        processor["cache_size"] = message.get("cache-size", -1)
        processor["vendor"] = message.get("vendor", "")
        self._persist.set(("processor", str(message["processor-id"])),
                          processor)


00121 class PowerPCMessageFactory:
    """Factory for ppc-based processors provides processor information."""

00124     def __init__(self, source_filename):
        """Initialize reader with filename of data source."""
        self._source_filename = source_filename

00128     def create_message(self):
        """Returns a list containing information about each processor."""
        processors = []
        file = open(self._source_filename)

        try:
            current = None

            for line in file:
                parts = line.split(":", 1)
                key = parts[0].strip()

                if key == "processor":
                    current = {"processor-id": int(parts[1].strip())}
                    processors.append(current)
                elif key == "cpu":
                    current["model"] = parts[1].strip()
        finally:
            file.close()

        return processors


00151 class SparcMessageFactory:
    """Factory for sparc-based processors provides processor information."""

00154     def __init__(self, source_filename):
        """Initialize reader with filename of data source."""
        self._source_filename = source_filename

00158     def create_message(self):
        """Returns a list containing information about each processor."""
        processors = []
        model = None
        file = open(self._source_filename)

        try:
            regexp = re.compile("CPU(\d{1})+")

            for line in file:
                parts = line.split(":", 1)
                key = parts[0].strip()

                if key == "cpu":
                    model = parts[1].strip()
                elif regexp.match(key):
                    start, end = re.compile("\d+").search(key).span()
                    message = {"processor-id": int(key[start:end]),
                               "model": model}
                    processors.append(message)
        finally:
            file.close()

        return processors


00184 class X86MessageFactory:
    """Factory for x86-based processors provides processor information."""

00187     def __init__(self, source_filename):
        """Initialize reader with filename of data source."""
        self._source_filename = source_filename

00191     def create_message(self):
        """Returns a list containing information about each processor."""
        processors = []
        file = open(self._source_filename)

        try:
            current = None

            for line in file:
                parts = line.split(":", 1)
                key = parts[0].strip()

                if key == "processor":
                    current = {"processor-id": int(parts[1].strip())}
                    processors.append(current)
                elif key == "vendor_id":
                    current["vendor"] = parts[1].strip()
                elif key == "model name":
                    current["model"] = parts[1].strip()
                elif key == "cache size":
                    value_parts = parts[1].split()
                    current["cache-size"] = int(value_parts[0].strip())
        finally:
            file.close()

        return processors


message_factories = [("ppc(64)?", PowerPCMessageFactory),
                     ("sparc[64]", SparcMessageFactory),
                     ("i[3-7]86|x86_64", X86MessageFactory)]

Generated by  Doxygen 1.6.0   Back to index