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

« back to all changes in this revision

Viewing changes to landscape/broker/registration.py

  • Committer: Bazaar Package Importer
  • Author(s): Rick Clark
  • Date: 2008-09-08 16:35:57 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080908163557-l3ixzj5dxz37wnw2
Tags: 1.0.18-0ubuntu1
New upstream release 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import logging
 
2
import socket
 
3
 
 
4
from twisted.internet.defer import Deferred
 
5
 
 
6
 
 
7
class InvalidCredentialsError(Exception):
 
8
    """
 
9
    Raised when an invalid account title and/or registration password
 
10
    is used with L{RegistrationManager.register}.
 
11
    """
 
12
 
 
13
 
 
14
def persist_property(name):
 
15
    def get(self):
 
16
        return self._persist.get(name)
 
17
    def set(self, value):
 
18
        self._persist.set(name, value)
 
19
    return property(get, set)
 
20
 
 
21
def config_property(name):
 
22
    def get(self):
 
23
        return getattr(self._config, name)
 
24
    return property(get)
 
25
 
 
26
 
 
27
class Identity(object):
 
28
    """Maintains details about the identity of this Landscape client."""
 
29
 
 
30
    secure_id = persist_property("secure-id")
 
31
    insecure_id = persist_property("insecure-id")
 
32
    computer_title = config_property("computer_title")
 
33
    account_name = config_property("account_name")
 
34
    registration_password = config_property("registration_password")
 
35
 
 
36
    def __init__(self, config, persist):
 
37
        self._config = config
 
38
        self._persist = persist.root_at("registration")
 
39
 
 
40
 
 
41
class RegistrationHandler(object):
 
42
    """
 
43
    An object from which registration can be requested of the server,
 
44
    and which will handle forced ID changes from the server.
 
45
 
 
46
    L{register} should be used to initial registration.
 
47
    """
 
48
 
 
49
    def __init__(self, identity, reactor, exchange, message_store):
 
50
        self._identity = identity
 
51
        self._reactor = reactor
 
52
        self._exchange = exchange
 
53
        self._message_store = message_store
 
54
        self._reactor.call_on("pre-exchange", self._handle_pre_exchange)
 
55
        self._reactor.call_on("exchange-done", self._handle_exchange_done)
 
56
        self._reactor.call_on("message", self._handle_message)
 
57
        self._should_register = None
 
58
 
 
59
    def should_register(self):
 
60
        id = self._identity
 
61
        return bool(not id.secure_id and id.computer_title and id.account_name
 
62
                    and self._message_store.accepts("register"))
 
63
 
 
64
    def register(self):
 
65
        """Attempt to register with the Landscape server.
 
66
 
 
67
        @return: A L{Deferred} which will either be fired with None if
 
68
            registration was successful or will fail with an
 
69
            L{InvalidCredentialsError} if not.
 
70
        """
 
71
        self._identity.secure_id = None
 
72
        self._identity.insecure_id = None
 
73
        # This was the original code, it works as well but it
 
74
        # takes longer due to the urgent exchange interval.
 
75
        #self._exchange.schedule_exchange(urgent=True)
 
76
        result = RegistrationResponse(self._reactor).deferred
 
77
        self._exchange.exchange()
 
78
        return result
 
79
 
 
80
    def _handle_message(self, message):
 
81
        message_type = message["type"]
 
82
        if message_type == "set-id":
 
83
            self._handle_set_id(message)
 
84
        elif message_type == "unknown-id":
 
85
            self._handle_unknown_id(message)
 
86
        elif message_type == "registration":
 
87
            self._handle_registration(message)
 
88
 
 
89
    def _handle_exchange_done(self):
 
90
        if self.should_register() and not self._should_register:
 
91
            # This was the original code, it works as well but it
 
92
            # takes longer due to the urgent exchange interval.
 
93
            #self._exchange.schedule_exchange(urgent=True)
 
94
            self._exchange.exchange()
 
95
 
 
96
    def _handle_pre_exchange(self):
 
97
        """
 
98
        An exchange is about to happen.  If we don't have a secure id
 
99
        already set, and we have the needed information available,
 
100
        queue a registration message with the server.
 
101
        """
 
102
 
 
103
        # The point of storing this flag is that if we should *not*
 
104
        # register now, and then after the exchange we *should*, we
 
105
        # schedule an urgent exchange again.  Without this flag we
 
106
        # would just spin trying to connect to the server when
 
107
        # something is clearly preventing the registration.
 
108
        self._should_register = self.should_register()
 
109
 
 
110
        if self._should_register:
 
111
            id = self._identity
 
112
 
 
113
            with_word = ["without", "with"][bool(id.registration_password)]
 
114
            logging.info("Queueing message to register with account %r %s "
 
115
                         "a password." % (id.account_name, with_word))
 
116
 
 
117
            self._message_store.delete_all_messages()
 
118
 
 
119
            message = {"type": "register",
 
120
                       "computer_title": id.computer_title,
 
121
                       "account_name": id.account_name,
 
122
                       "registration_password": id.registration_password,
 
123
                       "hostname": socket.gethostname()}
 
124
 
 
125
            self._exchange.send(message)
 
126
 
 
127
    def _handle_set_id(self, message):
 
128
        """
 
129
        Record and start using the secure and insecure IDs from the given
 
130
        message.
 
131
        """
 
132
        id = self._identity
 
133
        id.secure_id = message.get("id")
 
134
        id.insecure_id = message.get("insecure-id")
 
135
        logging.info("Using new secure-id ending with %s for account %s.",
 
136
                     id.secure_id[-10:], id.account_name)
 
137
        logging.debug("Using new secure-id: %s", id.secure_id)
 
138
        self._reactor.fire("registration-done")
 
139
        self._reactor.fire("resynchronize-clients")
 
140
 
 
141
    def _handle_registration(self, message):
 
142
        if message["info"] == "unknown-account":
 
143
            self._reactor.fire("registration-failed")
 
144
 
 
145
    def _handle_unknown_id(self, message):
 
146
        id = self._identity
 
147
        logging.info("Client has unknown secure-id for account %s."
 
148
                     % id.account_name)
 
149
        id.secure_id = None
 
150
        id.insecure_id = None
 
151
 
 
152
 
 
153
class RegistrationResponse(object):
 
154
    """A helper for dealing with the response of a single registration request.
 
155
 
 
156
    @ivar deferred: The L{Deferred} that will be fired as per
 
157
        L{RegistrationHandler.register}.
 
158
    """
 
159
 
 
160
    def __init__(self, reactor):
 
161
        self._reactor = reactor
 
162
        self._done_id = reactor.call_on("registration-done", self._done)
 
163
        self._failed_id = reactor.call_on("registration-failed", self._failed)
 
164
        self.deferred = Deferred()
 
165
 
 
166
    def _cancel_calls(self):
 
167
        self._reactor.cancel_call(self._done_id)
 
168
        self._reactor.cancel_call(self._failed_id)
 
169
 
 
170
    def _done(self):
 
171
        self.deferred.callback(None)
 
172
        self._cancel_calls()
 
173
 
 
174
    def _failed(self):
 
175
        self.deferred.errback(InvalidCredentialsError())
 
176
        self._cancel_calls()