Merge lp:~therve/landscape-client/lshw into lp:~landscape/landscape-client/trunk

Proposed by Thomas Herve
Status: Merged
Approved by: Mike Milner
Approved revision: 417
Merged at revision: 414
Proposed branch: lp:~therve/landscape-client/lshw
Merge into: lp:~landscape/landscape-client/trunk
Diff against target: 1816 lines (+103/-1159)
41 files modified
README (+1/-10)
dbus/landscape.conf (+0/-62)
debian/control (+2/-3)
debian/landscape-client.install (+0/-2)
debian/landscape-client.postinst (+0/-11)
debian/rules (+6/-9)
landscape/broker/exchange.py (+1/-3)
landscape/configuration.py (+0/-4)
landscape/hal.py (+0/-52)
landscape/lib/bpickle_dbus.py (+0/-63)
landscape/lib/tests/test_bpickle_dbus.py (+0/-75)
landscape/manager/config.py (+1/-1)
landscape/manager/hardwareinfo.py (+27/-0)
landscape/manager/tests/test_config.py (+2/-1)
landscape/manager/tests/test_hardwareinfo.py (+29/-0)
landscape/manager/tests/test_service.py (+3/-9)
landscape/message_schemas.py (+5/-1)
landscape/monitor/config.py (+4/-5)
landscape/monitor/hardwareinventory.py (+0/-114)
landscape/monitor/mountinfo.py (+2/-65)
landscape/monitor/tests/test_hardwareinventory.py (+0/-273)
landscape/monitor/tests/test_mountinfo.py (+0/-76)
landscape/monitor/tests/test_service.py (+3/-9)
landscape/package/releaseupgrader.py (+0/-21)
landscape/package/tests/test_releaseupgrader.py (+0/-54)
landscape/reactor.py (+2/-13)
landscape/service.py (+0/-6)
landscape/tests/test_configuration.py (+1/-1)
landscape/tests/test_hal.py (+0/-87)
landscape/tests/test_service.py (+0/-9)
landscape/tests/test_textmessage.py (+2/-2)
landscape/textmessage.py (+1/-2)
landscape/watchdog.py (+7/-10)
man/landscape-client.1 (+1/-6)
man/landscape-client.txt (+0/-2)
man/landscape-config.1 (+1/-6)
man/landscape-config.txt (+0/-2)
man/landscape-message.1 (+1/-5)
man/landscape-message.txt (+0/-1)
scripts/landscape-dbus-proxy (+0/-82)
setup.py (+1/-2)
To merge this branch: bzr merge lp:~therve/landscape-client/lshw
Reviewer Review Type Date Requested Status
Mike Milner (community) Approve
Alberto Donato Approve
Review via email: mp+84225@code.launchpad.net

Description of the change

The branch ought to be really small, but I removed the code for HAL support, and what was remaining of DBus.

The only part remaining is the old message schemas, but it needs to be removed on the server first.

To post a comment you must log in.
lp:~therve/landscape-client/lshw updated
416. By Thomas Herve

Lints

Revision history for this message
Alberto Donato (ack) wrote :

Looks good! +1

review: Approve
lp:~therve/landscape-client/lshw updated
417. By Thomas Herve

Fix man pages dates

Revision history for this message
Mike Milner (milner) wrote :

