This file is indexed.

/usr/share/pyshared/landscape/manager/shutdownmanager.py is in landscape-common 12.04.3-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import logging

from twisted.internet.defer import Deferred
from twisted.internet.protocol import ProcessProtocol
from twisted.internet.error import ProcessDone

from landscape.manager.plugin import ManagerPlugin, SUCCEEDED, FAILED


class ShutdownFailedError(Exception):
    """Raised when a call to C{/sbin/shutdown} fails.

    @ivar data: The data that the process printed before failing.
    """

    def __init__(self, data):
        self.data = data


class ShutdownManager(ManagerPlugin):

    def __init__(self, process_factory=None):
        if process_factory is None:
            from twisted.internet import reactor as process_factory
        self._process_factory = process_factory

    def register(self, registry):
        """Add this plugin to C{registry}.

        The shutdown manager handles C{shutdown} activity messages broadcast
        from the server.
        """
        super(ShutdownManager, self).register(registry)
        registry.register_message("shutdown", self.perform_shutdown)

    def perform_shutdown(self, message):
        """Request a system restart or shutdown.

        If the call to C{/sbin/shutdown} runs without errors the activity
        specified in the message will be responded as succeeded.  Otherwise,
        it will be responded as failed.
        """
        operation_id = message["operation-id"]
        reboot = message["reboot"]
        protocol = ShutdownProcessProtocol()
        protocol.set_timeout(self.registry.reactor)
        protocol.result.addCallback(self._respond_success, operation_id)
        protocol.result.addErrback(self._respond_failure, operation_id)
        command, args = self._get_command_and_args(protocol, reboot)
        self._process_factory.spawnProcess(protocol, command, args=args)

    def _respond_success(self, data, operation_id):
        logging.info("Shutdown request succeeded.")
        return self._respond(SUCCEEDED, data, operation_id)

    def _respond_failure(self, failure, operation_id):
        logging.info("Shutdown request failed.")
        return self._respond(FAILED, failure.value.data, operation_id)

    def _respond(self, status, data, operation_id):
        message = {"type": "operation-result",
                   "status": status,
                   "result-text": data,
                   "operation-id": operation_id}
        return self.registry.broker.send_message(message, True)

    def _get_command_and_args(self, protocol, reboot):
        """
        Returns a C{command, args} 2-tuple suitable for use with
        L{IReactorProcess.spawnProcess}.
        """
        minutes = "+%d" % (protocol.delay // 60,)
        if reboot:
            args = ["/sbin/shutdown", "-r", minutes,
                    "Landscape is rebooting the system"]
        else:
            args = ["/sbin/shutdown", "-h", minutes,
                    "Landscape is shutting down the system"]
        return "/sbin/shutdown", args


class ShutdownProcessProtocol(ProcessProtocol):
    """A ProcessProtocol for calling C{/sbin/shutdown}.

    C{shutdown} doesn't return immediately when a time specification is
    provided.  Failures are reported immediately after it starts and return a
    non-zero exit code.  The process protocol calls C{shutdown} and waits for
    failures for C{timeout} seconds.  If no failures are reported it fires
    C{result}'s callback with whatever output was received from the process.
    If failures are reported C{result}'s errback is fired.

    @ivar result: A L{Deferred} fired when C{shutdown} fails or
        succeeds.
    @ivar reboot: A flag indicating whether a shutdown or reboot should be
        performed.  Default is C{False}.
    @ivar delay: The time in seconds from now to schedule the shutdown.
        Default is 240 seconds.  The time will be converted to minutes using
        integer division when passed to C{shutdown}.
    """

    def __init__(self, reboot=False, delay=240):
        self.result = Deferred()
        self.reboot = reboot
        self.delay = delay
        self._data = []
        self._waiting = True

    def get_data(self):
        """Get the data printed by the subprocess."""
        return "".join(self._data)

    def set_timeout(self, reactor, timeout=10):
        """
        Set the error checking timeout, after which C{result}'s callback will
        be fired.
        """
        reactor.call_later(timeout, self._succeed)

    def childDataReceived(self, fd, data):
        """Some data was received from the child.

        Add it to our buffer to pass to C{result} when it's fired.
        """
        if self._waiting:
            self._data.append(data)

    def processEnded(self, reason):
        """Fire back the C{result} L{Deferred}.

        C{result}'s callback will be fired with the string of data received
        from the subprocess, or if the subprocess failed C{result}'s errback
        will be fired with the string of data received from the subprocess.
        """
        if self._waiting:
            if reason.check(ProcessDone):
                self._succeed()
            else:
                self.result.errback(ShutdownFailedError(self.get_data()))
                self._waiting = False

    def _succeed(self):
        """Fire C{result}'s callback with data accumulated from the process."""
        if self._waiting:
            self.result.callback(self.get_data())
            self._waiting = False