Merge lp:~townsend/libertine/rebuild-running-app-state into lp:libertine

Proposed by Christopher Townsend
Status: Merged
Approved by: Larry Price
Approved revision: 417
Merged at revision: 412
Proposed branch: lp:~townsend/libertine/rebuild-running-app-state
Merge into: lp:libertine
Diff against target: 513 lines (+178/-89)
8 files modified
python/libertine/Client.py (+19/-11)
python/libertine/ContainersConfig.py (+12/-3)
python/libertine/Libertine.py (+2/-0)
python/libertine/LxcContainer.py (+23/-27)
python/libertine/LxdContainer.py (+20/-22)
python/libertine/launcher/session.py (+15/-7)
python/libertine/service/manager.py (+12/-19)
python/libertine/service/operations_state.py (+75/-0)
To merge this branch: bzr merge lp:~townsend/libertine/rebuild-running-app-state
Reviewer Review Type Date Requested Status
Larry Price Approve
Libertine CI Bot continuous-integration Approve
Review via email: mp+317548@code.launchpad.net

Commit message

Fix libertined such that it can probe for currently running X apps and rebuild application running state.

To post a comment you must log in.
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:408
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/390/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/744
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/612
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/612
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/612
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/612
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/754
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/735
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/735/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/735
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/735/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/735
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/735/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/735
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/735/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/390/rebuild

review: Approve (continuous-integration)
Revision history for this message
Larry Price (larryprice) wrote :

a few inlines - this is some complex stuff, and it'll be very nice to get it in.

review: Needs Fixing
409. By Christopher Townsend

Changes based on review.

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:409
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/397/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/752
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/617
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/617
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/617
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/617
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/762
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/743
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/743/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/743
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/743/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/743
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/743/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/743
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/743/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/397/rebuild

review: Approve (continuous-integration)
410. By Christopher Townsend

Add invalidate method to the Client.

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:410
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/398/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/753
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/618
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/618
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/618
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/618
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/763
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/744
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/744/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/744
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/744/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/744
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/744/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/744
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/744/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/398/rebuild

review: Approve (continuous-integration)
411. By Christopher Townsend

A few more changes based on review.

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:411
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/400/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/756
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/621
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/621
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/621
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/621
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/766
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/747
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/747/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/747
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/747/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/747
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/747/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/747
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/747/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/400/rebuild

review: Approve (continuous-integration)
412. By Christopher Townsend

Merge lp:libertine.

413. By Christopher Townsend

Better handle container state when trying to destroy a container.

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:413
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/402/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/759
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/624
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/624
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/624
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/624
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/769
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/750
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/750/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/750
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/750/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/750
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/750/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/750
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/750/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/402/rebuild

review: Approve (continuous-integration)
Revision history for this message
Larry Price (larryprice) wrote :

one inline - i'm about to load up the debs and do some verification

414. By Christopher Townsend

Only need to instantiate the ContainersConfig object once.

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:414
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/404/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/763
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/627
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/627
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/627
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/627
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/773
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/754
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/754/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/754
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/754/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/754
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/754/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/754
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/754/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/404/rebuild

review: Approve (continuous-integration)
415. By Christopher Townsend

Missed some variable inits.

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:415
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/405/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/764
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/628
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/628
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/628
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/628
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/774
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/755
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/755/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/755
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/755/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/755
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/755/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/755
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/755/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/405/rebuild

review: Approve (continuous-integration)
416. By Christopher Townsend

Used wrong init type.

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:416
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/406/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/765
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/629
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/629
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/629
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/629
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/775
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/756
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/756/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/756
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/756/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/756
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/756/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/756
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/756/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/406/rebuild

review: Approve (continuous-integration)
Revision history for this message
Larry Price (larryprice) wrote :

So we don't forget, the bug I found EOD is that my bad pids aren't being cleaned up by libertined.

review: Needs Fixing
417. By Christopher Townsend

Fix removal of more than one invalid app.

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:417
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/407/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/766
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/630
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=zesty,testname=default/630
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/630
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=zesty,testname=default/630
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/776
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/757
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/757/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/757
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=zesty/757/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/757
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/757/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/757
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=zesty/757/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/407/rebuild

review: Approve (continuous-integration)
Revision history for this message
Larry Price (larryprice) wrote :

