~free.ekanayaka/landscape-client/config-failure

« back to all changes in this revision

Viewing changes to landscape/package/tests/test_reporter.py

  • Committer: Free Ekanayaka
  • Date: 2010-04-28 13:38:56 UTC
  • mfrom: (182.1.30 amp-trunk)
  • Revision ID: free.ekanayaka@canonical.com-20100428133856-wo697ypl3e96cd6i
Merge amp-trunk [trivial]

Migrate our inter-process communication system from D-Bus to a Twisted AMP-based
protocol.

The change has been splitted into serveral branches that have been reviewed
separately in the LP bugs 570763, 570192, 568983, 568499, 567152, 564587,
564620, 562330, 561471, 559312, 558455, 556603, 552414, 546825, 544070, 539658,
537538, 535227, 499176, 531480, 499121, 514250, 499225 and 499018.

For sake of convenience here follows a summary of the changes introduced by
each branch:

  - Cleanup for having the base classes for monitor and manager plugins
    in landscape.monitor.plugin and landscape.manager.plugin.
  
  - Install the dbus bpickle extensions when starting a LandscapeService, letting
    plugins like the HAL/hardware one send dbus data types over AMP.
  
  - Make the monitor and manager test cases inherit from LandscapeTest instead of
    LandscapeIsolatedTest, as they don't need DBus anymore.
  
  - Make the landscape-config script use the AMP-based protocol to communicate
    with the broker. 

 -  Change the MethodCall protocol to split arguments in chunks of
    64k and transparently send them over several AMP commands.

 -  Make all task handlers derived from PackageTaskHandlers use the AMP-based
    protocol instead of D-Bus to communicate with the broker.
  
  - Port the behavior introduced in Bug #542215 to the AMP-based
    BrokerServer, which now broadcasts package-data-changed events.
  
  - Make the BrokerServiceHelper provide a 'live' RemoteBroker instead
    of a FakeRemoteBroker. The former BrokerServiceHelper has been renamed
    to FakeBrokerServiceHelper.
  
  - Migrate the watchdog to AMP, replacing the existing DBus-based
    communication mechanism with the AMP-based one.

  - Change is in the shutdown logic in the watchdog to be fully asynchronous,
    while before was relying on DBus being synchronous.
  
  - Add a 'factor' parameter to the RemoteComponentConnector.connect
    mehtod, for setting the pace at which service will try to reconnect.
  
  - Make services pass "wantPID" to the reactor.listenUNIX method, which
    cleans up left-over unix sockets on the filesystem (e.g. the former
    process died).
  
  - Change the landscape-{broker,monitor,manager} scripts to use the AMP-based versions
    of the associated services.
  
  - Move the BrokerConfiguration from landscape.broker.deployment to landscape.broker.config,
    for consistency with the monitor and the manager equivalent classes.

  - Replace the DBus-based MonitorHelper and ManagerHelper with their
    AMP-based equivalent.
  
  - Make the BrokerServer subscribe to the exchanger events, like "message",
   "impending-exchange", "exchange-failed", "registration-done", etc. and
    notifiy all connected clients about them.
        
  - Convert the usermanager and usermonitor communication mechanism from
    D-Bus to our AMP-based protocol.
  
  - Add a ManagerService class that takes care of starting the manager
    and make it listen to the correct Unix socket for incoming AMP
    connections.
 
  - Add a MonitorService class that takes care of starting the monitor
    and make it listen to the correct Unix socket for incoming AMP
    connections.

  - Add a BrokerService class that starts listening for incoming AMP connections
    on a Unix socket.
  
  - Add a BrokerClientProtocol for exposing the methods of a broker client
    to the broker server.

  - Decouple the broker client API logic from DBus, adding a new BrokerClient
    class implementing the behavior the broker expects for its clients.

  - Add a BrokerServerProtocol class that can be used by the broker
    clients (monitor and manager) to perform remote method calls
    on the BrokerServer.

  - Add a MethodCall-based protocol for basic communication between the
    various Landscape components.
  
  - Add a BrokerServer class implementing the same methods and
    interfaces of BrokerDBusObject, but not publishing them on
    DBus. The methods of this class will be exposed to the broker
    clients (the monitor and the manager) by an AMP-based protocol.

  - Add a reconnection mechanism to the MethodCall protocol makes it:
  
    * Keep trying to connect if the very fist attempt failed (for instance the
      remote process we're trying to contact is not yet ready to accept
      connections).
  
    * Try to reconnect if the connection drops (for instance the remote
      process died and the watchdog started it again).
  
    * Try to re-perform a failed MethodCall request as soon as the connection
      is up again, in case it failed because it was issued during a connection 
      blackout (for instance a monitor plugin tries to call a 
      RemoteBroker.send_message while the broker is restarting).
  
  - Make the MethodCall protocol able to cope with remote methods returning
    deferreds.
  
  - Add an AMP-based protocol to easily expose objects over AMP and perform
    remote method calls on them.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import glob
2
2
import sys
3
3
import os
4
 
import logging
5
4
import unittest
6
5
import time
7
6
 
15
14
    PackageReporterConfiguration)
16
15
from landscape.package import reporter
17
16
from landscape.package.facade import SmartFacade
18
 
