~free.ekanayaka/landscape-client/karmic-1.5.4-0ubuntu0.9.10.0

« back to all changes in this revision

Viewing changes to landscape/configuration.py

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2010-06-28 18:07:18 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100628180718-g9l55c9c5bnch03b
Tags: 1.5.2.1-0ubuntu0.9.10.0
Filter duplicate network interfaces in get_active_interfaces (LP: #597000)

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
from ConfigParser import ConfigParser, Error as ConfigParserError
14
14
from StringIO import StringIO
15
15
 
16
 
from dbus.exceptions import DBusException
17
 
 
18
16
from landscape.lib.tag import is_valid_tag
19
17
 
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
25
 
 
 
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
29
26
 
30
27
 
31
28
class ConfigurationError(Exception):
32
29
    """Raised when required configuration values are missing."""
33
30
 
 
31
 
34
32
class ImportOptionError(ConfigurationError):
35
33
    """Raised when there are issues with handling the --import option."""
36
34
 
40
38
        stream = sys.stderr
41
39
    else:
42
40
        stream = sys.stdout
43
 
    stream.write(text+end)
 
41
    stream.write(text + end)
44
42
    stream.flush()
45
43
 
46
44
 
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 "
161
159
 
162
160
    def show_help(self, text):
163
161
        lines = text.strip().splitlines()
164
 
        print_text("\n"+"".join([line.strip()+"\n" for line in lines]))
 
162
        print_text("\n" + "".join([line.strip() + "\n" for line in lines]))
165
163
 
166
164
    def prompt_get_input(self, msg, required):
167
165
        """Prompt the user on the terminal for a value
215
213
                value2 = getpass.getpass("Please confirm: ")
216
214
            if value:
217
215
                if value != value2:
218
 
                   self.show_help("Passwords must match.")
 
216
                    self.show_help("Passwords must match.")
219
217
                else:
220
218
                    setattr(self.config, option, value)
221
219
                    break
359
357
        """
360
358
        invalid_tags = []
361
359
        if tagnames:
362
 
           tags  = [tag.strip() for tag in tagnames.split(",")]
363
 
           invalid_tags = [tag for tag in tags if not is_valid_tag(tag)]
 
360
            tags = [tag.strip() for tag in tagnames.split(",")]
 
361
            invalid_tags = [tag for tag in tags if not is_valid_tag(tag)]
364
362
        return invalid_tags
365
363
 
366
364
    def query_tags(self):
378
376
        while True:
379
377
            self.prompt("tags", "Tags", False)
380
378
            if self._get_invalid_tags(self.config.tags):
381
 
               self.show_help("Tag names may only contain alphanumeric "
 
379
                self.show_help("Tag names may only contain alphanumeric "
382
380
                              "characters.")
383
 
               self.config.tags = None # Reset for the next prompt
 
381
                self.config.tags = None # Reset for the next prompt
384
382
            else:
385
383
                break
386
384
 
490
488
        have totally mangled everything with mocker.  Otherwise bad things
491
489
        will happen.
492
490
    """
493
 
    from landscape.reactor import install
494
 
    install()
495
 
    if reactor is None:
496
 
        from twisted.internet import reactor
 
491
    reactor = TwistedReactor()
 
492
    exit_with_error = []
497
493
 
498
494
    # XXX: many of these reactor.stop() calls should also specify a non-0 exit
499
495
    # code, unless ok-no-register is passed.
500
496
 
 
497
    def stop():
 
498
        connector.disconnect()
 
499
        reactor.stop()
 
500
 
501
501
    def failure():
502
502
        print_text("Invalid account name or "
503
503
                   "registration password.", error=True)
504
 
        reactor.stop()
 
504
        stop()
505
505
 
506
506
    def success():
507
507
        print_text("System successfully registered.")
508
 
        reactor.stop()
 
508
        stop()
509
509
 
510
510
    def exchange_failure():
511
511
        print_text("We were unable to contact the server. "
513
513
                   "The landscape client will continue to try and contact "
514
514
                   "the server periodically.",
515
515
                   error=True)
516
 
        reactor.stop()
 
516
        stop()
517
517
 
518
518
    def handle_registration_errors(failure):
519
519
        # 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")
 
520
        failure.trap(InvalidCredentialsError, MethodCallError)
 
521
        connector.disconnect()
526
522
 
527
523
    def catch_all(failure):
528
524
        # We catch SecurityError here too, because on some DBUS configurations
529
525
        # if you try to connect to a dbus name that doesn't have a listener,
530
526
        # it'll try auto-starting the service, but then the StartServiceByName
531
527
        # 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)
535
 
        else:
536
 
            print_text(failure.getTraceback(), error=True)
537
 
            print_text("Unknown error occurred.", error=True)
538
 
        reactor.callLater(0, reactor.stop)
 
528
        print_text(failure.getTraceback(), error=True)
 
529
        print_text("Unknown error occurred.", error=True)
 
530
        stop()
539
531
 
540
532
    print_text("Please wait... ", "")
541
533
 
542
534
    time.sleep(2)
543
 
    try:
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)
 
535
 
 
536
    def got_connection(remote):
 
537
        handlers = {"registration-done": success,
 
538
                    "registration-failed": failure,
 
539
                    "exchange-failed": exchange_failure}
 
540
        deferreds = [
 
541
            remote.reload_configuration(),
 
542
            remote.call_on_event(handlers),
 
543
            remote.register().addErrback(handle_registration_errors)]
 
544
        # We consume errors here to ignore errors after the first one.
 
545
        # catch_all will be called for the very first deferred that fails.
 
546
        results = gather_results(deferreds, consume_errors=True)
 
547
        return results.addErrback(catch_all)
 
548
 
 
549
    def got_error(failure):
 
550
        print_text("There was an error communicating with the Landscape "
 
551
                   "client.", error=True)
548
552
        print_text("This machine will be registered with the provided "
549
553
                   "details when the client runs.", error=True)
550
 
        exit_code = 2
551
 
        if config.ok_no_register:
552
 
            exit_code = 0
553
 
        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.
560
 
    deferreds = [
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)
 
554
        if not config.ok_no_register:
 
555
            exit_with_error.append(2)
 
556
        stop()
 
557
 
 
558
    connector = RemoteBrokerConnector(reactor, config)
 
559
    result = connector.connect(max_retries=0, quiet=True)
 
560
    result.addCallback(got_connection)
 
561
    result.addErrback(got_error)
 
562
 
569
563
    reactor.run()
570
564
 
 
565
    if exit_with_error:
 
566
        sys.exit(exit_with_error[0])
 
567
 
 
568
    return result
 
569
 
571
570
 
572
571
def fetch_import_url(url):
573
572
    """Handle fetching of URLs passed to --url.