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
=== modified file 'python/libertine/Client.py'
--- python/libertine/Client.py 2017-02-15 21:25:15 +0000
+++ python/libertine/Client.py 2017-02-23 15:25:56 +0000
@@ -20,6 +20,9 @@
2020
21class Client(object):21class Client(object):
22 def __init__(self):22 def __init__(self):
23 self._get_manager()
24
25 def _get_manager(self):
23 self._manager = None26 self._manager = None
2427
25 try:28 try:
@@ -33,16 +36,25 @@
33 except dbus.exceptions.DBusException as e:36 except dbus.exceptions.DBusException as e:
34 utils.get_logger().warning("Exception raised while discovering d-bus service: {}".format(str(e)))37 utils.get_logger().warning("Exception raised while discovering d-bus service: {}".format(str(e)))
3538
39 def _do_operation(self, operation):
40 # It's possible that the service has gone down from when first getting the object.
41 # This catches the dbus excpetion if it did, and tries to reconnect to the service
42 # and then retry the dbus method.
43 while self.valid:
44 try:
45 return operation()
46 except dbus.exceptions.DBusException as e:
47 self._get_manager()
48 else:
49 return False
50
36 @property51 @property
37 def valid(self):52 def valid(self):
38 return self._manager is not None53 return self._manager is not None
3954
40 def container_operation_start(self, id):55 def container_operation_start(self, id):
41 if not self.valid:
42 return False
43
44 retries = 056 retries = 0
45 while not self._manager.get_dbus_method('container_operation_start', self._interface)(id):57 while not self._do_operation(lambda: self._manager.get_dbus_method('container_operation_start', self._interface)(id)):
46 retries += 158 retries += 1
47 if retries > 5:59 if retries > 5:
48 return False60 return False
@@ -50,12 +62,8 @@
5062
51 return True63 return True
5264
53 def container_operation_finished(self, id):65 def container_operation_finished(self, id, app_name, pid):
54 return self.valid and self._manager.get_dbus_method("container_operation_finished", self._interface)(id)66 return self._do_operation(lambda: self._manager.get_dbus_method("container_operation_finished", self._interface)(id, app_name, pid))
5567
56 def container_stopped(self, id):68 def container_stopped(self, id):
57 if not self.valid:69 return self._do_operation(lambda: self._manager.get_dbus_method('container_stopped', self._interface)(id))
58 return False
59
60 self._manager.get_dbus_method('container_stopped', self._interface)(id)
61 return True
6270
=== modified file 'python/libertine/ContainersConfig.py'
--- python/libertine/ContainersConfig.py 2017-02-07 14:09:49 +0000
+++ python/libertine/ContainersConfig.py 2017-02-23 15:25:56 +0000
@@ -364,9 +364,18 @@
364 app_obj = {'appExecName': app_exec_name, 'pid': pid}364 app_obj = {'appExecName': app_exec_name, 'pid': pid}
365 self._set_value_by_key(container_id, 'runningApps', app_obj)365 self._set_value_by_key(container_id, 'runningApps', app_obj)
366366
367 def delete_running_app(self, container_id, app_exec_name):367 def delete_running_app(self, container_id, app_obj):
368 self._delete_array_object_by_key_value(container_id, 'runningApps',368 self._delete_array_object_by_value(container_id, 'runningApps', app_obj)
369 'appExecName', app_exec_name)369
370 def find_running_app_by_name_and_pid(self, container_id, app_exec_name, pid):
371 for app in self.get_running_apps(container_id):
372 if app['appExecName'] == app_exec_name and app['pid'] == pid:
373 return app
374
375 return None
376
377 def get_running_apps(self, container_id):
378 return self._get_value_by_key(container_id, 'runningApps') or []
370379
371 """380 """
372 Operations for bind-mount maintenance in a Libertine container.381 Operations for bind-mount maintenance in a Libertine container.
373382
=== modified file 'python/libertine/Libertine.py'
--- python/libertine/Libertine.py 2017-02-09 15:40:37 +0000
+++ python/libertine/Libertine.py 2017-02-23 15:25:56 +0000
@@ -83,6 +83,8 @@
83 self.container_type = container_type83 self.container_type = container_type
84 self.container_id = container_id84 self.container_id = container_id
85 self._config = config85 self._config = config
86 self._app_name = ''
87 self._pid = 0
86 self.root_path = utils.get_libertine_container_rootfs_path(self.container_id)88 self.root_path = utils.get_libertine_container_rootfs_path(self.container_id)
87 self.locale = self._config.get_container_locale(container_id)89 self.locale = self._config.get_container_locale(container_id)
88 self.language = self._get_language_from_locale()90 self.language = self._get_language_from_locale()
8991
=== modified file 'python/libertine/LxcContainer.py'
--- python/libertine/LxcContainer.py 2017-02-15 21:12:37 +0000
+++ python/libertine/LxcContainer.py 2017-02-23 15:25:56 +0000
@@ -14,7 +14,6 @@
1414
15import contextlib15import contextlib
16import crypt16import crypt
17import dbus
18import lxc17import lxc
19import os18import os
20import psutil19import psutil
@@ -22,7 +21,6 @@
22import subprocess21import subprocess
23import sys22import sys
24import tempfile23import tempfile
25import time
2624
27from .Libertine import BaseContainer25from .Libertine import BaseContainer
28from . import utils, HostInfo, Client26from . import utils, HostInfo, Client
@@ -215,7 +213,8 @@
215 return fd.read().strip('\n') != self.host_info.get_host_timezone()213 return fd.read().strip('\n') != self.host_info.get_host_timezone()
216214
217 def start_container(self):215 def start_container(self):
218 self._manager.container_operation_start(self.container_id)216 if not self._manager.container_operation_start(self.container_id):
217 return False
219218
220 if self.container.state == 'RUNNING':219 if self.container.state == 'RUNNING':
221 return True220 return True
@@ -231,33 +230,21 @@
231 return True230 return True
232231
233 def stop_container(self):232 def stop_container(self):
234 if self._manager.valid:233 if (self._manager.container_operation_finished(self.container_id, self._app_name, self._pid) and
235 if not self._manager.container_operation_finished(self.container_id):234 lxc_stop(self.container, self._freeze_on_stop)):
236 return False
237
238 if not lxc_stop(self.container, self._freeze_on_stop):
239 return False
240
241 return self._manager.container_stopped(self.container_id)235 return self._manager.container_stopped(self.container_id)
242 else:236
243 return lxc_stop(self.container, self._freeze_on_stop)237 return False
244238
245 def restart_container(self):239 def restart_container(self):
246 if self.container.state != 'FROZEN':240 if self.container.state != 'FROZEN':
247 utils.get_logger().warning("Container {} is not frozen. Cannot restart.".format(self.container_id))241 utils.get_logger().warning("Container {} is not frozen. Cannot restart.".format(self.container_id))
248 return False242 return False
249243
250 orig_freeze = self._freeze_on_stop244 if not (lxc_stop(self.container) and lxc_start(self.container)):
251 self._freeze_on_stop = False
252
253 # We never want to use the manager when restarting.
254 self._manager = None
255
256 if not (self.stop_container() and self.start_container()):
257 return False245 return False
258246
259 self._freeze_on_stop = orig_freeze247 return lxc_stop(self.container, self._freeze_on_stop)
260 return self.stop_container()
261248
262 def run_in_container(self, command_string):249 def run_in_container(self, command_string):
263 cmd_args = shlex.split(command_string)250 cmd_args = shlex.split(command_string)
@@ -276,7 +263,14 @@
276 if not self.container.defined:263 if not self.container.defined:
277 return False264 return False
278265
279 self.container.stop()266 if self.container.state == 'RUNNING':
267 utils.get_logger().error("Canceling destruction due to running container")
268 return False
269
270 if self.container.state == 'FROZEN' and not lxc_stop(self.container):
271 utils.get_logger().error("Canceling destruction due to container not stopped")
272 return False
273
280 self.container.destroy()274 self.container.destroy()
281 return True275 return True
282276
@@ -389,10 +383,6 @@
389 self.container.save_config()383 self.container.save_config()
390384
391 def start_application(self, app_exec_line, environ):385 def start_application(self, app_exec_line, environ):
392 if not self._manager.valid:
393 utils.get_logger().error("No interface to libertine-lxc-manager. Failing application launch.")
394 return
395
396 os.environ.clear()386 os.environ.clear()
397 os.environ.update(environ)387 os.environ.update(environ)
398388
@@ -400,11 +390,17 @@
400 self._manager.container_stopped(self.container_id)390 self._manager.container_stopped(self.container_id)
401 return391 return
402392
393 self._app_name = app_exec_line[0]
394
403 app_launch_cmd = "sudo -E -u " + os.environ['USER'] + " env PATH=" + os.environ['PATH']395 app_launch_cmd = "sudo -E -u " + os.environ['USER'] + " env PATH=" + os.environ['PATH']
404 cmd = shlex.split(app_launch_cmd)396 cmd = shlex.split(app_launch_cmd)
405 app = self.container.attach(lxc.attach_run_command,397 app = self.container.attach(lxc.attach_run_command,
406 cmd + app_exec_line)398 cmd + app_exec_line)
407 return psutil.Process(app)399
400 proc = psutil.Process(app)
401 self._pid = proc.pid
402
403 return proc
408404
409 def finish_application(self, app):405 def finish_application(self, app):
410 os.waitpid(app.pid, 0)406 os.waitpid(app.pid, 0)
411407
=== modified file 'python/libertine/LxdContainer.py'
--- python/libertine/LxdContainer.py 2017-02-22 15:35:46 +0000
+++ python/libertine/LxdContainer.py 2017-02-23 15:25:56 +0000
@@ -14,7 +14,6 @@
1414
15import contextlib15import contextlib
16import crypt16import crypt
17import dbus
18import os17import os
19import psutil18import psutil
20import pylxd19import pylxd
@@ -368,10 +367,14 @@
368 utils.get_logger().error("No such container '%s'" % self.container_id)367 utils.get_logger().error("No such container '%s'" % self.container_id)
369 return False368 return False
370369
371 if not (self.stop_container(wait=True) or self._container.status == 'Stopped'):370 if self._container.status == 'Running':
372 utils.get_logger().error("Canceling destruction due to running container")371 utils.get_logger().error("Canceling destruction due to running container")
373 return False372 return False
374373
374 if self._container.status == 'Frozen' and not lxd_stop(self._container):
375 utils.get_logger().error("Canceling destruction due to container not stopped")
376 return False
377
375 self._container.delete()378 self._container.delete()
376379
377 return self._delete_rootfs()380 return self._delete_rootfs()
@@ -398,7 +401,8 @@
398 if not self._try_get_container():401 if not self._try_get_container():
399 return False402 return False
400403
401 self._manager.container_operation_start(self.container_id)404 if not self._manager.container_operation_start(self.container_id):
405 return False
402406
403 if self._container.status == 'Running':407 if self._container.status == 'Running':
404 return True408 return True
@@ -425,16 +429,11 @@
425 if not self._try_get_container():429 if not self._try_get_container():
426 return False430 return False
427431
428 if self._manager.valid:432 if (self._manager.container_operation_finished(self.container_id, self._app_name, self._pid) and
429 if not self._manager.container_operation_finished(self.container_id):433 lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop)):
430 return False
431
432 if not lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop):
433 return False
434
435 return self._manager.container_stopped(self.container_id)434 return self._manager.container_stopped(self.container_id)
436 else:435
437 return lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop)436 return False
438437
439 def restart_container(self, wait=True):438 def restart_container(self, wait=True):
440 if not self._try_get_container():439 if not self._try_get_container():
@@ -444,17 +443,10 @@
444 utils.get_logger().warning("Container {} is not frozen. Cannot restart.".format(self._container.name))443 utils.get_logger().warning("Container {} is not frozen. Cannot restart.".format(self._container.name))
445 return False444 return False
446445
447 orig_freeze = self._freeze_on_stop446 if not (lxd_stop(self._container) and lxd_start(self._container)):
448 self._freeze_on_stop = False
449
450 # We never want to use the manager when restarting.
451 self._manager = None
452
453 if not (self.stop_container(wait=True) and self.start_container()):
454 return False447 return False
455448
456 self._freeze_on_stop = orig_freeze449 return lxd_stop(self._container, freeze_on_stop=self._freeze_on_stop)
457 return self.stop_container(wait=True)
458450
459 def start_application(self, app_exec_line, environ):451 def start_application(self, app_exec_line, environ):
460 if not self._try_get_container():452 if not self._try_get_container():
@@ -467,10 +459,16 @@
467 if not self.start_container(home=environ['HOME']):459 if not self.start_container(home=environ['HOME']):
468 return False460 return False
469461
462 self._app_name = app_exec_line[0]
463
470 args = self._lxc_args("sudo -E -u {} env PATH={}".format(environ['USER'], environ['PATH']), environ)464 args = self._lxc_args("sudo -E -u {} env PATH={}".format(environ['USER'], environ['PATH']), environ)
471465
472 args.extend(app_exec_line)466 args.extend(app_exec_line)
473 return psutil.Popen(args)467
468 proc = psutil.Popen(args)
469 self._pid = proc.pid
470
471 return proc
474472
475 def finish_application(self, app):473 def finish_application(self, app):
476 app.wait()474 app.wait()
477475
=== modified file 'python/libertine/launcher/session.py'
--- python/libertine/launcher/session.py 2016-12-12 19:59:14 +0000
+++ python/libertine/launcher/session.py 2017-02-23 15:25:56 +0000
@@ -1,4 +1,4 @@
1# Copyright 2016 Canonical Ltd.1# Copyright 2016-2017 Canonical Ltd.
2#2#
3# This program is free software: you can redistribute it and/or modify it3# This program is free software: you can redistribute it and/or modify it
4# under the terms of the GNU General Public License version 3, as published4# under the terms of the GNU General Public License version 3, as published
@@ -234,25 +234,36 @@
234 handler, datum = key.data234 handler, datum = key.data
235 handler(key.fd, datum)235 handler(key.fd, datum)
236 self._container.finish_application(self._app)236 self._container.finish_application(self._app)
237
238 if self._config.container_id:
239 self._remove_running_app()
240
237 self._stop_services()241 self._stop_services()
238242
239 def start_application(self):243 def start_application(self):
240 """Connect to the container and start the application running."""244 """Connect to the container and start the application running."""
241 self._container.connect()245 self._container.connect()
242 self.callback(self._container.disconnect)246 self.callback(self._container.disconnect)
243 self._add_running_app()
244 self._app = self._container.start_application(self._config.exec_line,247 self._app = self._container.start_application(self._config.exec_line,
245 self._config.session_environ)248 self._config.session_environ)
249 if self._app:
250 self._add_running_app()
246251
247 def _add_running_app(self):252 def _add_running_app(self):
248 """Add a running app entry to ContainersConfig.json."""253 """Add a running app entry to ContainersConfig.json."""
249 if self._config.container_id:254 if self._config.container_id:
250 ContainersConfig().add_running_app(self._config.container_id, self._config.exec_line[0])255 ContainersConfig().add_running_app(self._config.container_id, self._config.exec_line[0], self._app.pid)
251256
252 def _remove_running_app(self):257 def _remove_running_app(self):
253 """Remove a running app entry from ContainersConfig.json."""258 """Remove a running app entry from ContainersConfig.json."""
254 if self._config.container_id:259 if self._config.container_id:
255 ContainersConfig().delete_running_app(self._config.container_id, self._config.exec_line[0])260 containers_config = ContainersConfig()
261 running_app = containers_config.find_running_app_by_name_and_pid(self._config.container_id,
262 self._config.exec_line[0],
263 self._app.pid)
264
265 if running_app:
266 containers_config.delete_running_app(self._config.container_id, running_app)
256267
257 def _create_bridge_listener(self, bridge_config):268 def _create_bridge_listener(self, bridge_config):
258 """Create a socket bridge listener for a socket bridge configuration.269 """Create a socket bridge listener for a socket bridge configuration.
@@ -343,9 +354,6 @@
343 signal.signal(signal.SIGINT, self._sigint_handler)354 signal.signal(signal.SIGINT, self._sigint_handler)
344 signal.signal(signal.SIGTERM, self._sigterm_handler)355 signal.signal(signal.SIGTERM, self._sigterm_handler)
345356
346 if self._config.container_id:
347 self._remove_running_app()
348
349 for bridge_pair in self._config.socket_bridges:357 for bridge_pair in self._config.socket_bridges:
350 os.remove(translate_to_real_address(bridge_pair.session_address))358 os.remove(translate_to_real_address(bridge_pair.session_address))
351359
352360
=== modified file 'python/libertine/service/manager.py'
--- python/libertine/service/manager.py 2017-02-15 21:12:37 +0000
+++ python/libertine/service/manager.py 2017-02-23 15:25:56 +0000
@@ -15,7 +15,7 @@
15import dbus15import dbus
16import dbus.service16import dbus.service
17import libertine.service.task_dispatcher17import libertine.service.task_dispatcher
18from collections import Counter18import libertine.service.operations_state
19from dbus.mainloop.glib import DBusGMainLoop19from dbus.mainloop.glib import DBusGMainLoop
20from libertine.service import container20from libertine.service import container
21from libertine import utils21from libertine import utils
@@ -29,8 +29,9 @@
29class Manager(dbus.service.Object):29class Manager(dbus.service.Object):
30 def __init__(self):30 def __init__(self):
31 utils.get_logger().debug("creating service")31 utils.get_logger().debug("creating service")
32 self._operations = Counter()
33 DBusGMainLoop(set_as_default=True)32 DBusGMainLoop(set_as_default=True)
33 self._operations_state = libertine.service.operations_state.OperationsState()
34
34 try:35 try:
35 bus_name = dbus.service.BusName(LIBERTINE_MANAGER_NAME,36 bus_name = dbus.service.BusName(LIBERTINE_MANAGER_NAME,
36 bus=dbus.SessionBus(),37 bus=dbus.SessionBus(),
@@ -124,28 +125,20 @@
124 def container_operation_start(self, container):125 def container_operation_start(self, container):
125 utils.get_logger().debug("container_operation_start({})".format(container))126 utils.get_logger().debug("container_operation_start({})".format(container))
126127
127 if self._operations[container] == -1:128 return self._operations_state.operation_start(container)
128 return False
129
130 self._operations[container] += 1
131 return True
132129
133 @dbus.service.method(LIBERTINE_MANAGER_INTERFACE,130 @dbus.service.method(LIBERTINE_MANAGER_INTERFACE,
134 in_signature='s',131 in_signature='ssi',
135 out_signature='b')132 out_signature='b')
136 def container_operation_finished(self, container):133 def container_operation_finished(self, container, app_name='', pid=0):
137 utils.get_logger().debug("container_operation_finished({})".format(container))134 utils.get_logger().debug("container_operation_finished({})".format(container))
138 stop = False135
139 self._operations[container] -= 1136 return self._operations_state.operation_finished(container, app_name, pid)
140
141 if self._operations[container] == 0:
142 self._operations[container] -= 1
143 stop = True
144
145 return stop
146137
147 @dbus.service.method(LIBERTINE_MANAGER_INTERFACE,138 @dbus.service.method(LIBERTINE_MANAGER_INTERFACE,
148 in_signature='s')139 in_signature='s',
140 out_signature='b')
149 def container_stopped(self, container):141 def container_stopped(self, container):
150 utils.get_logger().debug("container_stopped({})".format(container))142 utils.get_logger().debug("container_stopped({})".format(container))
151 del self._operations[container]143
144 return self._operations_state.operation_stopped(container)
152145
=== added file 'python/libertine/service/operations_state.py'
--- python/libertine/service/operations_state.py 1970-01-01 00:00:00 +0000
+++ python/libertine/service/operations_state.py 2017-02-23 15:25:56 +0000
@@ -0,0 +1,75 @@
1# Copyright 2017 Canonical Ltd.
2#
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; version 3 of the License.
6#
7# This program is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10# GNU General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License
13# along with this program. If not, see <http://www.gnu.org/licenses/>.
14
15import libertine.ContainersConfig
16import psutil
17
18from collections import Counter
19from libertine import utils
20
21
22class OperationsState(object):
23 def __init__(self):
24 self._get_running_apps_per_container()
25
26 def _get_running_apps_per_container(self):
27 self._invalid_apps = dict()
28 self._operations = Counter()
29 config = libertine.ContainersConfig.ContainersConfig()
30
31 for container in config.get_containers():
32 running_apps = config.get_running_apps(container).copy()
33
34 for app in running_apps:
35 try:
36 proc = psutil.Process(app['pid'])
37 if app['appExecName'] in proc.cmdline():
38 self._operations[container] += 1
39 else:
40 raise
41 except:
42 utils.get_logger().error("Container app {} is not valid.".format(app['appExecName']))
43 if container not in self._invalid_apps:
44 self._invalid_apps[container] = [{app['appExecName'], app['pid']}]
45 else:
46 self._invalid_apps[container].append({app['appExecName'], app['pid']})
47 config.delete_running_app(container, app)
48 continue
49
50 def operation_start(self, container):
51 if self._operations[container] == -1:
52 return False
53
54 self._operations[container] += 1
55
56 return True
57
58 def operation_finished(self, container, app_name, pid):
59 if container in self._invalid_apps and {app_name, pid} in self._invalid_apps[container]:
60 self._invalid_apps[container].remove({app_name, pid})
61 if not self._invalid_apps[container]:
62 del self._invalid_apps[container]
63 else:
64 self._operations[container] -= 1
65
66 if self._operations[container] == 0:
67 self._operations[container] = -1
68 return True
69
70 return False
71
72 def operation_stopped(self, container):
73 del self._operations[container]
74
75 return True

Subscribers

People subscribed via source and target branches