Looks good - I love it when code goes away! +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'README'
--- README 2008-12-22 17:21:04 +0000
+++ README 2011-12-02 09:56:24 +0000
@@ -23,14 +23,6 @@
2323
24== Developing ==24== Developing ==
2525
26To run the full test suite, you must have a dbus session bus
27running. If you don't have one (for example, if you're running the
28tests in an ssh session), run the following command:
29
30export DBUS_SESSION_BUS_ADDRESS=`dbus-daemon --print-address=1 --session --fork`
31
32Then your tests should pass.
33
34When you want to test the landscape client manually without management26When you want to test the landscape client manually without management
35features, you can simply run:27features, you can simply run:
3628
@@ -39,8 +31,7 @@
39This defaults to the 'landscape-client.conf' configuration file.31This defaults to the 'landscape-client.conf' configuration file.
4032
41When you want to test management features manually, you'll need to run as root.33When you want to test management features manually, you'll need to run as root.
42There's a configuration file 'root-client.conf' which specifies use of the34There's a configuration file 'root-client.conf'.
43system bus.
4435
45$ sudo ./scripts/landscape-client -c root-client.conf36$ sudo ./scripts/landscape-client -c root-client.conf
4637
4738
=== removed directory 'dbus'
=== removed file 'dbus/landscape.conf'
--- dbus/landscape.conf 2010-06-10 13:30:58 +0000
+++ dbus/landscape.conf 1970-01-01 00:00:00 +0000
@@ -1,62 +0,0 @@
1<!DOCTYPE busconfig PUBLIC
2 "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
3 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
4<busconfig>
5
6 <policy user="landscape">
7 <allow own="com.canonical.landscape.Broker" />
8 <allow own="com.canonical.landscape.Monitor" />
9
10 <allow send_destination="com.canonical.landscape.Broker" />
11 <allow receive_sender="com.canonical.landscape.Broker" />
12
13 <allow send_destination="com.canonical.landscape.Monitor" />
14 <allow receive_sender="com.canonical.landscape.Monitor" />
15
16 <allow send_destination="com.canonical.landscape.Manager" />
17 <allow receive_sender="com.canonical.landscape.Manager" />
18
19 <allow send_interface="org.freedesktop.Hal.Manager" />
20 <allow send_interface="org.freedesktop.Hal.Device" />
21
22 </policy>
23
24 <!-- this is a horrible hack -->
25 <policy user="haldaemon">
26
27 <allow receive_sender="com.canonical.landscape.Manager" />
28 <allow receive_sender="com.canonical.landscape.Monitor" />
29 <allow receive_sender="com.canonical.landscape.Broker" />
30
31 </policy>
32
33 <policy user="root">
34 <allow own="com.canonical.landscape.Manager" />
35
36 <allow send_destination="com.canonical.landscape.Broker" />
37 <allow receive_sender="com.canonical.landscape.Broker" />
38
39 <allow send_destination="com.canonical.landscape.Monitor" />
40 <allow receive_sender="com.canonical.landscape.Monitor" />
41
42 <allow send_destination="com.canonical.landscape.Manager" />
43 <allow receive_sender="com.canonical.landscape.Manager" />
44 </policy>
45
46 <policy context="default">
47 <deny own="com.canonical.landscape.Broker" />
48 <deny own="com.canonical.landscape.Monitor" />
49 <deny own="com.canonical.landscape.Manager" />
50
51 <deny send_destination="com.canonical.landscape.Broker" />
52 <deny receive_sender="com.canonical.landscape.Broker" />
53
54 <deny send_destination="com.canonical.landscape.Monitor" />
55 <deny receive_sender="com.canonical.landscape.Monitor" />
56
57 <deny send_destination="com.canonical.landscape.Manager" />
58 <deny receive_sender="com.canonical.landscape.Manager" />
59
60 </policy>
61
62</busconfig>
630
=== modified file 'debian/control'
--- debian/control 2011-01-31 11:04:34 +0000
+++ debian/control 2011-12-02 09:56:24 +0000
@@ -12,15 +12,14 @@
12Depends: ${python:Depends}, ${misc:Depends}, ${extra:Depends},12Depends: ${python:Depends}, ${misc:Depends}, ${extra:Depends},
13 python-gnupginterface,13 python-gnupginterface,
14 python-twisted-core,14 python-twisted-core,
15 python-gobject,
16 python-apt,15 python-apt,
17 ca-certificates,16 ca-certificates,
18 perl-modules,
19 python-gdbm,17 python-gdbm,
20 lsb-release,18 lsb-release,
21 lsb-base,19 lsb-base,
22 adduser,20 adduser,
23 bc21 bc,
22 lshw
24Suggests: ${extra:Suggests}23Suggests: ${extra:Suggests}
25Replaces: landscape-client (<= 1.0.23-0ubuntu0.8.10)24Replaces: landscape-client (<= 1.0.23-0ubuntu0.8.10)
26Description: The Landscape administration system client25Description: The Landscape administration system client
2726
=== modified file 'debian/landscape-client.install'
--- debian/landscape-client.install 2010-06-10 13:30:58 +0000
+++ debian/landscape-client.install 2011-12-02 09:56:24 +0000
@@ -8,7 +8,5 @@
8usr/bin/landscape-package-reporter8usr/bin/landscape-package-reporter
9usr/bin/landscape-release-upgrader9usr/bin/landscape-release-upgrader
10usr/bin/landscape-is-cloud-managed10usr/bin/landscape-is-cloud-managed
11usr/bin/landscape-dbus-proxy
12usr/share/landscape/cloud-default.conf11usr/share/landscape/cloud-default.conf
13etc/dbus-1/system.d/landscape.conf
14usr/lib/landscape12usr/lib/landscape
1513
=== modified file 'debian/landscape-client.postinst'
--- debian/landscape-client.postinst 2011-11-04 11:42:10 +0000
+++ debian/landscape-client.postinst 2011-12-02 09:56:24 +0000
@@ -123,17 +123,6 @@
123 if [ -e $very_old_cron_job ]; then123 if [ -e $very_old_cron_job ]; then
124 rm $very_old_cron_job124 rm $very_old_cron_job
125 fi125 fi
126
127 # Check if we're upgrading from a D-Bus version
128 if ! [ -z $2 ]; then
129 if dpkg --compare-versions $2 lt 1.5.1; then
130 # Launch a proxy service that will forward requests over DBus
131 # from the old package-changer to the new AMP-based broker. This
132 # is a one-off only needed for the DBus->AMP upgrade
133 start-stop-daemon -x /usr/bin/landscape-dbus-proxy -b -c landscape -u landscape -S
134 fi
135 fi
136
137 ;;126 ;;
138127
139 abort-upgrade|abort-remove|abort-deconfigure)128 abort-upgrade|abort-remove|abort-deconfigure)
140129
=== modified file 'debian/rules'
--- debian/rules 2011-11-04 11:42:10 +0000
+++ debian/rules 2011-12-02 09:56:24 +0000
@@ -60,7 +60,6 @@
60 install -D -o root -g root -m 644 debian/cloud-default.conf $(root_dir)/usr/share/landscape/cloud-default.conf60 install -D -o root -g root -m 644 debian/cloud-default.conf $(root_dir)/usr/share/landscape/cloud-default.conf
61 install -D -o root -g root -m 755 smart-update/smart-update $(root_dir)/usr/lib/landscape/smart-update61 install -D -o root -g root -m 755 smart-update/smart-update $(root_dir)/usr/lib/landscape/smart-update
62 install -D -o root -g root -m 755 apt-update/apt-update $(root_dir)/usr/lib/landscape/apt-update62 install -D -o root -g root -m 755 apt-update/apt-update $(root_dir)/usr/lib/landscape/apt-update
63 install -D -o root -g root -m 644 dbus/landscape.conf $(root_dir)/etc/dbus-1/system.d/landscape.conf
6463
65binary-indep:64binary-indep:
66# do nothing65# do nothing
@@ -84,24 +83,22 @@
8483
85ifneq (,$(findstring $(dist_release),"dapper"))84ifneq (,$(findstring $(dist_release),"dapper"))
86 # We need python2.4-pysqlite2 and a non-buggy libcurl3-gnutls on dapper85 # We need python2.4-pysqlite2 and a non-buggy libcurl3-gnutls on dapper
87 echo "extra:Depends=python2.4-pysqlite2, libcurl3-gnutls (>= 7.15.1-1ubuntu3), python-smartpm (>= 1.1.1~bzr20081010-0ubuntu1.6.06.0), python2.4-dbus" >> $(landscape_common_substvars)86 echo "extra:Depends=python2.4-pysqlite2, libcurl3-gnutls (>= 7.15.1-1ubuntu3), python-smartpm (>= 1.1.1~bzr20081010-0ubuntu1.6.06.0)" >> $(landscape_common_substvars)
88 echo "extra:Depends=python2.4-pycurl, hal" >> $(landscape_client_substvars)87 echo "extra:Depends=python2.4-pycurl" >> $(landscape_client_substvars)
89endif88endif
90ifneq (,$(findstring $(dist_release),"hardy"))89ifneq (,$(findstring $(dist_release),"hardy"))
91 # We want the smart 1.1.1 from the Landscape repository on hardy90 # We want the smart 1.1.1 from the Landscape repository on hardy
92 echo "extra:Depends=python-smartpm (>= 1.1.1~bzr20081010-0ubuntu1.8.04.1), python-dbus" >> $(landscape_common_substvars)91 echo "extra:Depends=python-smartpm (>= 1.1.1~bzr20081010-0ubuntu1.8.04.1)" >> $(landscape_common_substvars)
93 echo "extra:Depends=python-pycurl, hal" >> $(landscape_client_substvars)92 echo "extra:Depends=python-pycurl" >> $(landscape_client_substvars)
94endif93endif
95ifneq (,$(filter $(dist_release),karmic lucid maverick))94ifneq (,$(filter $(dist_release),karmic lucid maverick))
96 # We want libpam-modules in karmic, and smart 1.295 # We want libpam-modules in karmic, and smart 1.2
97 echo "extra:Depends=libpam-modules (>= 1.0.1-9ubuntu3), python-smartpm (>= 1.2-4), python-dbus" >> $(landscape_common_substvars)96 echo "extra:Depends=libpam-modules (>= 1.0.1-9ubuntu3), python-smartpm (>= 1.2-4)" >> $(landscape_common_substvars)
98 echo "extra:Depends=python-pycurl, hal" >> $(landscape_client_substvars)97 echo "extra:Depends=python-pycurl" >> $(landscape_client_substvars)
99endif98endif
100ifeq (,$(filter $(dist_release),dapper hardy karmic lucid maverick))99ifeq (,$(filter $(dist_release),dapper hardy karmic lucid maverick))
101 # Starting natty, no more hal or dbus
102 echo "extra:Depends=libpam-modules (>= 1.0.1-9ubuntu3), python-smartpm (>= 1.2-4)" >> $(landscape_common_substvars)100 echo "extra:Depends=libpam-modules (>= 1.0.1-9ubuntu3), python-smartpm (>= 1.2-4)" >> $(landscape_common_substvars)
103 echo "extra:Depends=python-pycurl, gir1.2-gudev-1.0 (>= 165-0ubuntu2)" >> $(landscape_client_substvars)101 echo "extra:Depends=python-pycurl, gir1.2-gudev-1.0 (>= 165-0ubuntu2)" >> $(landscape_client_substvars)
104 echo "extra:Suggests=python-dbus, hal" >> $(landscape_client_substvars)
105endif102endif
106ifeq (,$(filter $(dist_release),dapper hardy karmic))103ifeq (,$(filter $(dist_release),dapper hardy karmic))
107 # The python-image-store-proxy package is needed for the eucalyptus plugin104 # The python-image-store-proxy package is needed for the eucalyptus plugin
108105
=== modified file 'landscape/broker/exchange.py'
--- landscape/broker/exchange.py 2011-07-18 13:35:59 +0000
+++ landscape/broker/exchange.py 2011-12-02 09:56:24 +0000
@@ -422,9 +422,7 @@
422 handler(message)422 handler(message)
423423
424 def register_client_accepted_message_type(self, type):424 def register_client_accepted_message_type(self, type):
425 # stringify the type because it's a dbus.String. It should work425 self._client_accepted_types.add(type)
426 # anyway, but this is just for sanity and less confusing logs.
427 self._client_accepted_types.add(str(type))
428426
429 def get_client_accepted_message_types(self):427 def get_client_accepted_message_types(self):
430 return sorted(self._client_accepted_types)428 return sorted(self._client_accepted_types)
431429
=== modified file 'landscape/configuration.py'
--- landscape/configuration.py 2011-11-11 12:34:57 +0000
+++ landscape/configuration.py 2011-12-02 09:56:24 +0000
@@ -541,10 +541,6 @@
541 connector.disconnect()541 connector.disconnect()
542542
543 def catch_all(failure):543 def catch_all(failure):
544 # We catch SecurityError here too, because on some DBUS configurations
545 # if you try to connect to a dbus name that doesn't have a listener,
546 # it'll try auto-starting the service, but then the StartServiceByName
547 # call can raise a SecurityError.
548 print_text(failure.getTraceback(), error=True)544 print_text(failure.getTraceback(), error=True)
549 print_text("Unknown error occurred.", error=True)545 print_text("Unknown error occurred.", error=True)
550 stop()546 stop()
551547
=== removed file 'landscape/hal.py'
--- landscape/hal.py 2011-06-13 23:58:09 +0000
+++ landscape/hal.py 1970-01-01 00:00:00 +0000
@@ -1,52 +0,0 @@
1import logging
2
3from dbus import Interface, SystemBus
4from dbus.exceptions import DBusException
5
6
7class HALManager(object):
8
9 def __init__(self, bus=None):
10 try:
11 self._bus = bus or SystemBus()
12 manager = self._bus.get_object("org.freedesktop.Hal",
13 "/org/freedesktop/Hal/Manager")
14 except DBusException:
15 logging.error("Couldn't to connect to Hal via DBus")
16 self._manager = None
17 else:
18 self._manager = Interface(manager, "org.freedesktop.Hal.Manager")
19
20 def get_devices(self):
21 """Returns a list of HAL devices.
22
23 @note: If it wasn't possible to connect to HAL over DBus, then an
24 empty list will be returned. This can happen if the HAL or DBus
25 services are not running.
26 """
27 if not self._manager:
28 return []
29 devices = []
30 for udi in self._manager.GetAllDevices():
31 device = self._bus.get_object("org.freedesktop.Hal", udi)
32 device = Interface(device, "org.freedesktop.Hal.Device")
33 device = HALDevice(device)
34 devices.append(device)
35 return devices
36
37
38class HALDevice(object):
39
40 def __init__(self, device):
41 self._children = []
42 self._device = device
43 self.properties = device.GetAllProperties()
44 self.udi = self.properties["info.udi"]
45 self.parent = None
46
47 def add_child(self, device):
48 self._children.append(device)
49 device.parent = self
50
51 def get_children(self):
52 return self._children
530
=== removed file 'landscape/lib/bpickle_dbus.py'
--- landscape/lib/bpickle_dbus.py 2008-06-10 10:56:01 +0000
+++ landscape/lib/bpickle_dbus.py 1970-01-01 00:00:00 +0000
@@ -1,63 +0,0 @@
1"""
2Different versions of the Python DBus bindings return different types
3to represent integers, strings, lists, etc. Older versions return
4builtin Python types: C{int}, C{str}, C{list}, etc. Newer versions
5return DBus-specific wrappers: C{Int16}, C{String}, C{Array}, etc.
6Failures occur when DBus types are used because bpickle doesn't know
7that an C{Int16} is really an C{int} and that an C{Array} is really a
8C{list}.
9
10L{install} and L{uninstall} can install and remove extensions that
11make bpickle work with DBus types.
12"""
13
14import dbus
15
16from landscape.lib import bpickle
17
18
19def install():
20 """Install bpickle extensions for DBus types."""
21 for type, function in get_dbus_types():
22 bpickle.dumps_table[type] = function
23
24
25def uninstall():
26 """Uninstall bpickle extensions for DBus types."""
27 for type, function in get_dbus_types():
28 del bpickle.dumps_table[type]
29
30
31def dumps_utf8string(obj):
32 """
33 Convert the specified L{dbus.types.UTF8String} to bpickle's
34 representation for C{unicode} data.
35 """
36 return "u%s:%s" % (len(obj), obj)
37
38def dumps_double(obj):
39 """
40 Convert a dbus.types.Double into a floating point representation.
41 """
42 return "f%r;" % float(obj)
43
44def get_dbus_types():
45 """
46 Generator yields C{(type, bpickle_function)} for available DBus
47 types.
48 """
49 for (type_name, function) in [("Boolean", bpickle.dumps_bool),
50 ("Int16", bpickle.dumps_int),
51 ("UInt16", bpickle.dumps_int),
52 ("Int32", bpickle.dumps_int),
53 ("UInt32", bpickle.dumps_int),
54 ("Int64", bpickle.dumps_int),
55 ("UInt64", bpickle.dumps_int),
56 ("Double", dumps_double),
57 ("Array", bpickle.dumps_list),
58 ("Dictionary", bpickle.dumps_dict),
59 ("String", bpickle.dumps_unicode),
60 ("UTF8String", dumps_utf8string),]:
61 type = getattr(dbus.types, type_name, None)
62 if type is not None:
63 yield type, function
640
=== removed file 'landscape/lib/tests/test_bpickle_dbus.py'
--- landscape/lib/tests/test_bpickle_dbus.py 2011-07-05 05:09:11 +0000
+++ landscape/lib/tests/test_bpickle_dbus.py 1970-01-01 00:00:00 +0000
@@ -1,75 +0,0 @@
1import unittest
2
3from dbus.types import Double
4
5from landscape.lib import bpickle
6from landscape.lib.bpickle_dbus import install, uninstall, dumps_utf8string
7
8
9original = dict(bpickle.dumps_table)
10
11
12class DBusBPickleExtensionsTest(unittest.TestCase):
13
14 def tearDown(self):
15 # Mutate the original object back to the original version
16 # because rebinding it will cause bizarre failures.
17 bpickle.dumps_table.clear()
18 bpickle.dumps_table.update(original)
19
20 def test_install(self):
21 """
22 Installing bpickle extensions for DBus types should add to the
23 existing table. Existing bpickle mappings shouldn't be
24 changed.
25 """
26 install()
27 self.assertNotEquals(original, bpickle.dumps_table)
28 pre = set(original.iteritems())
29 post = set(bpickle.dumps_table.iteritems())
30 self.assertTrue(pre.issubset(post))
31
32 def test_uninstall(self):
33 """
34 Uninstalling bpickle extensions for DBus types should remove
35 whatever was added during installation. Extensions installed
36 by external components should not be affected by this
37 operation.
38 """
39 install()
40 self.assertFalse(object in bpickle.dumps_table)
41 bpickle.dumps_table[object] = lambda obj: None
42
43 uninstall()
44 pre = set(original.iteritems())
45 post = set(bpickle.dumps_table.iteritems())
46 self.assertTrue(pre.issubset(post))
47 self.assertTrue(object in bpickle.dumps_table)
48 self.assertTrue(len(original) + 1, len(bpickle.dumps_table))
49
50 def test_dumps_utf8string(self):
51 """
52 Dumping a L{dbus.types.UTF8String} should produce the same
53 bpickle output as would be produced for a C{unicode} value.
54 """
55 try:
56 from dbus.types import UTF8String
57
58 value = UTF8String("")
59 self.assertEqual(dumps_utf8string(value), "u0:")
60 value = UTF8String("Charlie!")
61 self.assertEqual(dumps_utf8string(value), "u8:Charlie!")
62 except ImportError:
63 pass
64
65 def test_dumps_double(self):
66 """
67 Dumping and restoring a L{dbus.types.Double} should result in the
68 same value.
69 """
70 install()
71 try:
72 value = Double(480.0, variant_level=1)
73 except TypeError:
74 value = Double(480.0)
75 self.assertAlmostEquals(bpickle.loads(bpickle.dumps(value)), 480.0)
760
=== modified file 'landscape/manager/config.py'
--- landscape/manager/config.py 2011-04-14 09:58:34 +0000
+++ landscape/manager/config.py 2011-12-02 09:56:24 +0000
@@ -5,7 +5,7 @@
55
66
7ALL_PLUGINS = ["ProcessKiller", "PackageManager", "UserManager",7ALL_PLUGINS = ["ProcessKiller", "PackageManager", "UserManager",
8 "ShutdownManager", "Eucalyptus", "AptSources"]8 "ShutdownManager", "Eucalyptus", "AptSources", "HardwareInfo"]
99
1010
11class ManagerConfiguration(Configuration):11class ManagerConfiguration(Configuration):
1212
=== added file 'landscape/manager/hardwareinfo.py'
--- landscape/manager/hardwareinfo.py 1970-01-01 00:00:00 +0000
+++ landscape/manager/hardwareinfo.py 2011-12-02 09:56:24 +0000
@@ -0,0 +1,27 @@
1import os
2
3from twisted.internet.utils import getProcessOutput
4
5from landscape.manager.plugin import ManagerPlugin
6
7
8class HardwareInfo(ManagerPlugin):
9 """A plugin to retrieve hardware information."""
10
11 message_type = "hardware-info"
12 run_interval = 60 * 60 * 24
13 run_immediately = True
14 command = "/usr/bin/lshw"
15
16 def run(self):
17 return self.registry.broker.call_if_accepted(
18 self.message_type, self.send_message)
19
20 def send_message(self):
21 result = getProcessOutput(
22 self.command, args=["-xml", "-quiet"], env=os.environ, path=None)
23 return result.addCallback(self._got_output)
24
25 def _got_output(self, output):
26 message = {"type": self.message_type, "data": output}
27 return self.registry.broker.send_message(message)
028
=== modified file 'landscape/manager/tests/test_config.py'
--- landscape/manager/tests/test_config.py 2011-07-05 05:09:11 +0000
+++ landscape/manager/tests/test_config.py 2011-12-02 09:56:24 +0000
@@ -12,7 +12,8 @@
12 def test_plugin_factories(self):12 def test_plugin_factories(self):
13 """By default all plugins are enabled."""13 """By default all plugins are enabled."""
14 self.assertEqual(["ProcessKiller", "PackageManager", "UserManager",14 self.assertEqual(["ProcessKiller", "PackageManager", "UserManager",
15 "ShutdownManager", "Eucalyptus", "AptSources"],15 "ShutdownManager", "Eucalyptus", "AptSources",
16 "HardwareInfo"],
16 ALL_PLUGINS)17 ALL_PLUGINS)
17 self.assertEqual(ALL_PLUGINS, self.config.plugin_factories)18 self.assertEqual(ALL_PLUGINS, self.config.plugin_factories)
1819
1920
=== added file 'landscape/manager/tests/test_hardwareinfo.py'
--- landscape/manager/tests/test_hardwareinfo.py 1970-01-01 00:00:00 +0000
+++ landscape/manager/tests/test_hardwareinfo.py 2011-12-02 09:56:24 +0000
@@ -0,0 +1,29 @@
1from landscape.tests.helpers import LandscapeTest, ManagerHelper
2
3from landscape.manager.hardwareinfo import HardwareInfo
4
5
6class HardwareInfoTests(LandscapeTest):
7 helpers = [ManagerHelper]
8
9 def setUp(self):
10 super(HardwareInfoTests, self).setUp()
11 self.info = HardwareInfo()
12 self.info.command = "/bin/echo"
13 self.manager.add(self.info)
14
15 service = self.broker_service
16 service.message_store.set_accepted_types(["hardware-info"])
17
18 def test_message(self):
19 """
20 L{HardwareInfo} sends the output of its command when running.
21 """
22 deferred = self.info.run()
23
24 def check(ignored):
25 self.assertMessages(
26 self.broker_service.message_store.get_pending_messages(),
27 [{"data": u"-xml -quiet\n", "type": "hardware-info"}])
28
29 return deferred.addCallback(check)
030
=== modified file 'landscape/manager/tests/test_service.py'
--- landscape/manager/tests/test_service.py 2011-07-05 05:09:11 +0000
+++ landscape/manager/tests/test_service.py 2011-12-02 09:56:24 +0000
@@ -1,4 +1,3 @@
1from landscape.tests.mocker import ANY
2from landscape.tests.helpers import (1from landscape.tests.helpers import (
3 LandscapeTest, FakeBrokerServiceHelper)2 LandscapeTest, FakeBrokerServiceHelper)
4from landscape.reactor import FakeReactor3from landscape.reactor import FakeReactor
@@ -42,15 +41,10 @@
42 The L{ManagerService.startService} method connects to the broker,41 The L{ManagerService.startService} method connects to the broker,
43 starts the plugins and register the manager as broker client.42 starts the plugins and register the manager as broker client.
44 """43 """
45 # FIXME: don't actually run the real register method, because at the
46 # moment the UserManager plugin still depends on DBus. We can probably
47 # drop this mocking once the AMP migration is completed.
48 for plugin in self.service.plugins:
49 plugin.register = self.mocker.mock()
50 plugin.register(ANY)
51 self.mocker.replay()
52
53 def stop_service(ignored):44 def stop_service(ignored):
45 for plugin in self.service.plugins:
46 if getattr(plugin, "stop", None) is not None:
47 plugin.stop()
54 [connector] = self.broker_service.broker.get_connectors()48 [connector] = self.broker_service.broker.get_connectors()
55 connector.disconnect()49 connector.disconnect()
56 self.service.stopService()50 self.service.stopService()
5751
=== modified file 'landscape/message_schemas.py'
--- landscape/message_schemas.py 2011-11-11 12:30:53 +0000
+++ landscape/message_schemas.py 2011-12-02 09:56:24 +0000
@@ -99,6 +99,10 @@
99 )})99 )})
100100
101101
102HARDWARE_INFO = Message("hardware-info", {
103 "data": utf8})
104
105
102LOAD_AVERAGE = Message("load-average", {106LOAD_AVERAGE = Message("load-average", {
103 "load-averages": List(Tuple(Int(), Float())),107 "load-averages": List(Tuple(Int(), Float())),
104 })108 })
@@ -392,7 +396,7 @@
392message_schemas = {}396message_schemas = {}
393for schema in [ACTIVE_PROCESS_INFO, COMPUTER_UPTIME, CLIENT_UPTIME,397for schema in [ACTIVE_PROCESS_INFO, COMPUTER_UPTIME, CLIENT_UPTIME,
394 OPERATION_RESULT, COMPUTER_INFO, DISTRIBUTION_INFO,398 OPERATION_RESULT, COMPUTER_INFO, DISTRIBUTION_INFO,
395 HARDWARE_INVENTORY, LOAD_AVERAGE, MEMORY_INFO,399 HARDWARE_INVENTORY, HARDWARE_INFO, LOAD_AVERAGE, MEMORY_INFO,
396 RESYNCHRONIZE, MOUNT_ACTIVITY, MOUNT_INFO, FREE_SPACE,400 RESYNCHRONIZE, MOUNT_ACTIVITY, MOUNT_INFO, FREE_SPACE,
397 REGISTER, REGISTER_CLOUD_VM, REGISTER_PROVISIONED_MACHINE,401 REGISTER, REGISTER_CLOUD_VM, REGISTER_PROVISIONED_MACHINE,
398 TEMPERATURE, PROCESSOR_INFO, USERS, PACKAGES, PACKAGE_LOCKS,402 TEMPERATURE, PROCESSOR_INFO, USERS, PACKAGES, PACKAGE_LOCKS,
399403
=== modified file 'landscape/monitor/config.py'
--- landscape/monitor/config.py 2010-05-04 17:23:45 +0000
+++ landscape/monitor/config.py 2011-12-02 09:56:24 +0000
@@ -1,11 +1,10 @@
1from landscape.deployment import Configuration1from landscape.deployment import Configuration
22
33
4ALL_PLUGINS = ["ActiveProcessInfo", "ComputerInfo", "HardwareInventory",4ALL_PLUGINS = ["ActiveProcessInfo", "ComputerInfo", "LoadAverage",
5 "LoadAverage", "MemoryInfo", "MountInfo", "ProcessorInfo",5 "MemoryInfo", "MountInfo", "ProcessorInfo", "Temperature",
6 "Temperature", "PackageMonitor", "UserMonitor",6 "PackageMonitor", "UserMonitor", "RebootRequired",
7 "RebootRequired", "AptPreferences", "NetworkActivity",7 "AptPreferences", "NetworkActivity", "NetworkDevice"]
8 "NetworkDevice"]
98
109
11class MonitorConfiguration(Configuration):10class MonitorConfiguration(Configuration):
1211
=== removed file 'landscape/monitor/hardwareinventory.py'
--- landscape/monitor/hardwareinventory.py 2011-01-28 09:37:10 +0000
+++ landscape/monitor/hardwareinventory.py 1970-01-01 00:00:00 +0000
@@ -1,114 +0,0 @@
1import logging
2
3from twisted.internet.defer import succeed
4
5from landscape.lib.log import log_failure
6
7from landscape.diff import diff
8from landscape.monitor.plugin import MonitorPlugin
9
10
11class HardwareInventory(MonitorPlugin):
12
13 persist_name = "hardware-inventory"
14
15 def __init__(self, hal_manager=None):
16 super(HardwareInventory, self).__init__()
17 self._persist_sets = []
18 self._persist_removes = []
19 self.enabled = True
20 try:
21 from landscape.hal import HALManager
22 except ImportError:
23 self.enabled = False
24 else:
25 self._hal_manager = hal_manager or HALManager()
26
27 def register(self, manager):
28 if not self.enabled:
29 return
30 super(HardwareInventory, self).register(manager)
31 self.call_on_accepted("hardware-inventory", self.exchange, True)
32
33 def send_message(self, urgent):
34 devices = self.create_message()
35 if devices:
36 message = {"type": "hardware-inventory", "devices": devices}
37 result = self.registry.broker.send_message(message, urgent=urgent)
38 result.addCallback(self.persist_data)
39 result.addErrback(log_failure)
40 logging.info("Queueing a message with hardware-inventory "
41 "information.")
42 else:
43 result = succeed(None)
44 return result
45
46 def exchange(self, urgent=False):
47 if not self.enabled:
48 return
49 return self.registry.broker.call_if_accepted("hardware-inventory",
50 self.send_message, urgent)
51
52 def persist_data(self, message_id):
53 for key, udi, value in self._persist_sets:
54 self._persist.set((key, udi), value)
55 for key in self._persist_removes:
56 self._persist.remove(key)
57 del self._persist_sets[:]
58 del self._persist_removes[:]
59 # This forces the registry to write the persistent store to disk
60 # This means that the persistent data reflects the state of the
61 # messages sent.
62 self.registry.flush()
63
64 def create_message(self):
65 # FIXME Using persist to keep track of changes here uses a
66 # fair amount of memory. On my machine a rough test seemed to
67 # indicate that memory usage grew by 1.3mb, about 12% of the
68 # overall process size. Look here to save memory.
69 del self._persist_sets[:]
70 del self._persist_removes[:]
71 devices = []
72 previous_devices = self._persist.get("devices", {})
73 current_devices = set()
74
75 for device in self._hal_manager.get_devices():
76 previous_properties = previous_devices.get(device.udi)
77 if not previous_properties:
78 devices.append(("create", device.properties))
79 elif previous_properties != device.properties:
80 creates, updates, deletes = diff(previous_properties,
81 device.properties)
82 devices.append(("update", device.udi,
83 creates, updates, deletes))
84 current_devices.add(device.udi)
85 self._persist_sets.append(
86 ("devices", device.udi, device.properties))
87
88 items_with_parents = {}
89 deleted_devices = set()
90 for udi, value in previous_devices.iteritems():
91 if udi not in current_devices:
92 if "info.parent" in value:
93 items_with_parents[udi] = value["info.parent"]
94 deleted_devices.add(udi)
95
96 # We remove the deleted devices from our persistent store it's
97 # only the information we're sending to the server that we're
98 # compressing.
99 for udi in deleted_devices:
100 self._persist_removes.append(("devices", udi))
101
102 # We can now flatten the list of devices we send to the server
103 # For each of the items_with_parents, if both the item and it's parent
104 # are in the deleted_devices set, then we can remove this item from the
105 # set.
106 minimal_deleted_devices = deleted_devices.copy()
107 for child, parent in items_with_parents.iteritems():
108 if child in deleted_devices and parent in deleted_devices:
109 minimal_deleted_devices.remove(child)
110 # We now build the deleted devices message
111 for udi in minimal_deleted_devices:
112 devices.append(("delete", udi))
113
114 return devices
1150
=== modified file 'landscape/monitor/mountinfo.py'
--- landscape/monitor/mountinfo.py 2011-04-08 09:01:42 +0000
+++ landscape/monitor/mountinfo.py 2011-12-02 09:56:24 +0000
@@ -15,7 +15,7 @@
1515
16 def __init__(self, interval=300, monitor_interval=60 * 60,16 def __init__(self, interval=300, monitor_interval=60 * 60,
17 mounts_file="/proc/mounts", create_time=time.time,17 mounts_file="/proc/mounts", create_time=time.time,
18 statvfs=None, hal_manager=None, mtab_file="/etc/mtab"):18 statvfs=None, mtab_file="/etc/mtab"):
19 self.run_interval = interval19 self.run_interval = interval
20 self._monitor_interval = monitor_interval20 self._monitor_interval = monitor_interval
21 self._create_time = create_time21 self._create_time = create_time
@@ -29,12 +29,6 @@
29 self._mount_info = []29 self._mount_info = []
30 self._mount_info_to_persist = None30 self._mount_info_to_persist = None
31 try:31 try:
32 from landscape.hal import HALManager
33 except ImportError:
34 self._hal_manager = hal_manager
35 else:
36 self._hal_manager = hal_manager or HALManager()
37 try:
38 from gi.repository import GUdev32 from gi.repository import GUdev
39 except ImportError:33 except ImportError:
40 self._gudev_client = None34 self._gudev_client = None
@@ -122,9 +116,7 @@
122 current_mount_points.add(mount_point)116 current_mount_points.add(mount_point)
123117
124 def _get_removable_devices(self):118 def _get_removable_devices(self):
125 if self._hal_manager is not None:119 if self._gudev_client is not None:
126 return self._get_hal_removable_devices()
127 elif self._gudev_client is not None:
128 return self._get_udev_removable_devices()120 return self._get_udev_removable_devices()
129 else:121 else:
130 return set()122 return set()
@@ -138,61 +130,6 @@
138 return False130 return False
139 return is_removable()131 return is_removable()
140132
141 def _get_hal_removable_devices(self):
142 block_devices = {} # {udi: [device, ...]}
143 children = {} # {parent_udi: [child_udi, ...]}
144 removable = set()
145
146 # We walk the list of devices building up a dictionary of all removable
147 # devices, and a mapping of {UDI => [block devices]}
148 # We differentiate between devices that we definitely know are
149 # removable and devices that _may_ be removable, depending on their
150 # parent device, e.g. /dev/sdb1 isn't flagged as removable, but
151 # /dev/sdb may well be removable.
152
153 # Unfortunately, HAL doesn't guarantee the order of the devices
154 # returned from get_devices(), so we may not know that a parent device
155 # is removable when we find it's first child.
156 devices = self._hal_manager.get_devices()
157 for device in devices:
158 block_device = device.properties.get("block.device")
159 if block_device:
160 if device.properties.get("storage.removable"):
161 removable.add(device.udi)
162
163 try:
164 block_devices[device.udi].append(block_device)
165 except KeyError:
166 block_devices[device.udi] = [block_device]
167
168 parent_udi = device.properties.get("info.parent")
169 if parent_udi is not None:
170 try:
171 children[parent_udi].append(device.udi)
172 except KeyError:
173 children[parent_udi] = [device.udi]
174
175 # Propagate the removable flag from each node all the way to
176 # its leaf children.
177 updated = True
178 while updated:
179 updated = False
180 for parent_udi in children:
181 if parent_udi in removable:
182 for child_udi in children[parent_udi]:
183 if child_udi not in removable:
184 removable.add(child_udi)
185 updated = True
186
187 # We've now seen _all_ devices, and have the definitive list of
188 # removable UDIs, so we can now find all the removable devices in the
189 # system.
190 removable_devices = set()
191 for udi in removable:
192 removable_devices.update(block_devices[udi])
193
194 return removable_devices
195
196 def _get_mount_info(self):133 def _get_mount_info(self):
197 """Generator yields local mount points worth recording data for."""134 """Generator yields local mount points worth recording data for."""
198 removable_devices = self._get_removable_devices()135 removable_devices = self._get_removable_devices()
199136
=== removed file 'landscape/monitor/tests/test_hardwareinventory.py'
--- landscape/monitor/tests/test_hardwareinventory.py 2011-07-05 05:09:11 +0000
+++ landscape/monitor/tests/test_hardwareinventory.py 1970-01-01 00:00:00 +0000
@@ -1,273 +0,0 @@
1from twisted.internet.defer import fail, succeed
2
3from landscape.monitor.hardwareinventory import HardwareInventory
4from landscape.tests.test_hal import MockHALManager, MockRealHALDevice
5from landscape.tests.helpers import LandscapeTest, MonitorHelper
6from landscape.tests.mocker import ANY
7from landscape.message_schemas import HARDWARE_INVENTORY
8
9
10class HardwareInventoryTest(LandscapeTest):
11
12 helpers = [MonitorHelper]
13
14 def setUp(self):
15 super(HardwareInventoryTest, self).setUp()
16 self.mstore.set_accepted_types(["hardware-inventory"])
17 devices = [MockRealHALDevice({u"info.udi": u"wubble",
18 u"info.product": u"Wubble"}),
19 MockRealHALDevice({u"info.udi": u"ooga",
20 u"info.product": u"Ooga"})]
21 self.hal_manager = MockHALManager(devices)
22 self.plugin = HardwareInventory(hal_manager=self.hal_manager)
23 self.monitor.add(self.plugin)
24
25 def assertSchema(self, devices):
26 full_message = {"type": "hardware-inventory", "devices": devices}
27 self.assertEqual(HARDWARE_INVENTORY.coerce(full_message),
28 full_message)
29
30 def test_hal_devices(self):
31 """
32 The first time the plugin runs it should report information
33 about all HAL devices found on the system. Every UDI provided
34 by HAL should be present in the devices list as is from HAL.
35 """
36 message = self.plugin.create_message()
37 actual_udis = [part[1][u"info.udi"] for part in message]
38 expected_udis = [device.udi for device
39 in self.hal_manager.get_devices()]
40 self.assertEqual(set(actual_udis), set(expected_udis))
41
42 def test_first_message(self):
43 """
44 The first time the plugin runs it should report information
45 about all HAL devices found on the system. All new devices
46 will be reported with 'create' actions.
47 """
48 message = self.plugin.create_message()
49 actions = [part[0] for part in message]
50 self.assertEqual(set(actions), set(["create"]))
51 self.assertSchema(message)
52
53 def test_no_changes(self):
54 """
55 Messages should not be created if hardware information is
56 unchanged since the last server exchange.
57 """
58 self.plugin.exchange()
59 self.assertNotEquals(len(self.mstore.get_pending_messages()), 0)
60
61 messages = self.mstore.get_pending_messages()
62 self.plugin.exchange()
63 self.assertEqual(self.mstore.get_pending_messages(), messages)
64
65 def test_update(self):
66 """
67 If a change is detected for a device that was previously
68 reported to the server, the changed device should be reported
69 with an 'update' action. Property changes are reported at a
70 key/value pair level.
71 """
72 self.hal_manager.devices = [
73 MockRealHALDevice({u"info.udi": u"wubble",
74 u"info.product": u"Wubble"})]
75 registry_mocker = self.mocker.replace(self.plugin.registry)
76 registry_mocker.flush()
77 self.mocker.count(2)
78 self.mocker.result(None)
79 self.mocker.replay()
80 message = self.plugin.create_message()
81 self.plugin.persist_data(None)
82 self.assertEqual(message, [("create", {u"info.udi": u"wubble",
83 u"info.product": u"Wubble"})])
84
85 self.hal_manager.devices[0] = MockRealHALDevice(
86 {u"info.udi": u"wubble", u"info.product": u"Ooga"})
87 message = self.plugin.create_message()
88 self.plugin.persist_data(None)
89 self.assertEqual(message, [("update", u"wubble",
90 {}, {u"info.product": u"Ooga"}, {})])
91 self.assertSchema(message)
92 self.assertEqual(self.plugin.create_message(), [])
93
94 def test_update_list(self):
95 """
96 An update should be sent to the server when a strlist device
97 property changes. No updates should be sent if a device is
98 unchanged.
99 """
100 self.hal_manager.devices = [
101 MockRealHALDevice({u"info.udi": u"wubble",
102 u"info.product": u"Wubble",
103 u"info.capabilities": [u"foo", u"bar"]})]
104
105 message = self.plugin.create_message()
106 self.plugin.persist_data(None)
107 self.assertEqual(message, [("create",
108 {u"info.udi": u"wubble",
109 u"info.product": u"Wubble",
110 u"info.capabilities": [u"foo", u"bar"]}),
111 ])
112
113 self.assertSchema(message)
114
115 self.hal_manager.devices[0] = MockRealHALDevice(
116 {u"info.udi": u"wubble", u"info.product": u"Wubble",
117 u"info.capabilities": [u"foo"]})
118 message = self.plugin.create_message()
119 self.plugin.persist_data(None)
120 self.assertEqual(message, [("update", u"wubble",
121 {}, {u"info.capabilities": [u"foo"]}, {}),
122 ])
123 self.assertSchema(message)
124
125 self.assertEqual(self.plugin.create_message(), [])
126
127 def test_update_complex(self):
128 """
129 The 'update' action reports property create, update and
130 delete changes.
131 """
132 self.hal_manager.devices = [
133 MockRealHALDevice({u"info.udi": u"wubble",
134 u"info.product": u"Wubble",
135 u"linux.acpi_type": 11})]
136
137 message = self.plugin.create_message()
138 self.plugin.persist_data(None)
139 self.assertEqual(message, [("create", {u"info.udi": u"wubble",
140 u"info.product": u"Wubble",
141 u"linux.acpi_type": 11})])
142
143 self.hal_manager.devices[0] = MockRealHALDevice(
144 {u"info.udi": u"wubble", u"info.product": u"Ooga",
145 u"info.category": u"unittest"})
146 message = self.plugin.create_message()
147 self.plugin.persist_data(None)
148 self.assertEqual(message, [("update", u"wubble",
149 {u"info.category": u"unittest"},
150 {u"info.product": u"Ooga"},
151 {u"linux.acpi_type": 11})])
152 self.assertSchema(message)
153
154 self.assertEqual(self.plugin.create_message(), [])
155
156 def test_delete(self):
157 """
158 If a device that was previously reported is no longer present
159 in a system a device entry should be created with a 'delete'
160 action.
161 """
162 self.hal_manager.devices = [
163 MockRealHALDevice({u"info.udi": u"wubble",
164 u"info.product": u"Wubble"}),
165 MockRealHALDevice({u"info.udi": u"ooga",
166 u"info.product": u"Ooga"})]
167
168 message = self.plugin.create_message()
169 self.plugin.persist_data(None)
170 self.assertEqual(message, [("create", {u"info.udi": u"wubble",
171 u"info.product": u"Wubble"}),
172 ("create", {u"info.udi": u"ooga",
173 u"info.product": u"Ooga"})])
174 self.assertSchema(message)
175
176 self.hal_manager.devices.pop(1)
177 message = self.plugin.create_message()
178 self.plugin.persist_data(None)
179 self.assertEqual(message, [("delete", u"ooga")])
180 self.assertSchema(message)
181 self.assertEqual(self.plugin.create_message(), [])
182
183 def test_minimal_delete(self):
184 self.hal_manager.devices = [
185 MockRealHALDevice({u"info.udi": u"wubble",
186 u"block.device": u"/dev/scd",
187 u"storage.removable": True}),
188 MockRealHALDevice({u"info.udi": u"wubble0",
189 u"block.device": u"/dev/scd0",
190 u"info.parent": u"wubble"}),
191 MockRealHALDevice({u"info.udi": u"wubble1",
192 u"block.device": u"/dev/scd1",
193 u"info.parent": u"wubble"}),
194 MockRealHALDevice({u"info.udi": u"wubble2",
195 u"block.device": u"/dev/scd1",
196 u"info.parent": u"wubble0"}),
197 MockRealHALDevice({u"info.udi": u"wubble3",
198 u"block.device": u"/dev/scd1",
199 u"info.parent": u"wubble2"})]
200
201 message = self.plugin.create_message()
202 self.plugin.persist_data(None)
203
204 del self.hal_manager.devices[:]
205
206 message = self.plugin.create_message()
207 self.plugin.persist_data(None)
208
209 self.assertEqual(message, [("delete", u"wubble")])
210 self.assertEqual(self.plugin.create_message(), [])
211
212 def test_resynchronize(self):
213 """
214 If a 'resynchronize' reactor event is fired, the plugin should
215 send a message that contains all data as if the server has
216 none.
217 """
218 self.plugin.exchange()
219 self.reactor.fire("resynchronize")
220 self.plugin.exchange()
221
222 messages = self.mstore.get_pending_messages()
223 self.assertEqual(len(messages), 2)
224 self.assertEqual(messages[0]["devices"], messages[1]["devices"])
225
226 def test_call_on_accepted(self):
227 remote_broker_mock = self.mocker.replace(self.remote)
228 remote_broker_mock.send_message(ANY, urgent=True)
229 self.mocker.result(succeed(None))
230 self.mocker.replay()
231
232 self.reactor.fire(("message-type-acceptance-changed",
233 "hardware-inventory"),
234 True)
235
236 def test_no_message_if_not_accepted(self):
237 """
238 Don't add any messages at all if the broker isn't currently
239 accepting their type.
240 """
241 self.mstore.set_accepted_types([])
242 self.reactor.advance(self.monitor.step_size * 2)
243 self.monitor.exchange()
244
245 self.mstore.set_accepted_types(["hardware-inventory"])
246 self.assertMessages(list(self.mstore.get_pending_messages()), [])
247
248 def test_do_not_persist_changes_when_send_message_fails(self):
249 """
250 When the plugin is run it persists data that it uses on
251 subsequent checks to calculate the delta to send. It should
252 only persist data when the broker confirms that the message
253 sent by the plugin has been sent.
254 """
255
256 class MyException(Exception):
257 pass
258
259 self.log_helper.ignore_errors(MyException)
260
261 broker_mock = self.mocker.replace(self.monitor.broker)
262 broker_mock.send_message(ANY, urgent=ANY)
263 self.mocker.result(fail(MyException()))
264 self.mocker.replay()
265
266 message = self.plugin.create_message()
267
268 def assert_message(message_id):
269 self.assertEqual(message, self.plugin.create_message())
270
271 result = self.plugin.exchange()
272 result.addCallback(assert_message)
273 return result
2740
=== modified file 'landscape/monitor/tests/test_mountinfo.py'
--- landscape/monitor/tests/test_mountinfo.py 2011-07-05 05:09:11 +0000
+++ landscape/monitor/tests/test_mountinfo.py 2011-12-02 09:56:24 +0000
@@ -3,7 +3,6 @@
3from twisted.internet.defer import succeed3from twisted.internet.defer import succeed
44
5from landscape.monitor.mountinfo import MountInfo5from landscape.monitor.mountinfo import MountInfo
6from landscape.tests.test_hal import MockHALManager, MockRealHALDevice
7from landscape.tests.helpers import LandscapeTest, mock_counter, MonitorHelper6from landscape.tests.helpers import LandscapeTest, mock_counter, MonitorHelper
8from landscape.tests.mocker import ANY7from landscape.tests.mocker import ANY
98
@@ -22,8 +21,6 @@
22 self.log_helper.ignore_errors("Typelib file for namespace")21 self.log_helper.ignore_errors("Typelib file for namespace")
2322
24 def get_mount_info(self, *args, **kwargs):23 def get_mount_info(self, *args, **kwargs):
25 hal_devices = kwargs.pop("hal_devices", [])
26 kwargs["hal_manager"] = MockHALManager(hal_devices)
27 if "statvfs" not in kwargs:24 if "statvfs" not in kwargs:
28 kwargs["statvfs"] = lambda path: (0,) * 1025 kwargs["statvfs"] = lambda path: (0,) * 10
29 return MountInfo(*args, **kwargs)26 return MountInfo(*args, **kwargs)
@@ -323,51 +320,8 @@
323 message = plugin.create_mount_info_message()320 message = plugin.create_mount_info_message()
324 self.assertEqual(message, None)321 self.assertEqual(message, None)
325322
326 def test_ignore_removable_partitions(self):
327 """
328 Partitions on removable devices don't directly report
329 storage.removable : True, but they do point to their parent and the
330 parent will be marked removable if appropriate.
331 """
332 devices = [MockRealHALDevice({"info.udi": "wubble",
333 "block.device": "/dev/scd",
334 "storage.removable": True}),
335 MockRealHALDevice({"info.udi": "wubble0",
336 "block.device": "/dev/scd0",
337 "info.parent": "wubble"})]
338
339 filename = self.makeFile("""\
340/dev/scd0 /media/Xerox_M750 iso9660 ro,nosuid,nodev,uid=1000,utf8 0 0
341""")
342 plugin = self.get_mount_info(mounts_file=filename, hal_devices=devices,
343 mtab_file=filename)
344 self.monitor.add(plugin)
345 plugin.run()
346
347 message = plugin.create_mount_info_message()
348 self.assertEqual(message, None)
349
350 def test_ignore_removable_devices(self):323 def test_ignore_removable_devices(self):
351 """324 """
352 The mount info plugin should only report data about
353 non-removable devices.
354 """
355 devices = [MockRealHALDevice({"info.udi": "wubble",
356 "block.device": "/dev/scd0",
357 "storage.removable": True})]
358 filename = self.makeFile("""\
359/dev/scd0 /media/Xerox_M750 iso9660 ro,nosuid,nodev,uid=1000,utf8 0 0
360""")
361 plugin = self.get_mount_info(mounts_file=filename, hal_devices=devices,
362 mtab_file=filename)
363 self.monitor.add(plugin)
364 plugin.run()
365
366 message = plugin.create_mount_info_message()
367 self.assertEqual(message, None)
368
369 def test_ignore_removable_devices_gudev(self):
370 """
371 The mount info plugin uses gudev to retrieve removable information325 The mount info plugin uses gudev to retrieve removable information
372 about devices.326 about devices.
373 """327 """
@@ -376,7 +330,6 @@
376""")330""")
377 plugin = self.get_mount_info(mounts_file=filename,331 plugin = self.get_mount_info(mounts_file=filename,
378 mtab_file=filename)332 mtab_file=filename)
379 plugin._hal_manager = None
380333
381 class MockDevice(object):334 class MockDevice(object):
382 def get_sysfs_attr_as_boolean(self, attr):335 def get_sysfs_attr_as_boolean(self, attr):
@@ -395,35 +348,6 @@
395 message = plugin.create_mount_info_message()348 message = plugin.create_mount_info_message()
396 self.assertEqual(message, None)349 self.assertEqual(message, None)
397350
398 def test_ignore_multiparented_removable_devices(self):
399 """
400 Some removable devices might be the grand-children of a device that is
401 marked as "storage.removable".
402 """
403 devices = [MockRealHALDevice({"info.udi": "wubble",
404 "block.device": "/dev/scd",
405 "storage.removable": True}),
406 MockRealHALDevice({"info.udi": "wubble0",
407 "block.device": "/dev/scd0",
408 "info.parent": "wubble"}),
409 MockRealHALDevice({"info.udi": "wubble0a",
410 "block.device": "/dev/scd0a",
411 "info.parent": "wubble0"}),
412 MockRealHALDevice({"info.udi": "wubble0b",
413 "block.device": "/dev/scd0b",
414 "info.parent": "wubble0"})]
415
416 filename = self.makeFile("""\
417/dev/scd0a /media/Xerox_M750 iso9660 ro,nosuid,nodev,uid=1000,utf8 0 0
418""")
419 plugin = self.get_mount_info(mounts_file=filename, hal_devices=devices,
420 mtab_file=filename)
421 self.monitor.add(plugin)
422 plugin.run()
423
424 message = plugin.create_mount_info_message()
425 self.assertEqual(message, None)
426
427 def test_sample_free_space(self):351 def test_sample_free_space(self):
428 """Test collecting information about free space."""352 """Test collecting information about free space."""
429 def statvfs(path, multiplier=mock_counter(1).next):353 def statvfs(path, multiplier=mock_counter(1).next):
430354
=== modified file 'landscape/monitor/tests/test_service.py'
--- landscape/monitor/tests/test_service.py 2011-07-05 05:09:11 +0000
+++ landscape/monitor/tests/test_service.py 2011-12-02 09:56:24 +0000
@@ -1,4 +1,3 @@
1from landscape.tests.mocker import ANY
2from landscape.tests.helpers import LandscapeTest, FakeBrokerServiceHelper1from landscape.tests.helpers import LandscapeTest, FakeBrokerServiceHelper
3from landscape.reactor import FakeReactor2from landscape.reactor import FakeReactor
4from landscape.monitor.config import MonitorConfiguration, ALL_PLUGINS3from landscape.monitor.config import MonitorConfiguration, ALL_PLUGINS
@@ -46,15 +45,10 @@
46 starts the plugins and register the monitor as broker client. It also45 starts the plugins and register the monitor as broker client. It also
47 start listening on its own socket for incoming connections.46 start listening on its own socket for incoming connections.
48 """47 """
49 # FIXME: don't actually run the real register method, because at the
50 # moment the UserMonitor plugin still depends on DBus. We can probably
51 # drop this mocking once the AMP migration is completed.
52 for plugin in self.service.plugins:
53 plugin.register = self.mocker.mock()
54 plugin.register(ANY)
55 self.mocker.replay()
56
57 def stop_service(ignored):48 def stop_service(ignored):
49 for plugin in self.service.plugins:
50 if getattr(plugin, "stop", None) is not None:
51 plugin.stop()
58 [connector] = self.broker_service.broker.get_connectors()52 [connector] = self.broker_service.broker.get_connectors()
59 connector.disconnect()53 connector.disconnect()
60 self.service.stopService()54 self.service.stopService()
6155
=== modified file 'landscape/package/releaseupgrader.py'
--- landscape/package/releaseupgrader.py 2011-07-06 12:34:11 +0000
+++ landscape/package/releaseupgrader.py 2011-12-02 09:56:24 +0000
@@ -188,32 +188,11 @@
188 config.add_section("NonInteractive")188 config.add_section("NonInteractive")
189 config.set("NonInteractive", "ForceOverwrite", "no")189 config.set("NonInteractive", "ForceOverwrite", "no")
190190
191 # Workaround for Bug #174148, which prevents dbus from restarting
192 # after a dapper->hardy upgrade
193 if not config.has_section("Distro"):
194 config.add_section("Distro")
195 if not config.has_option("Distro", "PostInstallScripts"):
196 config.set("Distro", "PostInstallScripts", "./dbus.sh")
197 else:
198 scripts = config.get("Distro", "PostInstallScripts")
199 scripts += ", ./dbus.sh"
200 config.set("Distro", "PostInstallScripts", scripts)
201
202 # Write config changes to disk191 # Write config changes to disk
203 fd = open(config_filename, "w")192 fd = open(config_filename, "w")
204 config.write(fd)193 config.write(fd)
205 fd.close()194 fd.close()
206195
207 # Generate the post-install script that starts DBus
208 dbus_sh_filename = os.path.join(upgrade_tool_directory,
209 "dbus.sh")
210 fd = open(dbus_sh_filename, "w")
211 fd.write("#!/bin/sh\n"
212 "/etc/init.d/dbus start\n"
213 "sleep 10\n")
214 fd.close()
215 os.chmod(dbus_sh_filename, 0755)
216
217 # On some releases the upgrade-tool doesn't support the allow third196 # On some releases the upgrade-tool doesn't support the allow third
218 # party environment variable, so this trick is needed to make it197 # party environment variable, so this trick is needed to make it
219 # possible to upgrade against testing client packages from the198 # possible to upgrade against testing client packages from the
220199
=== modified file 'landscape/package/tests/test_releaseupgrader.py'
--- landscape/package/tests/test_releaseupgrader.py 2011-11-15 09:57:05 +0000
+++ landscape/package/tests/test_releaseupgrader.py 2011-12-02 09:56:24 +0000
@@ -245,60 +245,6 @@
245 result.addCallback(check_result)245 result.addCallback(check_result)
246 return result246 return result
247247
248 def test_tweak_sets_dbus_start_script(self):
249 """
250 The L{ReleaseUpgrader.tweak} method adds to the upgrade-tool
251 configuration a little script that starts dbus after the upgrade.
252 """
253 config_filename = os.path.join(self.config.upgrade_tool_directory,
254 "DistUpgrade.cfg.dapper")
255 self.makeFile(path=config_filename,
256 content="[Distro]\n"
257 "PostInstallScripts=/foo.sh\n")
258
259 def check_result(ignored):
260 config = ConfigParser.ConfigParser()
261 config.read(config_filename)
262 self.assertEqual(config.get("Distro", "PostInstallScripts"),
263 "/foo.sh, ./dbus.sh")
264 dbus_sh = os.path.join(self.config.upgrade_tool_directory,
265 "dbus.sh")
266 self.assertFileContent(dbus_sh,
267 "#!/bin/sh\n"
268 "/etc/init.d/dbus start\n"
269 "sleep 10\n")
270
271 result = self.upgrader.tweak("dapper")
272 result.addCallback(check_result)
273 return result
274
275 def test_tweak_sets_dbus_start_script_with_no_post_install_scripts(self):
276 """
277 The L{ReleaseUpgrader.tweak} method adds to the upgrade-tool
278 configuration a little script that starts dbus after the upgrade. This
279 works even when the config file doesn't have a PostInstallScripts entry
280 yet.
281 """
282 config_filename = os.path.join(self.config.upgrade_tool_directory,
283 "DistUpgrade.cfg.dapper")
284 self.makeFile(path=config_filename, content="")
285
286 def check_result(ignored):
287 config = ConfigParser.ConfigParser()
288 config.read(config_filename)
289 self.assertEqual(config.get("Distro", "PostInstallScripts"),
290 "./dbus.sh")
291 dbus_sh = os.path.join(self.config.upgrade_tool_directory,
292 "dbus.sh")
293 self.assertFileContent(dbus_sh,
294 "#!/bin/sh\n"
295 "/etc/init.d/dbus start\n"
296 "sleep 10\n")
297
298 result = self.upgrader.tweak("dapper")
299 result.addCallback(check_result)
300 return result
301
302 def test_default_logs_directory(self):248 def test_default_logs_directory(self):
303 """249 """
304 The default directory for the upgrade-tool logs is the system one.250 The default directory for the upgrade-tool logs is the system one.
305251
=== modified file 'landscape/reactor.py'
--- landscape/reactor.py 2011-07-21 23:55:47 +0000
+++ landscape/reactor.py 2011-12-02 09:56:24 +0000
@@ -16,10 +16,6 @@
16 """Raised when an invalid ID is used with reactor.cancel_call()."""16 """Raised when an invalid ID is used with reactor.cancel_call()."""
1717
1818
19class CallHookError(Exception):
20 """Raised when hooking on a reactor incorrectly."""
21
22
23class EventID(object):19class EventID(object):
24 """Unique identifier for an event handler.20 """Unique identifier for an event handler.
2521
@@ -147,13 +143,6 @@
147 except Exception, e:143 except Exception, e:
148 logging.exception(e)144 logging.exception(e)
149145
150 def _hook_threaded_callbacks(self):
151 id = self.call_every(0.5, self._run_threaded_callbacks)
152 self._run_threaded_callbacks_id = id
153
154 def _unhook_threaded_callbacks(self):
155 self.cancel_call(self._run_threaded_callbacks_id)
156
157146
158class UnixReactorMixin(object):147class UnixReactorMixin(object):
159148
@@ -289,12 +278,12 @@
289 try:278 try:
290 # is it an IP address?279 # is it an IP address?
291 socket.inet_aton(hostname)280 socket.inet_aton(hostname)
292 except socket.error: # no281 except socket.error: # no
293 if hostname in self.hosts:282 if hostname in self.hosts:
294 return succeed(self.hosts[hostname])283 return succeed(self.hosts[hostname])
295 else:284 else:
296 return fail(DNSLookupError(hostname))285 return fail(DNSLookupError(hostname))
297 else: # yes286 else: # yes
298 return succeed(hostname)287 return succeed(hostname)
299288
300289
301290
=== modified file 'landscape/service.py'
--- landscape/service.py 2011-10-13 06:53:24 +0000
+++ landscape/service.py 2011-12-02 09:56:24 +0000
@@ -28,12 +28,6 @@
2828
29 def __init__(self, config):29 def __init__(self, config):
30 self.config = config30 self.config = config
31 try:
32 from landscape.lib import bpickle_dbus
33 except ImportError:
34 pass
35 else:
36 bpickle_dbus.install()
37 self.reactor = self.reactor_factory()31 self.reactor = self.reactor_factory()
38 if self.persist_filename:32 if self.persist_filename:
39 self.persist = get_versioned_persist(self)33 self.persist = get_versioned_persist(self)
4034
=== modified file 'landscape/tests/test_configuration.py'
--- landscape/tests/test_configuration.py 2011-11-14 17:28:04 +0000
+++ landscape/tests/test_configuration.py 2011-12-02 09:56:24 +0000
@@ -1856,7 +1856,7 @@
18561856
1857 def test_register_bus_connection_failure_ok_no_register(self):1857 def test_register_bus_connection_failure_ok_no_register(self):
1858 """1858 """
1859 Exit code 0 will be returned if we can't contact Landscape via DBus and1859 Exit code 0 will be returned if we can't contact Landscape and
1860 --ok-no-register was passed.1860 --ok-no-register was passed.
1861 """1861 """
1862 print_text_mock = self.mocker.replace(print_text)1862 print_text_mock = self.mocker.replace(print_text)
18631863
=== removed file 'landscape/tests/test_hal.py'
--- landscape/tests/test_hal.py 2011-07-05 05:09:11 +0000
+++ landscape/tests/test_hal.py 1970-01-01 00:00:00 +0000
@@ -1,87 +0,0 @@
1from dbus import SystemBus, Interface
2from dbus.exceptions import DBusException
3
4from landscape.hal import HALDevice, HALManager
5from landscape.tests.helpers import LandscapeTest
6
7
8class HALManagerTest(LandscapeTest):
9
10 def setUp(self):
11 super(HALManagerTest, self).setUp()
12 self.bus = SystemBus()
13
14 def test_get_devices(self):
15 """
16 A HALManager can return a flat list of devices. All available
17 devices should be included in the returned list.
18 """
19 devices = HALManager().get_devices()
20 manager = self.bus.get_object("org.freedesktop.Hal",
21 "/org/freedesktop/Hal/Manager")
22 manager = Interface(manager, "org.freedesktop.Hal.Manager")
23 expected_devices = manager.GetAllDevices()
24 actual_devices = [device.udi for device in devices]
25 self.assertEqual(set(expected_devices), set(actual_devices))
26
27 def test_get_devices_with_dbus_error(self):
28 """
29 If the L{HALManager} fails connecting to HAL over D-Bus, then the
30 L{HALManager.get_devices} method returns an empty list.
31 """
32 self.log_helper.ignore_errors("Couldn't to connect to Hal via DBus")
33 bus = self.mocker.mock()
34 bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager")
35 self.mocker.throw(DBusException())
36 self.mocker.replay()
37 devices = HALManager(bus=bus).get_devices()
38 self.assertEqual(devices, [])
39
40 def test_get_devices_with_no_server(self):
41 """
42 If the L{HALManager} fails connecting to HAL over D-Bus, for example
43 because the DBus server is not running at all, then the
44 L{HALManager.get_devices} method returns an empty list.
45 """
46 self.log_helper.ignore_errors("Couldn't to connect to Hal via DBus")
47 bus_mock = self.mocker.replace("dbus.SystemBus")
48 bus_mock()
49 self.mocker.throw(DBusException())
50 self.mocker.replay()
51 devices = HALManager().get_devices()
52 self.assertEqual(devices, [])
53
54
55class MockHALManager(object):
56
57 def __init__(self, devices):
58 self.devices = devices
59
60 def get_devices(self):
61 return [HALDevice(device) for device in self.devices]
62
63
64class MockRealHALDevice(object):
65
66 def __init__(self, properties):
67 self._properties = properties
68 self.udi = properties.get("info.udi", "fake_udi")
69
70 def GetAllProperties(self):
71 return self._properties
72
73
74class HALDeviceTest(LandscapeTest):
75
76 def test_init(self):
77 device = HALDevice(MockRealHALDevice({"info.udi": "wubble"}))
78 self.assertEqual(device.properties, {"info.udi": "wubble"})
79 self.assertEqual(device.udi, "wubble")
80 self.assertEqual(device.parent, None)
81
82 def test_add_child(self):
83 parent = HALDevice(MockRealHALDevice({"info.udi": "wubble"}))
84 child = HALDevice(MockRealHALDevice({"info.udi": "ooga"}))
85 parent.add_child(child)
86 self.assertEqual(parent.get_children(), [child])
87 self.assertEqual(child.parent, parent)
880
=== modified file 'landscape/tests/test_service.py'
--- landscape/tests/test_service.py 2011-07-05 05:09:11 +0000
+++ landscape/tests/test_service.py 2011-12-02 09:56:24 +0000
@@ -56,15 +56,6 @@
56 service = TestService(self.config)56 service = TestService(self.config)
57 self.assertFalse(hasattr(service, "persist"))57 self.assertFalse(hasattr(service, "persist"))
5858
59 def test_install_bpickle_dbus(self):
60 """
61 A L{LandscapeService} installs the DBus extensions of bpickle.
62 """
63 dbus_mock = self.mocker.replace("landscape.lib.bpickle_dbus.install")
64 dbus_mock()
65 self.mocker.replay()
66 TestService(self.config)
67
68 def test_usr1_rotates_logs(self):59 def test_usr1_rotates_logs(self):
69 """60 """
70 SIGUSR1 should cause logs to be reopened.61 SIGUSR1 should cause logs to be reopened.
7162
=== modified file 'landscape/tests/test_textmessage.py'
--- landscape/tests/test_textmessage.py 2011-07-05 05:09:11 +0000
+++ landscape/tests/test_textmessage.py 2011-12-02 09:56:24 +0000
@@ -13,8 +13,8 @@
1313
14 def test_send_message(self):14 def test_send_message(self):
15 """15 """
16 L{send_message} should send a message of type16 L{send_message} should send a message of type C{text-message} to the
17 C{text-message} to the landscape dbus messaging service.17 landscape messaging service.
18 """18 """
19 service = self.broker_service19 service = self.broker_service
20 service.message_store.set_accepted_types(["text-message"])20 service.message_store.set_accepted_types(["text-message"])
2121
=== modified file 'landscape/textmessage.py'
--- landscape/textmessage.py 2010-04-23 10:57:57 +0000
+++ landscape/textmessage.py 2011-12-02 09:56:24 +0000
@@ -1,7 +1,6 @@
1"""1"""
2Support code for the C{landscape-message} utility, which sends a text2Support code for the C{landscape-message} utility, which sends a text
3message to the Landscape web UI via the landscape-client's dbus3message to the Landscape web UI via the landscape-client's messaging service.
4messaging service (see L{landscape.plugins.dbus_message}).
5"""4"""
65
7import sys6import sys
87
=== modified file 'landscape/watchdog.py'
--- landscape/watchdog.py 2011-10-13 06:53:24 +0000
+++ landscape/watchdog.py 2011-12-02 09:56:24 +0000
@@ -57,8 +57,6 @@
57 @cvar program: The name of the executable program that will start this57 @cvar program: The name of the executable program that will start this
58 daemon.58 daemon.
59 @cvar username: The name of the user to switch to, by default.59 @cvar username: The name of the user to switch to, by default.
60 @cvar service: The DBus service name that the program will be expected to
61 listen on.
62 @cvar max_retries: The maximum number of retries before giving up when60 @cvar max_retries: The maximum number of retries before giving up when
63 trying to connect to the watched daemon.61 trying to connect to the watched daemon.
64 @cvar factor: The factor by which the delay between subsequent connection62 @cvar factor: The factor by which the delay between subsequent connection
@@ -173,8 +171,7 @@
173171
174 def is_running(self):172 def is_running(self):
175 # FIXME Error cases may not be handled in the best possible way173 # FIXME Error cases may not be handled in the best possible way
176 # here. We're basically return False if any error happens from the174 # here. We're basically return False if any error happens.
177 # dbus ping.
178 return self._connect_and_call("ping")175 return self._connect_and_call("ping")
179176
180 def wait(self):177 def wait(self):
@@ -362,7 +359,7 @@
362 def start(self):359 def start(self):
363 """360 """
364 Start all daemons. The broker will be started first, and no other361 Start all daemons. The broker will be started first, and no other
365 daemons will be started before it is running and responding to DBUS362 daemons will be started before it is running and responding to
366 messages.363 messages.
367364
368 @return: A deferred which fires when all services have successfully365 @return: A deferred which fires when all services have successfully
@@ -463,11 +460,11 @@
463460
464def daemonize():461def daemonize():
465 # See http://www.steve.org.uk/Reference/Unix/faq_2.html#SEC16462 # See http://www.steve.org.uk/Reference/Unix/faq_2.html#SEC16
466 if os.fork(): # launch child and...463 if os.fork(): # launch child and...
467 os._exit(0) # kill off parent464 os._exit(0) # kill off parent
468 os.setsid()465 os.setsid()
469 if os.fork(): # launch child and...466 if os.fork(): # launch child and...
470 os._exit(0) # kill off parent again.467 os._exit(0) # kill off parent again.
471 # some argue that this umask should be 0, but that's annoying.468 # some argue that this umask should be 0, but that's annoying.
472 os.umask(077)469 os.umask(077)
473 null = os.open('/dev/null', os.O_RDWR)470 null = os.open('/dev/null', os.O_RDWR)
@@ -505,7 +502,7 @@
505 error("ERROR: The following daemons are already running: %s"502 error("ERROR: The following daemons are already running: %s"
506 % (", ".join(x.program for x in running_daemons)))503 % (", ".join(x.program for x in running_daemons)))
507 self.exit_code = 1504 self.exit_code = 1
508 reactor.crash() # so stopService isn't called.505 reactor.crash() # so stopService isn't called.
509 return506 return
510 self._daemonize()507 self._daemonize()
511 info("Watchdog watching for daemons.")508 info("Watchdog watching for daemons.")
512509
=== modified file 'man/landscape-client.1'
--- man/landscape-client.1 2010-01-18 17:26:36 +0000
+++ man/landscape-client.1 2011-12-02 09:56:24 +0000
@@ -1,5 +1,5 @@
1.\"Text automatically generated by txt2man1.\"Text automatically generated by txt2man
2.TH landscape-client "18 January 2010" "" ""2.TH landscape-client 1 "02 December 2011" "" ""
3.SH NAME3.SH NAME
4\fBlandscape-client \fP- Landscape system client4\fBlandscape-client \fP- Landscape system client
5\fB5\fB
@@ -35,11 +35,6 @@
35\fIoptions\fP override settings from the file).35\fIoptions\fP override settings from the file).
36.TP36.TP
37.B37.B
38\fB--bus\fP=BUS
39Which DBUS bus to use. One of 'session' or
40'system'.
41.TP
42.B
43\fB-d\fP PATH, \fB--data-path\fP=PATH38\fB-d\fP PATH, \fB--data-path\fP=PATH
44The directory to store data files in.39The directory to store data files in.
45.TP40.TP
4641
=== modified file 'man/landscape-client.txt'
--- man/landscape-client.txt 2010-01-18 16:33:51 +0000
+++ man/landscape-client.txt 2011-12-02 09:56:24 +0000
@@ -17,8 +17,6 @@
17 -h, --help Show this help message and exit.17 -h, --help Show this help message and exit.
18 -c FILE, --config=FILE Use config from this file (any command line 18 -c FILE, --config=FILE Use config from this file (any command line
19 options override settings from the file).19 options override settings from the file).
20 --bus=BUS Which DBUS bus to use. One of 'session' or
21 'system'.
22 -d PATH, --data-path=PATH The directory to store data files in.20 -d PATH, --data-path=PATH The directory to store data files in.
23 -q, --quiet Do not log to the standard output.21 -q, --quiet Do not log to the standard output.
24 -l FILE, --log-dir=FILE The directory to write log files to.22 -l FILE, --log-dir=FILE The directory to write log files to.
2523
=== modified file 'man/landscape-config.1'
--- man/landscape-config.1 2010-01-18 17:26:36 +0000
+++ man/landscape-config.1 2011-12-02 09:56:24 +0000
@@ -1,5 +1,5 @@
1.\"Text automatically generated by txt2man1.\"Text automatically generated by txt2man
2.TH landscape-config "18 January 2010" "" ""2.TH landscape-config 1 "02 December 2011" "" ""
3.SH NAME3.SH NAME
4\fBlandscape-config \fP- configure the Landscape management client4\fBlandscape-config \fP- configure the Landscape management client
5\fB5\fB
@@ -46,11 +46,6 @@
46'/etc/landscape/client.conf').46'/etc/landscape/client.conf').
47.TP47.TP
48.B48.B
49\fB--bus\fP=BUS
50Which DBUS bus to use. One of 'session' or 'system'
51(default: 'system').
52.TP
53.B
54\fB-d\fP PATH, \fB--data-path\fP=PATH49\fB-d\fP PATH, \fB--data-path\fP=PATH
55The directory to store data files in (default:50The directory to store data files in (default:
56'/var/lib/landscape/client').51'/var/lib/landscape/client').
5752
=== modified file 'man/landscape-config.txt'
--- man/landscape-config.txt 2010-01-18 17:20:34 +0000
+++ man/landscape-config.txt 2011-12-02 09:56:24 +0000
@@ -28,8 +28,6 @@
28 -c FILE, --config=FILE Use config from this file (any command line options28 -c FILE, --config=FILE Use config from this file (any command line options
29 override settings from the file) (default:29 override settings from the file) (default:
30 '/etc/landscape/client.conf').30 '/etc/landscape/client.conf').
31 --bus=BUS Which DBUS bus to use. One of 'session' or 'system'
32 (default: 'system').
33 -d PATH, --data-path=PATH The directory to store data files in (default:31 -d PATH, --data-path=PATH The directory to store data files in (default:
34 '/var/lib/landscape/client').32 '/var/lib/landscape/client').
35 -q, --quiet Do not log to the standard output.33 -q, --quiet Do not log to the standard output.
3634
=== modified file 'man/landscape-message.1'
--- man/landscape-message.1 2010-01-18 17:26:36 +0000
+++ man/landscape-message.1 2011-12-02 09:56:24 +0000
@@ -1,5 +1,5 @@
1.\"Text automatically generated by txt2man1.\"Text automatically generated by txt2man
2.TH landscape-message "18 January 2010" "" ""2.TH landscape-message 1 "02 December 2011" "" ""
3.SH NAME3.SH NAME
4\fBlandscape-message \fP- Send a message to the landscape web interface4\fBlandscape-message \fP- Send a message to the landscape web interface
5\fB5\fB
@@ -31,10 +31,6 @@
31.B31.B
32\fB-h\fP, \fB--help\fP32\fB-h\fP, \fB--help\fP
33Show this help message and exit.33Show this help message and exit.
34.TP
35.B
36\fB-b\fP BUS, \fB--bus\fP=BUS
37The DBUS bus to use to send the message.
38.SH EXAMPLES34.SH EXAMPLES
3935
40\fBlandscape-message\fP Hello administrator36\fBlandscape-message\fP Hello administrator
4137
=== modified file 'man/landscape-message.txt'
--- man/landscape-message.txt 2010-01-18 16:33:51 +0000
+++ man/landscape-message.txt 2011-12-02 09:56:24 +0000
@@ -16,7 +16,6 @@
16OPTIONS16OPTIONS
17 --version Show program's version number and exit.17 --version Show program's version number and exit.
18 -h, --help Show this help message and exit.18 -h, --help Show this help message and exit.
19 -b BUS, --bus=BUS The DBUS bus to use to send the message.
2019
21EXAMPLES20EXAMPLES
2221
2322
=== removed file 'scripts/landscape-dbus-proxy'
--- scripts/landscape-dbus-proxy 2011-06-13 23:58:09 +0000
+++ scripts/landscape-dbus-proxy 1970-01-01 00:00:00 +0000
@@ -1,82 +0,0 @@
1#!/usr/bin/env python
2
3import os
4import dbus
5import dbus.service
6import dbus.glib # This as side effects, don't remove it!
7
8from dbus.service import Object, BusName, method
9
10from twisted.internet import glib2reactor
11glib2reactor.install()
12from twisted.internet import reactor
13
14from landscape.lib.bpickle import loads
15from landscape.lib.lock import lock_path, LockError
16from landscape.reactor import TwistedReactor
17from landscape.deployment import Configuration
18from landscape.broker.amp import RemoteBrokerConnector
19
20
21BUS_NAME = "com.canonical.landscape.Broker"
22OBJECT_PATH = "/com/canonical/landscape/Broker"
23
24
25def array_to_string(array):
26 """Convert an L{Array} of L{Byte}s (or integers) to a Python str."""
27 result = []
28 for item in array:
29 if item < 0:
30 item = item + 256
31 result.append(chr(item))
32 return "".join(result)
33
34
35class BrokerDBusObject(Object):
36 """A DBus-published object proxying L{RemoteBroker.send_message}.
37
38 It is used when upgrading from a DBus-based version of the Landscape client
39 to the newer AMP-based one, for letting the old package-changer process
40 performing the upgrade communicate with the new version of the client.
41 """
42
43 bus_name = BUS_NAME
44 object_path = OBJECT_PATH
45
46 def __init__(self, config):
47 super(BrokerDBusObject, self).__init__(BusName(
48 self.bus_name, dbus.SystemBus()), object_path=self.object_path)
49 self.config = config
50
51 @method(BUS_NAME)
52 def send_message(self, message, urgent=True):
53 """Queue the given message in the message exchange."""
54 message = loads(array_to_string(message))
55
56 def cb_connected(broker):
57 result = broker.send_message(message, urgent=True)
58 return result.addCallback(cb_done)
59
60 def cb_done(ignored):
61 return reactor.stop()
62
63 twisted_reactor = TwistedReactor()
64 connector = RemoteBrokerConnector(twisted_reactor, self.config)
65 connected = connector.connect()
66 connected.addCallback(cb_connected)
67
68
69if __name__ == "__main__":
70 config = Configuration()
71 lock_dir = os.path.join(config.data_path, "package")
72 if os.path.isdir(lock_dir):
73 lock_filename = os.path.join(lock_dir, "changer.lock")
74 try:
75 lock_path(lock_filename)
76 except LockError:
77 # The package-changer is running, this means that we're upgrading from
78 # a non-AMP version and that the upgrade is Landscape driven, so let's
79 # expose the DBus broker proxy to give a chance to the package-changer
80 # to send its result message.
81 remote = BrokerDBusObject(config)
82 reactor.run()
830
=== modified file 'setup.py'
--- setup.py 2010-06-10 13:30:58 +0000
+++ setup.py 2011-12-02 09:56:24 +0000
@@ -29,8 +29,7 @@
29 "scripts/landscape-package-reporter",29 "scripts/landscape-package-reporter",
30 "scripts/landscape-release-upgrader",30 "scripts/landscape-release-upgrader",
31 "scripts/landscape-sysinfo",31 "scripts/landscape-sysinfo",
32 "scripts/landscape-is-cloud-managed",32 "scripts/landscape-is-cloud-managed"],
33 "scripts/landscape-dbus-proxy"],
34 ext_modules=[Extension("landscape.lib.initgroups",33 ext_modules=[Extension("landscape.lib.initgroups",
35 ["landscape/lib/initgroups.c"])]34 ["landscape/lib/initgroups.c"])]
36 )35 )

Subscribers

People subscribed via source and target branches

to all changes: