13
13
from ConfigParser import ConfigParser, Error as ConfigParserError
14
14
from StringIO import StringIO
16
from dbus.exceptions import DBusException
18
16
from landscape.lib.tag import is_valid_tag
20
18
from landscape.sysvconfig import SysVConfig, ProcessError
21
from landscape.lib.dbus_util import (
22
get_bus, NoReplyError, ServiceUnknownError, SecurityError)
19
from landscape.lib.amp import MethodCallError
23
20
from landscape.lib.twisted_util import gather_results
24
21
from landscape.lib.fetch import fetch, FetchError
22
from landscape.reactor import TwistedReactor
26
23
from landscape.broker.registration import InvalidCredentialsError
27
from landscape.broker.deployment import BrokerConfiguration
28
from landscape.broker.remote import RemoteBroker
24
from landscape.broker.config import BrokerConfiguration
25
from landscape.broker.amp import RemoteBrokerConnector
31
28
class ConfigurationError(Exception):
32
29
"""Raised when required configuration values are missing."""
34
32
class ImportOptionError(ConfigurationError):
35
33
"""Raised when there are issues with handling the --import option."""
120
118
parser.add_option("--import", dest="import_from",
121
119
metavar="FILENAME_OR_URL",
122
120
help="Filename or URL to import configuration from. "
123
"Imported options behave as if they were passed "
124
"in the command line, with precedence being "
125
"given to real command line options.")
121
"Imported options behave as if they were "
122
"passed in the command line, with precedence "
123
"being given to real command line options.")
126
124
parser.add_option("--script-users", metavar="USERS",
127
125
help="A comma-separated list of users to allow "
128
126
"scripts to run. To allow scripts to be run "
490
488
have totally mangled everything with mocker. Otherwise bad things
493
from landscape.reactor import install
496
from twisted.internet import reactor
491
reactor = TwistedReactor()
498
493
# XXX: many of these reactor.stop() calls should also specify a non-0 exit
499
494
# code, unless ok-no-register is passed.
497
connector.disconnect()
498
# For some obscure reason our TwistedReactor.stop method calls
499
# reactor.crash() instead of reactor.stop(), which doesn't work
500
# here. Maybe TwistedReactor.stop should simply use reactor.stop().
501
reactor.call_later(0, reactor._reactor.stop)
502
504
print_text("Invalid account name or "
503
505
"registration password.", error=True)
507
509
print_text("System successfully registered.")
510
512
def exchange_failure():
511
513
print_text("We were unable to contact the server. "
513
515
"The landscape client will continue to try and contact "
514
516
"the server periodically.",
518
520
def handle_registration_errors(failure):
519
521
# We'll get invalid credentials through the signal.
520
error = failure.trap(InvalidCredentialsError, NoReplyError)
521
# This event is fired here so we can catch this case where
522
# there is no reply in a test. In the normal case when
523
# running the client there is no trigger added for this event
524
# and it is essentially a noop.
525
reactor.fireSystemEvent("landscape-registration-error")
522
failure.trap(InvalidCredentialsError, MethodCallError)
523
connector.disconnect()
527
525
def catch_all(failure):
528
526
# We catch SecurityError here too, because on some DBUS configurations
529
527
# if you try to connect to a dbus name that doesn't have a listener,
530
528
# it'll try auto-starting the service, but then the StartServiceByName
531
529
# call can raise a SecurityError.
532
if failure.check(ServiceUnknownError, SecurityError):
533
print_text("Error occurred contacting Landscape Client. "
534
"Is it running?", error=True)
536
print_text(failure.getTraceback(), error=True)
537
print_text("Unknown error occurred.", error=True)
538
reactor.callLater(0, reactor.stop)
530
print_text(failure.getTraceback(), error=True)
531
print_text("Unknown error occurred.", error=True)
540
534
print_text("Please wait... ", "")
544
remote = RemoteBroker(get_bus(config.bus), retry_timeout=0)
545
except DBusException:
546
print_text("There was an error communicating with the Landscape client "
547
"via DBus.", error=True)
538
def got_connection(remote):
539
handlers = {"registration-done": success,
540
"registration-failed": failure,
541
"exchange-failed": exchange_failure}
543
remote.reload_configuration(),
544
remote.call_on_event(handlers),
545
remote.register().addErrback(handle_registration_errors)]
546
# We consume errors here to ignore errors after the first one.
547
# catch_all will be called for the very first deferred that fails.
549
results = gather_results(deferreds, consume_errors=True)
550
return results.addErrback(catch_all)
552
def got_error(failure):
553
print_text("There was an error communicating with the Landscape "
554
"client.", error=True)
548
555
print_text("This machine will be registered with the provided "
549
556
"details when the client runs.", error=True)
551
558
if config.ok_no_register:
553
560
sys.exit(exit_code)
554
# This is a bit unfortunate. Every method of remote returns a deferred,
555
# even stuff like connect_to_signal, because the fetching of the DBus
556
# object itself is asynchronous. We can *mostly* fire-and-forget these
557
# things, except that if the object isn't found, *all* of the deferreds
558
# will fail. To prevent unhandled errors, we need to collect them all up
559
# and add an errback.
561
remote.reload_configuration(),
562
remote.connect_to_signal("registration_done", success),
563
remote.connect_to_signal("registration_failed", failure),
564
remote.connect_to_signal("exchange_failed", exchange_failure),
565
remote.register().addErrback(handle_registration_errors)]
566
# We consume errors here to ignore errors after the first one. catch_all
567
# will be called for the very first deferred that fails.
568
gather_results(deferreds, consume_errors=True).addErrback(catch_all)
562
connector = RemoteBrokerConnector(reactor, config)
563
result = connector.connect(max_retries=0, quiet=True)
564
result.addCallback(got_connection)
565
result.addErrback(got_error)
572
572
def fetch_import_url(url):
573
573
"""Handle fetching of URLs passed to --url.