from landscape.broker.remote import RemoteBroker
19
17
from landscape.package.tests.helpers import (
20
18
    SmartFacadeHelper, HASH1, HASH2, HASH3)
21
 
from landscape.tests.helpers import (
22
 
    LandscapeIsolatedTest, RemoteBrokerHelper)
 
19
from landscape.tests.helpers import LandscapeTest, BrokerServiceHelper
23
20
from landscape.tests.mocker import ANY
24
21
 
25
22
SAMPLE_LSB_RELEASE = "DISTRIB_CODENAME=codename\n"
38
35
        self.assertTrue(config.force_smart_update)
39
36
 
40
37
 
41
 
class PackageReporterTest(LandscapeIsolatedTest):
 
38
class PackageReporterTest(LandscapeTest):
42
39
 
43
 
    helpers = [SmartFacadeHelper, RemoteBrokerHelper]
 
40
    helpers = [SmartFacadeHelper, BrokerServiceHelper]
44
41
 
45
42
    def setUp(self):
46
 
        super(PackageReporterTest, self).setUp()
47
 
 
48
 
        self.store = PackageStore(self.makeFile())
49
 
        self.config = PackageReporterConfiguration()
50
 
        self.reporter = PackageReporter(self.store, self.facade, self.remote,
51
 
                                        self.config)
52
 
        self.config.data_path = self.makeDir()
53
 
        os.mkdir(self.config.package_directory)
 
43
 
 
44
        def set_up(ignored):
 
45
            self.store = PackageStore(self.makeFile())
 
46
            self.config = PackageReporterConfiguration()
 
47
            self.reporter = PackageReporter(
 
48
                self.store, self.facade, self.remote, self.config)
 
49
            self.config.data_path = self.makeDir()
 
50
            os.mkdir(self.config.package_directory)
 
51
 
 
52
        result = super(PackageReporterTest, self).setUp()
 
53
        return result.addCallback(set_up)
54
54
 
55
55
    def set_pkg2_upgrades_pkg1(self):
56
56
        previous = self.Facade.channels_reloaded
210
210
        deferred = Deferred()
211
211
        deferred.errback(Boom())
212
212
 
213
 
        remote_mock = self.mocker.patch(RemoteBroker)
 
213
        remote_mock = self.mocker.patch(self.reporter._broker)
214
214
        remote_mock.send_message(ANY, True)
215
215
        self.mocker.result(deferred)
216
216
        self.mocker.replay()
534
534
        self.reporter.smart_update_filename = self.makeFile(
535
535
            "#!/bin/sh\necho -n $@")
536
536
        os.chmod(self.reporter.smart_update_filename, 0755)
537
 
        logging_mock = self.mocker.replace("logging.debug")
538
 
        logging_mock("'%s' exited with status 0 (out='--after %d', err=''" % (
 
537
        debug_mock = self.mocker.replace("logging.debug")
 
538
        debug_mock("'%s' exited with status 0 (out='--after %d', err=''" % (
539
539
            self.reporter.smart_update_filename,
540
540
            self.reporter.smart_update_interval))
 
541
        warning_mock = self.mocker.replace("logging.warning")
 
542
        self.expect(warning_mock(ANY)).count(0)
541
543
        self.mocker.replay()
542
544
        deferred = Deferred()
543
545
 
544
546
        def do_test():
545
547
 
546
 
            def raiseme(x):
547
 
                raise Exception
548
 
 
549
 
            logging.warning = raiseme
550
548
            result = self.reporter.run_smart_update()
551
549
 
552
550
            def callback((out, err, code)):
700
698
        self.reporter.smart_update_filename = self.makeFile(
701
699
            "#!/bin/sh\necho\nexit 1")
702
700
        os.chmod(self.reporter.smart_update_filename, 0755)
 
701
        logging_mock = self.mocker.replace("logging.warning")
 
702
        self.expect(logging_mock(ANY)).count(0)
 
703
        self.mocker.replay()
703
704
        deferred = Deferred()
704
705
 
705
706
        def do_test():
706
707
 
707
 
            def raiseme(x):
708
 
                raise Exception
709
 
            logging.warning = raiseme
710
708
            result = self.reporter.run_smart_update()
711
709
 
712
710
            def callback((out, err, code)):
902
900
        deferred = Deferred()
903
901
        deferred.errback(Boom())
904
902
 
905
 
        remote_mock = self.mocker.patch(RemoteBroker)
 
903
        remote_mock = self.mocker.patch(self.reporter._broker)
906
904
        remote_mock.send_message(ANY, True)
907
905
        self.mocker.result(deferred)
908
906
        self.mocker.replay()
1334
1332
        self.mocker.result(succeed(False))
1335
1333
        reporter_mock.detect_package_locks_changes()
1336
1334
        self.mocker.result(succeed(True))
 
1335
        callback = self.mocker.mock()
 
1336
        callback()
1337
1337
        self.mocker.replay()
1338
1338
 
1339
 
        deferred = Deferred()
1340
 
        callback = lambda: deferred.callback(None)
1341
1339
        self.broker_service.reactor.call_on("package-data-changed", callback)
1342
 
        self.reporter.detect_changes()
1343
 
        return deferred
 
1340
        return self.reporter.detect_changes()
1344
1341
 
1345
1342
    def test_run(self):
1346
1343
        reporter_mock = self.mocker.patch(self.reporter)