ok lgtm!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'python/libertine/Client.py'
2--- python/libertine/Client.py 2017-02-15 21:25:15 +0000
3+++ python/libertine/Client.py 2017-02-23 15:25:56 +0000
4@@ -20,6 +20,9 @@
5
6 class Client(object):
7 def __init__(self):
8+ self._get_manager()
9+
10+ def _get_manager(self):
11 self._manager = None
12
13 try:
14@@ -33,16 +36,25 @@
15 except dbus.exceptions.DBusException as e:
16 utils.get_logger().warning("Exception raised while discovering d-bus service: {}".format(str(e)))
17
18+ def _do_operation(self, operation):
19+ # It's possible that the service has gone down from when first getting the object.
20+ # This catches the dbus excpetion if it did, and tries to reconnect to the service
21+ # and then retry the dbus method.
22+ while self.valid:
23+ try:
24+ return operation()
25+ except dbus.exceptions.DBusException as e:
26+ self._get_manager()
27+ else:
28+ return False
29+
30 @property
31 def valid(self):
32 return self._manager is not None
33
34 def container_operation_start(self, id):
35- if not self.valid:
36- return False
37-
38 retries = 0
39- while not self._manager.get_dbus_method('container_operation_start', self._interface)(id):
40+ while not self._do_operation(lambda: self._manager.get_dbus_method('container_operation_start', self._interface)(id)):
41 retries += 1
42 if retries > 5:
43 return False
44@@ -50,12 +62,8 @@
45
46 return True
47
48- def container_operation_finished(self, id):
49- return self.valid and self._manager.get_dbus_method("container_operation_finished", self._interface)(id)
50+ def container_operation_finished(self, id, app_name, pid):
51+ return self._do_operation(lambda: self._manager.get_dbus_method("container_operation_finished", self._interface)(id, app_name, pid))
52
53 def container_stopped(self, id):
54- if not self.valid:
55- return False
56-
57- self._manager.get_dbus_method('container_stopped', self._interface)(id)
58- return True
59+ return self._do_operation(lambda: self._manager.get_dbus_method('container_stopped', self._interface)(id))
60
61=== modified file 'python/libertine/ContainersConfig.py'
62--- python/libertine/ContainersConfig.py 2017-02-07 14:09:49 +0000
63+++ python/libertine/ContainersConfig.py 2017-02-23 15:25:56 +0000
64@@ -364,9 +364,18 @@
65 app_obj = {'appExecName': app_exec_name, 'pid': pid}
66 self._set_value_by_key(container_id, 'runningApps', app_obj)
67
68- def delete_running_app(self, container_id, app_exec_name):
69- self._delete_array_object_by_key_value(container_id, 'runningApps',
70- 'appExecName', app_exec_name)
71+ def delete_running_app(self, container_id, app_obj):
72+ self._delete_array_object_by_value(container_id, 'runningApps', app_obj)
73+
74+ def find_running_app_by_name_and_pid(self, container_id, app_exec_name, pid):
75+ for app in self.get_running_apps(container_id):
76+ if app['appExecName'] == app_exec_name and app['pid'] == pid:
77+ return app
78+
79+ return None
80+
81+ def get_running_apps(self, container_id):
82+ return self._get_value_by_key(container_id, 'runningApps') or []
83
84 """
85 Operations for bind-mount maintenance in a Libertine container.
86
87=== modified file 'python/libertine/Libertine.py'
88--- python/libertine/Libertine.py 2017-02-09 15:40:37 +0000
89+++ python/libertine/Libertine.py 2017-02-23 15:25:56 +0000
90@@ -83,6 +83,8 @@
91 self.container_type = container_type
92 self.container_id = container_id
93 self._config = config
94+ self._app_name = ''
95+ self._pid = 0
96 self.root_path = utils.get_libertine_container_rootfs_path(self.container_id)
97 self.locale = self._config.get_container_locale(container_id)
98 self.language = self._get_language_from_locale()
99
100=== modified file 'python/libertine/LxcContainer.py'
101--- python/libertine/LxcContainer.py 2017-02-15 21:12:37 +0000
102+++ python/libertine/LxcContainer.py 2017-02-23 15:25:56 +0000
103@@ -14,7 +14,6 @@
104
105 import contextlib
106 import crypt
107-import dbus
108 import lxc
109 import os
110 import psutil
111@@ -22,7 +21,6 @@
112 import subprocess
113 import sys
114 import tempfile
115-import time
116
117 from .Libertine import BaseContainer
118 from . import utils, HostInfo, Client
119@@ -215,7 +213,8 @@
120 return fd.read().strip('\n') != self.host_info.get_host_timezone()
121
122 def start_container(self):
123- self._manager.container_operation_start(self.container_id)
124+ if not self._manager.container_operation_start(self.container_id):
125+ return False
126
127 if self.container.state == 'RUNNING':
128 return True
129@@ -231,33 +230,21 @@
130 return True
131
132 def stop_container(self):
133- if self._manager.valid:
134- if not self._manager.container_operation_finished(self.container_id):
135- return False
136-
137- if not lxc_stop(self.container, self._freeze_on_stop):
138- return False
139-
140+ if (self._manager.container_operation_finished(self.container_id, self._app_name, self._pid) and
141+ lxc_stop(self.container, self._freeze_on_stop)):
142 return self._manager.container_stopped(self.container_id)
143- else:
144- return lxc_stop(self.container, self._freeze_on_stop)
145+
146+ return False
147
148 def restart_container(self):
149 if self.container.state != 'FROZEN':
150 utils.get_logger().warning("Container {} is not frozen. Cannot restart.".format(self.container_id))
151 return False
152
153- orig_freeze = self._freeze_on_stop
154- self._freeze_on_stop = False
155-
156- # We never want to use the manager when restarting.
157- self._manager = None
158-
159- if not (self.stop_container() and self.start_container()):
160+ if not (lxc_stop(self.container) and lxc_start(self.container)):
161 return False
162
163- self._freeze_on_stop = orig_freeze
164- return self.stop_container()
165+ return lxc_stop(self.container, self._freeze_on_stop)
166
167 def run_in_container(self, command_string):
168 cmd_args = shlex.split(command_string)
169@@ -276,7 +263,14 @@
170 if not self.container.defined:
171 return False
172
173- self.container.stop()
174+ if self.container.state == 'RUNNING':
175+ utils.get_logger().error("Canceling destruction due to running container")
176+ return False
177+
178+ if self.container.state == 'FROZEN' and not lxc_stop(self.container):
179+ utils.get_logger().error("Canceling destruction due to container not stopped")
180+ return False
181+
182 self.container.destroy()
183 return True
184
185@@ -389,10 +383,6 @@
186 self.container.save_config()
187
188 def start_application(self, app_exec_line, environ):
189- if not self._manager.valid:
190- utils.get_logger().error("No interface to libertine-lxc-manager. Failing application launch.")
191- return
192-
193 os.environ.clear()
194 os.environ.update(environ)
195
196@@ -400,11 +390,17 @@
197 self._manager.container_stopped(self.container_id)
198 return
199
200+ self._app_name = app_exec_line[0]
201+
202 app_launch_cmd = "sudo -E -u " + os.environ['USER'] + " env PATH=" + os.environ['PATH']
203 cmd = shlex.split(app_launch_cmd)
204 app = self.container.attach(lxc.attach_run_command,
205 cmd + app_exec_line)
206- return psutil.Process(app)
207+
208+ proc = psutil.Process(app)
209+ self._pid = proc.pid
210+
211+ return proc
212
213 def finish_application(self, app):
214 os.waitpid(app.pid, 0)
215
216=== modified file 'python/libertine/LxdContainer.py'
217--- python/libertine/LxdContainer.py 2017-02-22 15:35:46 +0000
218+++ python/libertine/LxdContainer.py 2017-02-23 15:25:56 +0000
219@@ -14,7 +14,6 @@
220
221 import contextlib
222 import crypt
223-import dbus
224 import os
225 import psutil
226 import pylxd
227@@ -368,10 +367,14 @@
228 utils.get_logger().error("No such container '%s'" % self.container_id)
229 return False
230
231- if not (self.stop_container(wait=True) or self._container.status == 'Stopped'):
232+ if self._container.status == 'Running':
233 utils.get_logger().error("Canceling destruction due to running container")
234 return False
235
236+ if self._container.status == 'Frozen' and not lxd_stop(self._container):
237+ utils.get_logger().error("Canceling destruction due to container not stopped")
238+ return False
239+
240 self._container.delete()
241
242 return self._delete_rootfs()
243@@ -398,7 +401,8 @@
244 if not self._try_get_container():
245 return False
246
247- self._manager.container_operation_start(self.container_id)
248+ if not self._manager.container_operation_start(self.container_id):
249+ return False
250
251 if self._container.status == 'Running':
252 return True
253@@ -425,16 +429,11 @@
254 if not self._try_get_container():
255 return False
256
257- if self._manager.valid:
258- if not self._manager.container_operation_finished(self.container_id):
259- return False
260-
261- if not lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop):
262- return False
263-
264+ if (self._manager.container_operation_finished(self.container_id, self._app_name, self._pid) and
265+ lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop)):
266 return self._manager.container_stopped(self.container_id)
267- else:
268- return lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop)
269+
270+ return False
271
272 def restart_container(self, wait=True):
273 if not self._try_get_container():
274@@ -444,17 +443,10 @@
275 utils.get_logger().warning("Container {} is not frozen. Cannot restart.".format(self._container.name))
276 return False
277
278- orig_freeze = self._freeze_on_stop
279- self._freeze_on_stop = False
280-
281- # We never want to use the manager when restarting.
282- self._manager = None
283-
284- if not (self.stop_container(wait=True) and self.start_container()):
285+ if not (lxd_stop(self._container) and lxd_start(self._container)):
286 return False
287
288- self._freeze_on_stop = orig_freeze
289- return self.stop_container(wait=True)
290+ return lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop)
291
292 def start_application(self, app_exec_line, environ):
293 if not self._try_get_container():
294@@ -467,10 +459,16 @@
295 if not self.start_container(home=environ['HOME']):
296 return False
297
298+ self._app_name = app_exec_line[0]
299+
300 args = self._lxc_args("sudo -E -u {} env PATH={}".format(environ['USER'], environ['PATH']), environ)
301
302 args.extend(app_exec_line)
303- return psutil.Popen(args)
304+
305+ proc = psutil.Popen(args)
306+ self._pid = proc.pid
307+
308+ return proc
309
310 def finish_application(self, app):
311 app.wait()
312
313=== modified file 'python/libertine/launcher/session.py'
314--- python/libertine/launcher/session.py 2016-12-12 19:59:14 +0000
315+++ python/libertine/launcher/session.py 2017-02-23 15:25:56 +0000
316@@ -1,4 +1,4 @@
317-# Copyright 2016 Canonical Ltd.
318+# Copyright 2016-2017 Canonical Ltd.
319 #
320 # This program is free software: you can redistribute it and/or modify it
321 # under the terms of the GNU General Public License version 3, as published
322@@ -234,25 +234,36 @@
323 handler, datum = key.data
324 handler(key.fd, datum)
325 self._container.finish_application(self._app)
326+
327+ if self._config.container_id:
328+ self._remove_running_app()
329+
330 self._stop_services()
331
332 def start_application(self):
333 """Connect to the container and start the application running."""
334 self._container.connect()
335 self.callback(self._container.disconnect)
336- self._add_running_app()
337 self._app = self._container.start_application(self._config.exec_line,
338 self._config.session_environ)
339+ if self._app:
340+ self._add_running_app()
341
342 def _add_running_app(self):
343 """Add a running app entry to ContainersConfig.json."""
344 if self._config.container_id:
345- ContainersConfig().add_running_app(self._config.container_id, self._config.exec_line[0])
346+ ContainersConfig().add_running_app(self._config.container_id, self._config.exec_line[0], self._app.pid)
347
348 def _remove_running_app(self):
349 """Remove a running app entry from ContainersConfig.json."""
350 if self._config.container_id:
351- ContainersConfig().delete_running_app(self._config.container_id, self._config.exec_line[0])
352+ containers_config = ContainersConfig()
353+ running_app = containers_config.find_running_app_by_name_and_pid(self._config.container_id,
354+ self._config.exec_line[0],
355+ self._app.pid)
356+
357+ if running_app:
358+ containers_config.delete_running_app(self._config.container_id, running_app)
359
360 def _create_bridge_listener(self, bridge_config):
361 """Create a socket bridge listener for a socket bridge configuration.
362@@ -343,9 +354,6 @@
363 signal.signal(signal.SIGINT, self._sigint_handler)
364 signal.signal(signal.SIGTERM, self._sigterm_handler)
365
366- if self._config.container_id:
367- self._remove_running_app()
368-
369 for bridge_pair in self._config.socket_bridges:
370 os.remove(translate_to_real_address(bridge_pair.session_address))
371
372
373=== modified file 'python/libertine/service/manager.py'
374--- python/libertine/service/manager.py 2017-02-15 21:12:37 +0000
375+++ python/libertine/service/manager.py 2017-02-23 15:25:56 +0000
376@@ -15,7 +15,7 @@
377 import dbus
378 import dbus.service
379 import libertine.service.task_dispatcher
380-from collections import Counter
381+import libertine.service.operations_state
382 from dbus.mainloop.glib import DBusGMainLoop
383 from libertine.service import container
384 from libertine import utils
385@@ -29,8 +29,9 @@
386 class Manager(dbus.service.Object):
387 def __init__(self):
388 utils.get_logger().debug("creating service")
389- self._operations = Counter()
390 DBusGMainLoop(set_as_default=True)
391+ self._operations_state = libertine.service.operations_state.OperationsState()
392+
393 try:
394 bus_name = dbus.service.BusName(LIBERTINE_MANAGER_NAME,
395 bus=dbus.SessionBus(),
396@@ -124,28 +125,20 @@
397 def container_operation_start(self, container):
398 utils.get_logger().debug("container_operation_start({})".format(container))
399
400- if self._operations[container] == -1:
401- return False
402-
403- self._operations[container] += 1
404- return True
405+ return self._operations_state.operation_start(container)
406
407 @dbus.service.method(LIBERTINE_MANAGER_INTERFACE,
408- in_signature='s',
409+ in_signature='ssi',
410 out_signature='b')
411- def container_operation_finished(self, container):
412+ def container_operation_finished(self, container, app_name='', pid=0):
413 utils.get_logger().debug("container_operation_finished({})".format(container))
414- stop = False
415- self._operations[container] -= 1
416-
417- if self._operations[container] == 0:
418- self._operations[container] -= 1
419- stop = True
420-
421- return stop
422+
423+ return self._operations_state.operation_finished(container, app_name, pid)
424
425 @dbus.service.method(LIBERTINE_MANAGER_INTERFACE,
426- in_signature='s')
427+ in_signature='s',
428+ out_signature='b')
429 def container_stopped(self, container):
430 utils.get_logger().debug("container_stopped({})".format(container))
431- del self._operations[container]
432+
433+ return self._operations_state.operation_stopped(container)
434
435=== added file 'python/libertine/service/operations_state.py'
436--- python/libertine/service/operations_state.py 1970-01-01 00:00:00 +0000
437+++ python/libertine/service/operations_state.py 2017-02-23 15:25:56 +0000
438@@ -0,0 +1,75 @@
439+# Copyright 2017 Canonical Ltd.
440+#
441+# This program is free software: you can redistribute it and/or modify
442+# it under the terms of the GNU General Public License as published by
443+# the Free Software Foundation; version 3 of the License.
444+#
445+# This program is distributed in the hope that it will be useful,
446+# but WITHOUT ANY WARRANTY; without even the implied warranty of
447+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
448+# GNU General Public License for more details.
449+#
450+# You should have received a copy of the GNU General Public License
451+# along with this program. If not, see <http://www.gnu.org/licenses/>.
452+
453+import libertine.ContainersConfig
454+import psutil
455+
456+from collections import Counter
457+from libertine import utils
458+
459+
460+class OperationsState(object):
461+ def __init__(self):
462+ self._get_running_apps_per_container()
463+
464+ def _get_running_apps_per_container(self):
465+ self._invalid_apps = dict()
466+ self._operations = Counter()
467+ config = libertine.ContainersConfig.ContainersConfig()
468+
469+ for container in config.get_containers():
470+ running_apps = config.get_running_apps(container).copy()
471+
472+ for app in running_apps:
473+ try:
474+ proc = psutil.Process(app['pid'])
475+ if app['appExecName'] in proc.cmdline():
476+ self._operations[container] += 1
477+ else:
478+ raise
479+ except:
480+ utils.get_logger().error("Container app {} is not valid.".format(app['appExecName']))
481+ if container not in self._invalid_apps:
482+ self._invalid_apps[container] = [{app['appExecName'], app['pid']}]
483+ else:
484+ self._invalid_apps[container].append({app['appExecName'], app['pid']})
485+ config.delete_running_app(container, app)
486+ continue
487+
488+ def operation_start(self, container):
489+ if self._operations[container] == -1:
490+ return False
491+
492+ self._operations[container] += 1
493+
494+ return True
495+
496+ def operation_finished(self, container, app_name, pid):
497+ if container in self._invalid_apps and {app_name, pid} in self._invalid_apps[container]:
498+ self._invalid_apps[container].remove({app_name, pid})
499+ if not self._invalid_apps[container]:
500+ del self._invalid_apps[container]
501+ else:
502+ self._operations[container] -= 1
503+
504+ if self._operations[container] == 0:
505+ self._operations[container] = -1
506+ return True
507+
508+ return False
509+
510+ def operation_stopped(self, container):
511+ del self._operations[container]
512+
513+ return True

Subscribers

People subscribed via source and target branches