Merge lp:~townsend/libertine/release-1.2.2 into lp:libertine/trunk

Proposed by Christopher Townsend
Status: Merged
Approved by: Larry Price
Approved revision: 139
Merged at revision: 138
Proposed branch: lp:~townsend/libertine/release-1.2.2
Merge into: lp:libertine/trunk
Diff against target: 2202 lines (+838/-865)
17 files modified
debian/changelog (+30/-0)
debian/python3-libertine.install (+2/-0)
debian/rules (+3/-0)
libertine/qml/ExtraArchivesView.qml (+3/-6)
libertine/qml/GenericErrorDialog.qml (+17/-3)
libertine/qml/HomeView.qml (+51/-43)
po/CMakeLists.txt (+0/-3)
python/libertine/ChrootContainer.py (+26/-72)
python/libertine/ContainersConfig.py (+309/-0)
python/libertine/HostInfo.py (+71/-0)
python/libertine/Libertine.py (+17/-44)
python/libertine/LxcContainer.py (+19/-16)
python/libertine/utils.py (+1/-29)
tests/unit/CMakeLists.txt (+11/-7)
tools/libertine-container-manager (+269/-634)
tools/libertine-launch (+8/-8)
tools/libertine-session-bridge (+1/-0)
To merge this branch: bzr merge lp:~townsend/libertine/release-1.2.2
Reviewer Review Type Date Requested Status
Larry Price Approve
Review via email: mp+299464@code.launchpad.net

Commit message

* If we fail to find the host path remove the session path since it would have been created with the socket.
* Only set the LXC log file when the container is about to start. (LP: #1596020)
* Add a new ContainersConfig Python class for managing all things ContainersConfig.json.
* Refactor host information into a new HostInfo class.
* Check if the LXC container is defined before trying to start it.
* Remove dependency on DISPLAY variable and use random string to generate session socket path.
* Prevent showing multiple error dialogs when adding archive fails. (LP: #1594957)
* Only generate translations when manually running `make translations`.
* Ensure /usr/games is in PATH before launching applications. (LP: #1598227)
* Make error details selectable and add clipboard button. (LP: #1598786)
* Use dialog instead of ActionSelectionPopover to address focusing issues when installing packages.
* Verify host kernel has lxc support. (LP: #1599193)
* Set DEBIAN_FRONTEND directly in environment for chroot containers. (LP: #1599246)

To post a comment you must log in.
Revision history for this message
Larry Price (larryprice) wrote :

When creating a container, I get the following error:

```
Traceback (most recent call last):
  File "tools/libertine-container-manager", line 492, in <module>
    args.func(args)
  File "tools/libertine-container-manager", line 51, in create
    container_type = self.host_info.select_container_type_by_kernel()
  File "/home/lrp/Projects/2016/libertine-1.2.2/python/libertine/HostInfo.py", line 25, in select_container_type_by_kernel
    if has_lxc_support():
NameError: name 'has_lxc_support' is not defined
```

Probably missing a `self`? See minor diff comments.

review: Needs Fixing
lp:~townsend/libertine/release-1.2.2 updated
139. By Christopher Townsend

Merged hot fix from lp:libertine.
Fix typo in debian/changelog.

Revision history for this message
Larry Price (larryprice) wrote :

Alright - lgtm!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2016-06-23 14:01:47 +0000
3+++ debian/changelog 2016-07-07 20:14:07 +0000
4@@ -1,3 +1,33 @@
5+libertine (1.2.2-0ubuntu1) UNRELEASED; urgency=medium
6+
7+ [ Brandon Schaefer ]
8+ * If we fail to find the host path remove the session path since it would
9+ have been created with the socket.
10+
11+ [ Chris Townsend ]
12+ * Only set the LXC log file when the container is about to start.
13+ (LP: #1596020)
14+ * Add a new ContainersConfig Python class for managing all things
15+ ContainersConfig.json.
16+ * Refactor host information into a new HostInfo class.
17+ * Check if the LXC container is defined before trying to start it.
18+
19+ [ Larry Price ]
20+ * Remove dependency on DISPLAY variable and use random string to generate
21+ session socket path.
22+ * Prevent showing multiple error dialogs when adding archive fails.
23+ (LP: #1594957)
24+ * Only generate translations when manually running `make translations`.
25+ * Ensure /usr/games is in PATH before launching applications. (LP: #1598227)
26+ * Make error details selectable and add clipboard button. (LP: #1598786)
27+ * Use dialog instead of ActionSelectionPopover to address focusing issues
28+ when installing packages.
29+ * Verify host kernel has lxc support. (LP: #1599193)
30+ * Set DEBIAN_FRONTEND directly in environment for chroot containers.
31+ (LP: #1599246)
32+
33+ -- Chris Townsend <christopher.townsend@canonical.com> Thu, 07 Jul 2016 15:08:59 -0400
34+
35 libertine (1.2.1+16.10.20160623-0ubuntu1) yakkety; urgency=medium
36
37 [ Chris Townsend ]
38
39=== modified file 'debian/python3-libertine.install'
40--- debian/python3-libertine.install 2015-12-15 15:46:58 +0000
41+++ debian/python3-libertine.install 2016-07-07 20:14:07 +0000
42@@ -1,4 +1,6 @@
43 usr/lib/python*/*/libertine/AppDiscovery.py
44 usr/lib/python*/*/libertine/Libertine.py
45+usr/lib/python*/*/libertine/ContainersConfig.py
46+usr/lib/python*/*/libertine/HostInfo.py
47 usr/lib/python*/*/libertine/utils.py
48 usr/lib/python*/*/libertine/__init__.py
49
50=== modified file 'debian/rules'
51--- debian/rules 2016-06-22 19:52:24 +0000
52+++ debian/rules 2016-07-07 20:14:07 +0000
53@@ -2,3 +2,6 @@
54
55 %:
56 dh $@ --with python3,gir,click
57+
58+override_dh_auto_build:
59+ dh_auto_build -- all translations
60
61=== modified file 'libertine/qml/ExtraArchivesView.qml'
62--- libertine/qml/ExtraArchivesView.qml 2016-05-19 17:56:43 +0000
63+++ libertine/qml/ExtraArchivesView.qml 2016-07-07 20:14:07 +0000
64@@ -126,25 +126,22 @@
65 }
66
67 function addArchive(archive) {
68- var comp = Qt.createComponent("ContainerManager.qml")
69- worker = comp.createObject(mainView)
70+ var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)
71 worker.finishedConfigure.connect(finishedConfigure)
72 worker.error.connect(sendAddError)
73- error.connect(mainView.error)
74 worker.configureContainer(mainView.currentContainer, containerConfigList.getContainerName(mainView.currentContainer), ["--add-archive", archive])
75 }
76
77 function deleteArchive(archive) {
78- var comp = Qt.createComponent("ContainerManager.qml")
79- worker = comp.createObject(mainView)
80+ var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)
81 worker.finishedConfigure.connect(finishedConfigure)
82 worker.error.connect(sendDeleteError)
83- error.connect(mainView.error)
84 worker.configureContainer(mainView.currentContainer, containerConfigList.getContainerName(mainView.currentContainer), ["--delete-archive", archive])
85 }
86
87 Component.onCompleted: {
88 containerConfigList.configChanged.connect(reloadArchives)
89+ error.connect(mainView.error)
90 }
91
92 Component.onDestruction: {
93
94=== modified file 'libertine/qml/GenericErrorDialog.qml'
95--- libertine/qml/GenericErrorDialog.qml 2016-05-10 14:55:15 +0000
96+++ libertine/qml/GenericErrorDialog.qml 2016-07-07 20:14:07 +0000
97@@ -22,11 +22,25 @@
98
99 Dialog {
100 id: genericErrorDialog
101- property var short_description: null
102- property var details: null
103+ property string short_description: ""
104+ property string details: ""
105
106 title: short_description
107- text: details
108+
109+ TextEdit {
110+ color: UbuntuColors.darkGrey
111+ text: details
112+ readOnly: true
113+ selectByMouse: true
114+ wrapMode: TextEdit.WordWrap
115+ }
116+
117+ Button {
118+ text: i18n.tr("Copy to Clipboard")
119+ onClicked: {
120+ Clipboard.push(details)
121+ }
122+ }
123
124 Button {
125 text: i18n.tr("Dismiss")
126
127=== modified file 'libertine/qml/HomeView.qml'
128--- libertine/qml/HomeView.qml 2016-06-08 21:36:14 +0000
129+++ libertine/qml/HomeView.qml 2016-07-07 20:14:07 +0000
130@@ -31,11 +31,11 @@
131 Action {
132 id: settingsButton
133 iconName: "settings"
134- onTriggered: PopupUtils.open(settingsMenu, homeView)
135+ onTriggered: PopupUtils.open(settingsMenu)
136 },
137 Action {
138 iconName: "add"
139- onTriggered: PopupUtils.open(addAppsMenu, homeView)
140+ onTriggered: PopupUtils.open(addAppsMenu)
141 }
142 ]
143 }
144@@ -98,26 +98,28 @@
145
146 Component {
147 id: settingsMenu
148- ActionSelectionPopover {
149- actions: ActionList {
150- Action {
151- text: i18n.tr("Manage Container")
152- onTriggered: {
153- pageStack.push(Qt.resolvedUrl("ManageContainer.qml"), {currentContainer: currentContainer})
154- }
155- }
156- Action {
157- text: i18n.tr("Container Information")
158- onTriggered: {
159- pageStack.push(Qt.resolvedUrl("ContainerInfoView.qml"), {currentContainer: currentContainer})
160- }
161- }
162- Action {
163- text: i18n.tr("Switch Container")
164- onTriggered: {
165- pageStack.pop()
166- pageStack.push(Qt.resolvedUrl("ContainersView.qml"))
167- }
168+ Dialog {
169+ id: settingsDialog
170+ __closeOnDismissAreaPress: true
171+ Button {
172+ text: i18n.tr("Manage Container")
173+ onTriggered: {
174+ PopupUtils.close(settingsDialog)
175+ pageStack.push(Qt.resolvedUrl("ManageContainer.qml"), {currentContainer: currentContainer})
176+ }
177+ }
178+ Button {
179+ text: i18n.tr("Container Information")
180+ onTriggered: {
181+ PopupUtils.close(settingsDialog)
182+ pageStack.push(Qt.resolvedUrl("ContainerInfoView.qml"), {currentContainer: currentContainer})
183+ }
184+ }
185+ Button {
186+ text: i18n.tr("Switch Container")
187+ onTriggered: {
188+ PopupUtils.close(settingsDialog)
189+ pageStack.pop()
190 }
191 }
192 }
193@@ -125,27 +127,33 @@
194
195 Component {
196 id: addAppsMenu
197- ActionSelectionPopover {
198- id: addAppsActions
199- actions: ActionList {
200- Action {
201- text: i18n.tr("Enter package name or Debian file")
202- onTriggered: {
203- PopupUtils.open(enterPackagePopup)
204- }
205- }
206- Action {
207- text: i18n.tr("Choose Debian package to install")
208- onTriggered: {
209- var packages = containerConfigList.getDebianPackageFiles()
210- pageStack.push(Qt.resolvedUrl("DebianPackagePicker.qml"), {packageList: packages})
211- }
212- }
213- Action {
214- text: i18n.tr("Search archives for a package")
215- onTriggered: {
216- PopupUtils.open(Qt.resolvedUrl("SearchPackagesDialog.qml"))
217- }
218+ Dialog {
219+ id: addAppsDialog
220+ __closeOnDismissAreaPress: true
221+
222+ Button {
223+ text: i18n.tr("Enter package name or Debian file")
224+ width: parent.width
225+ onClicked: {
226+ PopupUtils.close(addAppsDialog)
227+ PopupUtils.open(enterPackagePopup)
228+ }
229+ }
230+ Button {
231+ text: i18n.tr("Choose Debian package to install")
232+ width: parent.width
233+ onClicked: {
234+ PopupUtils.close(addAppsDialog)
235+ var packages = containerConfigList.getDebianPackageFiles()
236+ pageStack.push(Qt.resolvedUrl("DebianPackagePicker.qml"), {packageList: packages})
237+ }
238+ }
239+ Button {
240+ text: i18n.tr("Search archives for a package")
241+ width: parent.width
242+ onClicked: {
243+ PopupUtils.close(addAppsDialog)
244+ PopupUtils.open(Qt.resolvedUrl("SearchPackagesDialog.qml"))
245 }
246 }
247 }
248
249=== modified file 'po/CMakeLists.txt'
250--- po/CMakeLists.txt 2016-02-29 18:07:02 +0000
251+++ po/CMakeLists.txt 2016-07-07 20:14:07 +0000
252@@ -1,7 +1,6 @@
253 set (GETTEXT_PACKAGE "libertine")
254
255 intltool_update_potfile(
256- ALL
257 UBUNTU_SDK_DEFAULTS
258 POTFILES_TEMPLATE POTFILES.in.in
259 COPYRIGHT_HOLDER "Canonical Ltd."
260@@ -9,14 +8,12 @@
261 )
262
263 intltool_install_translations(
264- ALL
265 GETTEXT_PACKAGE ${GETTEXT_PACKAGE}
266 )
267
268 file(GLOB_RECURSE ALL_POFILES "*.po")
269
270 add_custom_target(potfiles
271- ALL
272 SOURCES
273 POTFILES.in.in
274 ${GETTEXT_PACKAGE}.pot
275
276=== modified file 'python/libertine/ChrootContainer.py'
277--- python/libertine/ChrootContainer.py 2016-06-15 18:10:05 +0000
278+++ python/libertine/ChrootContainer.py 2016-07-07 20:14:07 +0000
279@@ -17,6 +17,7 @@
280 import shlex
281 import shutil
282 import subprocess
283+
284 from .Libertine import BaseContainer
285 from . import utils
286
287@@ -53,10 +54,7 @@
288
289 def run_in_container(self, command_string):
290 cmd_args = shlex.split(command_string)
291- if self.get_container_distro(self.container_id) == "trusty":
292- command_prefix = self._build_privileged_proot_cmd()
293- else:
294- command_prefix = "fakechroot fakeroot chroot " + self.root_path
295+ command_prefix = "fakechroot fakeroot chroot " + self.root_path
296 args = shlex.split(command_prefix + ' ' + command_string)
297 cmd = subprocess.Popen(args)
298 return cmd.wait()
299@@ -66,15 +64,9 @@
300 shutil.rmtree(container_root)
301
302 def create_libertine_container(self, password=None, multiarch=False, verbosity=1):
303- installed_release = self.get_container_distro(self.container_id)
304- architecture = utils.get_host_architecture()
305-
306 # Create the actual chroot
307- if installed_release == "trusty":
308- command_line = "debootstrap --verbose " + installed_release + " " + self.root_path
309- else:
310- command_line = "fakechroot fakeroot debootstrap --verbose --variant=fakechroot {} {}".format(
311- installed_release, self.root_path)
312+ command_line = "fakechroot fakeroot debootstrap --verbose --variant=fakechroot {} {}".format(
313+ self.installed_release, self.root_path)
314 args = shlex.split(command_line)
315 cmd = subprocess.Popen(args)
316 cmd.wait()
317@@ -84,25 +76,24 @@
318 self.destroy_libertine_container()
319 return False
320
321- # Remove symlinks as they can ill-behaved recursive behavior in the chroot
322- if installed_release != "trusty":
323- print("Fixing chroot symlinks...")
324- os.remove(os.path.join(self.root_path, 'dev'))
325- os.remove(os.path.join(self.root_path, 'proc'))
326+ # Remove symlinks as they can cause ill-behaved recursive behavior in the chroot
327+ print("Fixing chroot symlinks...")
328+ os.remove(os.path.join(self.root_path, 'dev'))
329+ os.remove(os.path.join(self.root_path, 'proc'))
330
331- with open(os.path.join(self.root_path, 'usr', 'sbin', 'policy-rc.d'), 'w+') as fd:
332- fd.write("#!/bin/sh\n\n")
333- fd.write("while true; do\n")
334- fd.write("case \"$1\" in\n")
335- fd.write(" -*) shift ;;\n")
336- fd.write(" makedev) exit 0;;\n")
337- fd.write(" *) exit 101;;\n")
338- fd.write("esac\n")
339- fd.write("done\n")
340- os.fchmod(fd.fileno(), 0o755)
341+ with open(os.path.join(self.root_path, 'usr', 'sbin', 'policy-rc.d'), 'w+') as fd:
342+ fd.write("#!/bin/sh\n\n")
343+ fd.write("while true; do\n")
344+ fd.write("case \"$1\" in\n")
345+ fd.write(" -*) shift ;;\n")
346+ fd.write(" makedev) exit 0;;\n")
347+ fd.write(" *) exit 101;;\n")
348+ fd.write("esac\n")
349+ fd.write("done\n")
350+ os.fchmod(fd.fileno(), 0o755)
351
352 # Add universe, multiverse, and -updates to the chroot's sources.list
353- if (utils.get_host_architecture() == 'armhf'):
354+ if (self.architecture == 'armhf'):
355 archive = "deb http://ports.ubuntu.com/ubuntu-ports "
356 else:
357 archive = "deb http://archive.ubuntu.com/ubuntu "
358@@ -110,52 +101,15 @@
359 if verbosity == 1:
360 print("Updating chroot's sources.list entries...")
361 with open(os.path.join(self.root_path, 'etc', 'apt', 'sources.list'), 'a') as fd:
362- fd.write(archive + installed_release + "-updates main\n")
363- fd.write(archive + installed_release + " universe\n")
364- fd.write(archive + installed_release + "-updates universe\n")
365- fd.write(archive + installed_release + " multiverse\n")
366- fd.write(archive + installed_release + "-updates multiverse\n")
367+ fd.write(archive + self.installed_release + "-updates main\n")
368+ fd.write(archive + self.installed_release + " universe\n")
369+ fd.write(archive + self.installed_release + "-updates universe\n")
370+ fd.write(archive + self.installed_release + " multiverse\n")
371+ fd.write(archive + self.installed_release + "-updates multiverse\n")
372
373 utils.create_libertine_user_data_dir(self.container_id)
374
375- if installed_release == "trusty":
376- print("Additional configuration for Trusty chroot...")
377-
378- cmd_line_prefix = self._build_privileged_proot_cmd()
379-
380- command_line = cmd_line_prefix + " dpkg-divert --local --rename --add /etc/init.d/systemd-logind"
381- args = shlex.split(command_line)
382- cmd = subprocess.Popen(args).wait()
383-
384- command_line = cmd_line_prefix + " dpkg-divert --local --rename --add /sbin/initctl"
385- args = shlex.split(command_line)
386- cmd = subprocess.Popen(args).wait()
387-
388- command_line = cmd_line_prefix + " dpkg-divert --local --rename --add /sbin/udevd"
389- args = shlex.split(command_line)
390- cmd = subprocess.Popen(args).wait()
391-
392- command_line = cmd_line_prefix + " dpkg-divert --local --rename --add /usr/sbin/rsyslogd"
393- args = shlex.split(command_line)
394- cmd = subprocess.Popen(args).wait()
395-
396- command_line = cmd_line_prefix + " ln -s /bin/true /etc/init.d/systemd-logind"
397- args = shlex.split(command_line)
398- cmd = subprocess.Popen(args).wait()
399-
400- command_line = cmd_line_prefix + " ln -s /bin/true /sbin/initctl"
401- args = shlex.split(command_line)
402- cmd = subprocess.Popen(args).wait()
403-
404- command_line = cmd_line_prefix + " ln -s /bin/true /sbin/udevd"
405- args = shlex.split(command_line)
406- cmd = subprocess.Popen(args).wait()
407-
408- command_line = cmd_line_prefix + " ln -s /bin/true /usr/sbin/rsyslogd"
409- args = shlex.split(command_line)
410- cmd = subprocess.Popen(args).wait()
411-
412- if multiarch and architecture == 'amd64':
413+ if multiarch and self.architecture == 'amd64':
414 if verbosity == 1:
415 print("Adding i386 multiarch support...")
416 self.run_in_container("dpkg --add-architecture i386")
417@@ -170,7 +124,7 @@
418 self.destroy_libertine_container()
419 return False
420
421- if installed_release == "vivid":
422+ if self.installed_release == "vivid":
423 if verbosity == 1:
424 print("Installing the Vivid Stable Overlay PPA...")
425 self.run_in_container("add-apt-repository ppa:ci-train-ppa-service/stable-phone-overlay -y")
426
427=== added file 'python/libertine/ContainersConfig.py'
428--- python/libertine/ContainersConfig.py 1970-01-01 00:00:00 +0000
429+++ python/libertine/ContainersConfig.py 2016-07-07 20:14:07 +0000
430@@ -0,0 +1,309 @@
431+# Copyright 2016 Canonical Ltd.
432+#
433+# This program is free software: you can redistribute it and/or modify it
434+# under the terms of the GNU General Public License version 3, as published
435+# by the Free Software Foundation.
436+#
437+# This program is distributed in the hope that it will be useful, but
438+# WITHOUT ANY WARRANTY; without even the implied warranties of
439+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
440+# PURPOSE. See the GNU General Public License for more details.
441+#
442+# You should have received a copy of the GNU General Public License along
443+# with this program. If not, see <http://www.gnu.org/licenses/>.
444+
445+import fcntl
446+import json
447+import libertine.utils
448+import os
449+import sys
450+
451+
452+def read_container_config_file():
453+ container_list = {}
454+ container_config_file = libertine.utils.get_libertine_database_file_path()
455+
456+ if (os.path.exists(container_config_file) and
457+ os.path.getsize(container_config_file) != 0):
458+ with open(container_config_file, 'r') as fd:
459+ container_list = json.load(fd)
460+
461+ return container_list
462+
463+
464+def write_container_config_file(container_list):
465+ container_config_file = libertine.utils.get_libertine_database_file_path()
466+
467+ with open(container_config_file, 'w') as fd:
468+ fcntl.lockf(fd, fcntl.LOCK_EX)
469+ json.dump(container_list, fd, sort_keys=True, indent=4)
470+ fd.write('\n')
471+ fcntl.lockf(fd, fcntl.LOCK_UN)
472+
473+
474+class ContainersConfig(object):
475+
476+ def __init__(self):
477+ self.container_list = read_container_config_file()
478+
479+ if "defaultContainer" in self.container_list:
480+ self.default_container_id = self.container_list['defaultContainer']
481+ else:
482+ self.default_container_id = None
483+
484+ """
485+ Private helper methods
486+ """
487+ def _get_container_entry(self, container_id):
488+ if not self.container_list:
489+ return None
490+
491+ for container in self.container_list['containerList']:
492+ if container['id'] == container_id:
493+ return container
494+
495+ return None
496+
497+ def _get_value_by_key(self, container_id, key):
498+ container = self._get_container_entry(container_id)
499+
500+ if not container or key not in container:
501+ return None
502+ else:
503+ return container[key]
504+
505+ def _get_array_object_value_by_key(self, container_id, array_key, object_key, matcher, key):
506+ for item in self._get_value_by_key(container_id, array_key):
507+ if item[object_key] == matcher:
508+ return item[key]
509+
510+ def _set_value_by_key(self, container_id, key, value):
511+ container = self._get_container_entry(container_id)
512+
513+ if not container:
514+ return
515+
516+ if type(value) is str:
517+ container[key] = value
518+ elif type(value) is dict:
519+ if key not in container:
520+ container[key] = [value]
521+ else:
522+ container[key].append(value)
523+
524+ write_container_config_file(self.container_list)
525+
526+ def _set_array_object_value_by_key(self, container_id, array_key, object_key, matcher, key, value):
527+ container = self._get_container_entry(container_id)
528+
529+ if not container:
530+ return
531+
532+ for item in container[array_key]:
533+ if item[object_key] == matcher:
534+ item[key] = value
535+ write_container_config_file(self.container_list)
536+ return
537+
538+ def _delete_array_object_by_key_value(self, container_id, array_key, object_key, value):
539+ container = self._get_container_entry(container_id)
540+
541+ if not container:
542+ return
543+
544+ for item in container[array_key]:
545+ if item[object_key] == value:
546+ container[array_key].remove(item)
547+ write_container_config_file(self.container_list)
548+ return
549+
550+ def _test_key_value_exists(self, container_id, key, value=None):
551+ key_value = self._get_value_by_key(container_id, key)
552+
553+ if not key_value:
554+ return False
555+ elif key == 'id':
556+ return True
557+ elif key_value == value:
558+ return True
559+ else:
560+ return False
561+
562+ def _test_array_object_key_value_exists(self, container_id, array_key, object_key, value):
563+ array = self._get_value_by_key(container_id, array_key)
564+
565+ if not array:
566+ return False
567+
568+ for item in array:
569+ if item[object_key] == value:
570+ return True
571+
572+ return False
573+
574+ """
575+ Miscellaneous ContainersConfig.json operations
576+ """
577+ def _find_duplicate_container_entry(self, container_list, container_id):
578+ for container in container_list['containerList']:
579+ if container['id'] == container_id:
580+ return container
581+
582+ return None
583+
584+ def merge_container_config_files(self, filepath):
585+ merged_json = []
586+
587+ with open(filepath, 'r') as fd:
588+ merge_source = json.load(fd)
589+
590+ if "containerList" in self.container_list:
591+ # Finds any duplicate entries and assumes we want to update the main config
592+ # with entries from the merge source.
593+ for i, container in enumerate(self.container_list['containerList']):
594+ merge_container = self._find_duplicate_container_entry(merge_source, container['id'])
595+ if merge_container:
596+ self.container_list['containerList'][i] = merge_container
597+ merge_source['containerList'].remove(merge_container)
598+
599+ # Merges in any remaining non-duplicate entries.
600+ for container in merge_source['containerList']:
601+ self.container_list['containerList'].append(container)
602+
603+ else:
604+ self.container_list = merge_source
605+
606+ write_container_config_file(self.container_list)
607+
608+ def check_container_id(self, container_id):
609+ if container_id and not self.container_exists(container_id):
610+ print("Container id \'%s\' does not exist." % container_id, file=sys.stderr)
611+ sys.exit(1)
612+ elif not container_id:
613+ return self.get_default_container_id()
614+
615+ return container_id
616+
617+ def get_default_container_id(self):
618+ return self.default_container_id
619+
620+ def set_default_container_id(self, container_id, write_json=False):
621+ self.default_container_id = container_id
622+ self.container_list['defaultContainer'] = container_id
623+
624+ if write_json:
625+ write_container_config_file(self.container_list)
626+
627+ def clear_default_container_id(self, write_json=False):
628+ self.default_container_id = None
629+ self.container_list.pop('defaultContainer', None)
630+
631+ if write_json:
632+ write_container_config_file(self.container_list)
633+
634+ """
635+ Operations for the container itself.
636+ """
637+ def add_new_container(self, container_id, container_name, container_type, container_distro):
638+ container_obj = {'id': container_id, 'installStatus': 'new', 'type': container_type,
639+ 'distro': container_distro, 'name': container_name, 'installedApps': []}
640+
641+ if "defaultContainer" not in self.container_list:
642+ self.set_default_container_id(container_id)
643+
644+ if "containerList" not in self.container_list:
645+ self.container_list['containerList'] = [container_obj]
646+ else:
647+ self.container_list['containerList'].append(container_obj)
648+
649+ write_container_config_file(self.container_list)
650+
651+ def delete_container(self, container_id):
652+ if not self.container_list:
653+ print("Unable to delete container. No containers defined.")
654+ sys.exit(1)
655+
656+ container = self._get_container_entry(container_id)
657+
658+ self.container_list['containerList'].remove(container)
659+
660+ # Set a new defaultContainer if the current default is being deleted.
661+ if self.container_list['defaultContainer'] == container_id and self.container_list['containerList']:
662+ self.set_default_container_id(self.container_list['containerList'][0]['id'])
663+ # Remove the defaultContainer if there are no more containers left.
664+ elif not self.container_list['containerList']:
665+ self.clear_default_container_id()
666+
667+ write_container_config_file(self.container_list)
668+
669+ def update_container_install_status(self, container_id, new_status):
670+ self._set_value_by_key(container_id, 'installStatus', new_status)
671+
672+ def container_exists(self, container_id):
673+ return self._test_key_value_exists(container_id, 'id')
674+
675+ def update_container_multiarch_support(self, container_id, multiarch):
676+ if multiarch == 'enabled' and libertine.utils.get_host_architecture() == 'i386':
677+ multiarch = 'disabled'
678+
679+ self._set_value_by_key(container_id, 'multiarch', multiarch)
680+
681+ def get_container_multiarch_support(self, container_id):
682+ multiarch_support = self._get_value_by_key(container_id, 'multiarch')
683+
684+ if multiarch_support == None:
685+ return 'disabled'
686+ else:
687+ return multiarch_support
688+
689+ """
690+ Operations for archive (PPA) maintenance in a Libertine container.
691+ """
692+ def add_container_archive(self, container_id, archive_name):
693+ archive_obj = {'archiveName': archive_name, 'archiveStatus': 'new'}
694+ self._set_value_by_key(container_id, 'extraArchives', archive_obj)
695+
696+ def delete_container_archive(self, container_id, archive_name):
697+ self._delete_array_object_by_key_value(container_id, 'extraArchives',
698+ 'archiveName', archive_name)
699+
700+ def update_archive_install_status(self, container_id, archive_name, new_status):
701+ self._set_array_object_value_by_key(container_id, 'extraArchives', 'archiveName',
702+ archive_name, 'archiveStatus', new_status)
703+
704+ def archive_exists(self, container_id, archive_name):
705+ return self._test_array_object_key_value_exists(container_id, 'extraArchives', 'archiveName',
706+ archive_name)
707+
708+ """
709+ Operations for package maintenance in a Libertine container.
710+ """
711+ def add_new_package(self, container_id, package_name):
712+ package_obj = {'packageName': package_name, 'appStatus': 'new'}
713+ self._set_value_by_key(container_id, 'installedApps', package_obj)
714+
715+ def delete_package(self, container_id, package_name):
716+ self._delete_array_object_by_key_value(container_id, 'installedApps',
717+ 'packageName', package_name)
718+
719+ def update_package_install_status(self, container_id, package_name, new_status):
720+ self._set_array_object_value_by_key(container_id, 'installedApps', 'packageName',
721+ package_name, 'appStatus', new_status)
722+
723+ def get_package_install_status(self, container_id, package_name):
724+ return self._get_array_object_value_by_key(container_id, 'installedApps', 'packageName',
725+ package_name, 'appStatus')
726+
727+ def package_exists(self, container_id, package_name):
728+ return self._test_array_object_key_value_exists(container_id, 'installedApps', 'packageName',
729+ package_name)
730+
731+ """
732+ Fetcher functions for various configuration information.
733+ """
734+ def get_container_distro(self, container_id):
735+ return self._get_value_by_key(container_id, 'distro')
736+
737+ def get_container_type(self, container_id):
738+ return self._get_value_by_key(container_id, 'type')
739+
740
741=== added file 'python/libertine/HostInfo.py'
742--- python/libertine/HostInfo.py 1970-01-01 00:00:00 +0000
743+++ python/libertine/HostInfo.py 2016-07-07 20:14:07 +0000
744@@ -0,0 +1,71 @@
745+# Copyright 2016 Canonical Ltd.
746+#
747+# This program is free software: you can redistribute it and/or modify it
748+# under the terms of the GNU General Public License version 3, as published
749+# by the Free Software Foundation.
750+#
751+# This program is distributed in the hope that it will be useful, but
752+# WITHOUT ANY WARRANTY; without even the implied warranties of
753+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
754+# PURPOSE. See the GNU General Public License for more details.
755+#
756+# You should have received a copy of the GNU General Public License along
757+# with this program. If not, see <http://www.gnu.org/licenses/>.
758+
759+import lsb_release
760+import platform
761+import subprocess
762+
763+from distro_info import UbuntuDistroInfo
764+
765+
766+class HostInfo(object):
767+
768+ def select_container_type_by_kernel(self):
769+ if self.has_lxc_support():
770+ return "lxc"
771+ else:
772+ return "chroot"
773+
774+ def has_lxc_support(self):
775+ kernel_release = platform.release().split('.')
776+ return int(kernel_release[0]) >= 4 or (int(kernel_release[0]) == 3 and int(kernel_release[1]) >= 13)
777+
778+ def get_host_distro_release(self):
779+ distinfo = lsb_release.get_distro_information()
780+
781+ return distinfo.get('CODENAME', 'n/a')
782+
783+ def is_distro_valid(self, distro, force):
784+ if force:
785+ return UbuntuDistroInfo().valid(distro)
786+
787+ if distro == self.get_host_distro_release():
788+ return True
789+
790+ supported_distros = UbuntuDistroInfo().supported()
791+
792+ try:
793+ supported_distros.index(distro)
794+ except ValueError:
795+ return False
796+
797+ return True
798+
799+ def get_distro_codename(self, distro):
800+ ubuntu_distro_info = UbuntuDistroInfo()
801+
802+ for row in ubuntu_distro_info._rows:
803+ if row['series'] == distro:
804+ return row['codename']
805+
806+ return None
807+
808+ def get_host_architecture(self):
809+ dpkg = subprocess.Popen(['dpkg', '--print-architecture'],
810+ stdout=subprocess.PIPE,
811+ universal_newlines=True)
812+ if dpkg.wait() != 0:
813+ parser.error("Failed to determine the local architecture.")
814+
815+ return dpkg.stdout.read().strip()
816
817=== modified file 'python/libertine/Libertine.py'
818--- python/libertine/Libertine.py 2016-06-14 20:05:24 +0000
819+++ python/libertine/Libertine.py 2016-07-07 20:14:07 +0000
820@@ -16,30 +16,12 @@
821 from gi.repository import Libertine
822 import abc
823 import contextlib
824-import json
825 import libertine.utils
826 import os
827 import shutil
828
829-
830-def get_container_type(container_id):
831- """
832- Retrieves the type of container for a given container ID.
833- :param container_id: The Container ID to search for.
834- """
835- try:
836- with open(libertine.utils.get_libertine_database_file_path()) as fd:
837- container_list = json.load(fd)
838-
839- for container in container_list["containerList"]:
840- if container["id"] == container_id:
841- return container["type"]
842-
843- except FileNotFoundError:
844- pass
845-
846- # Return lxc as the default container type
847- return "lxc"
848+from libertine.ContainersConfig import ContainersConfig
849+from libertine.HostInfo import HostInfo
850
851
852 def apt_args_for_verbosity_level(verbosity):
853@@ -175,10 +157,9 @@
854
855 return ret
856 else:
857- cmd = apt_command_prefix(verbosity) + " install '" + package_name + "'"
858 if readline:
859- cmd = "env DEBIAN_FRONTEND=readline " + cmd
860- return self.run_in_container(cmd) == 0
861+ os.environ['DEBIAN_FRONTEND'] = 'readline'
862+ return self.run_in_container(apt_command_prefix(verbosity) + " install '" + package_name + "'") == 0
863
864 def configure_command(self, command, *args, verbosity=1):
865 """
866@@ -207,21 +188,6 @@
867 elif command == 'delete-archive':
868 return self.run_in_container("add-apt-repository -y -r " + args[0])
869
870- def get_container_distro(self, container_id):
871- """
872- Retrieves the distro code name for a given container ID.
873-
874- :param container_id: The Container ID to search for.
875- """
876- with open(libertine.utils.get_libertine_database_file_path()) as fd:
877- container_list = json.load(fd)
878-
879- for container in container_list["containerList"]:
880- if container["id"] == container_id:
881- return container["distro"]
882-
883- return ""
884-
885 @property
886 def name(self):
887 """
888@@ -281,9 +247,9 @@
889 """
890 super().__init__()
891
892- container_type = get_container_type(container_id)
893+ container_type = ContainersConfig().get_container_type(container_id)
894
895- if container_type == "lxc":
896+ if container_type == None or container_type == "lxc":
897 from libertine.LxcContainer import LibertineLXC
898 self.container = LibertineLXC(container_id)
899 elif container_type == "chroot":
900@@ -320,6 +286,9 @@
901 """
902 Creates the container.
903 """
904+ self.container.architecture = HostInfo().get_host_architecture()
905+ self.container.installed_release = ContainersConfig().get_container_distro(self.container_id)
906+
907 return self.container.create_libertine_container(password, multiarch, verbosity)
908
909 def update_libertine_container(self, verbosity=1):
910@@ -351,10 +320,10 @@
911 """
912 try:
913 with ContainerRunning(self.container):
914- cmd = apt_command_prefix(verbosity) + " purge '" + package_name + "'"
915 if readline:
916- cmd = "env DEBIAN_FRONTEND=readline " + cmd
917- if self.container.run_in_container(cmd) != 0:
918+ os.environ['DEBIAN_FRONTEND'] = 'readline'
919+
920+ if self.container.run_in_container(apt_command_prefix(verbosity) + " purge '" + package_name + "'") != 0:
921 return False
922 return self.container.run_in_container(apt_command_prefix(verbosity) + "autoremove --purge") == 0
923 except RuntimeError as e:
924@@ -380,7 +349,11 @@
925 :param app_exec_line: the application exec line as passed in by
926 ubuntu-app-launch
927 """
928- if libertine.utils.container_exists(self.container.container_id):
929+ if ContainersConfig().container_exists(self.container.container_id):
930+ # Update $PATH as necessary
931+ if '/usr/games' not in os.environ['PATH']:
932+ os.environ['PATH'] = os.environ['PATH'] + ":/usr/games"
933+
934 self.container.launch_application(app_exec_line)
935 else:
936 raise RuntimeError("Container with id %s does not exist." % self.container.container_id)
937
938=== modified file 'python/libertine/LxcContainer.py'
939--- python/libertine/LxcContainer.py 2016-06-22 16:26:15 +0000
940+++ python/libertine/LxcContainer.py 2016-07-07 20:14:07 +0000
941@@ -18,6 +18,7 @@
942 import psutil
943 import shlex
944 import subprocess
945+import sys
946 import tempfile
947
948 from .Libertine import BaseContainer
949@@ -85,11 +86,6 @@
950 self.container_type = "lxc"
951 self.container = lxc_container(container_id)
952
953- if self.container.defined:
954- self.lxc_log_file = os.path.join(tempfile.mkdtemp(), 'lxc-start.log')
955- self.container.append_config_item("lxc.logfile", self.lxc_log_file)
956- self.container.append_config_item("lxc.logpriority", "3")
957-
958 def is_running(self):
959 return self.container.running
960
961@@ -105,7 +101,11 @@
962 return True
963
964 def start_container(self):
965+ if not self.container.defined:
966+ raise RuntimeError("Container %s is not valid" % self.container_id)
967+
968 if not self.container.running:
969+ self._set_lxc_log()
970 if not self.container.start():
971 self._dump_lxc_log()
972 raise RuntimeError("Container failed to start")
973@@ -147,8 +147,6 @@
974 if password is None:
975 return False
976
977- installed_release = self.get_container_distro(self.container_id)
978-
979 username = os.environ['USER']
980 user_id = os.getuid()
981 group_id = os.getgid()
982@@ -177,13 +175,10 @@
983
984 utils.create_libertine_user_data_dir(self.container_id)
985
986- # Figure out the host architecture
987- architecture = utils.get_host_architecture()
988-
989 if not self.container.create("download", 0,
990 {"dist": "ubuntu",
991- "release": installed_release,
992- "arch": architecture}):
993+ "release": self.installed_release,
994+ "arch": self.architecture}):
995 print("Failed to create container")
996 return False
997
998@@ -202,7 +197,7 @@
999 self.run_in_container("useradd -u {} -p {} -G sudo {}".format(
1000 str(user_id), crypt.crypt(password), str(username)))
1001
1002- if multiarch and architecture == 'amd64':
1003+ if multiarch and self.architecture == 'amd64':
1004 if verbosity == 1:
1005 print("Adding i386 multiarch support...")
1006 self.run_in_container("dpkg --add-architecture i386")
1007@@ -308,7 +303,15 @@
1008 data = libertine_lxc_mgr_sock.recv(1024)
1009 libertine_lxc_mgr_sock.close()
1010
1011+ def _set_lxc_log(self):
1012+ self.lxc_log_file = os.path.join(tempfile.mkdtemp(), 'lxc-start.log')
1013+ self.container.append_config_item("lxc.logfile", self.lxc_log_file)
1014+ self.container.append_config_item("lxc.logpriority", "3")
1015+
1016 def _dump_lxc_log(self):
1017- with open(self.lxc_log_file, 'r') as fd:
1018- for line in fd:
1019- print(line.lstrip())
1020+ try:
1021+ with open(self.lxc_log_file, 'r') as fd:
1022+ for line in fd:
1023+ print(line.lstrip())
1024+ except Exception as ex:
1025+ print("Could not open LXC log file: %s" % ex, file=sys.stderr)
1026
1027=== modified file 'python/libertine/utils.py'
1028--- python/libertine/utils.py 2016-06-23 13:27:26 +0000
1029+++ python/libertine/utils.py 2016-07-07 20:14:07 +0000
1030@@ -16,9 +16,7 @@
1031 # You should have received a copy of the GNU General Public License
1032 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1033
1034-import json
1035 import os
1036-import psutil
1037 import shlex
1038 import subprocess
1039 import xdg.BaseDirectory as basedir
1040@@ -28,22 +26,6 @@
1041 from gi.repository import Libertine
1042
1043
1044-def container_exists(container_id):
1045- container_config_file_path = get_libertine_database_file_path()
1046-
1047- if (os.path.exists(container_config_file_path) and
1048- os.path.getsize(container_config_file_path) != 0):
1049- with open(get_libertine_database_file_path()) as fd:
1050- container_list = json.load(fd)
1051-
1052- if container_list:
1053- for container in container_list['containerList']:
1054- if container['id'] == container_id:
1055- return True
1056-
1057- return False
1058-
1059-
1060 def get_libertine_container_rootfs_path(container_id):
1061 path = Libertine.container_path(container_id)
1062
1063@@ -97,16 +79,6 @@
1064 return os.path.join(get_user_runtime_dir(), 'libertine')
1065
1066
1067-def get_host_architecture():
1068- dpkg = subprocess.Popen(['dpkg', '--print-architecture'],
1069- stdout=subprocess.PIPE,
1070- universal_newlines=True)
1071- if dpkg.wait() != 0:
1072- parser.error("Failed to determine the local architecture.")
1073-
1074- return dpkg.stdout.read().strip()
1075-
1076-
1077 def get_common_xdg_directories():
1078 return ['Documents', 'Music', 'Pictures', 'Videos', 'Downloads']
1079
1080@@ -167,4 +139,4 @@
1081 gdbus_cmd = ("gdbus emit --session --object-path %s --signal %s %s" %
1082 (scopes_object_path, invalidate_signal, libertine_scope_id))
1083
1084- subprocess.Popen(shlex.split(gdbus_cmd))
1085+ subprocess.Popen(shlex.split(gdbus_cmd), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
1086
1087=== modified file 'tests/unit/CMakeLists.txt'
1088--- tests/unit/CMakeLists.txt 2015-12-21 21:02:33 +0000
1089+++ tests/unit/CMakeLists.txt 2016-07-07 20:14:07 +0000
1090@@ -44,10 +44,14 @@
1091 ENVIRONMENT
1092 "GI_TYPELIB_PATH=${CMAKE_BINARY_DIR}/liblibertine;LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/liblibertine:${LD_LIBRARY_PATH};CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR};PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}:${CMAKE_SOURCE_DIR}/python;CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}")
1093
1094-add_test(test_libertine_launch
1095- "/usr/bin/python3" "-m" "testtools.run" "libertine_launch_tests"
1096-)
1097-set_tests_properties(test_libertine_launch
1098- PROPERTIES
1099- ENVIRONMENT
1100- "GI_TYPELIB_PATH=${CMAKE_BINARY_DIR}/liblibertine;LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/liblibertine:${LD_LIBRARY_PATH};CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR};PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}:${CMAKE_SOURCE_DIR}/python;CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}")
1101+set(DISABLED 1)
1102+
1103+if (NOT DISABLED)
1104+ add_test(test_libertine_launch
1105+ "/usr/bin/python3" "-m" "testtools.run" "libertine_launch_tests"
1106+ )
1107+ set_tests_properties(test_libertine_launch
1108+ PROPERTIES
1109+ ENVIRONMENT
1110+ "GI_TYPELIB_PATH=${CMAKE_BINARY_DIR}/liblibertine;LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/liblibertine:${LD_LIBRARY_PATH};CMAKE_BINARY_DIR=${CMAKE_BINARY_DIR};PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR}:${CMAKE_SOURCE_DIR}/python;CMAKE_SOURCE_DIR=${CMAKE_SOURCE_DIR}")
1111+endif()
1112
1113=== modified file 'tools/libertine-container-manager'
1114--- tools/libertine-container-manager 2016-06-20 15:15:38 +0000
1115+++ tools/libertine-container-manager 2016-07-07 20:14:07 +0000
1116@@ -17,637 +17,270 @@
1117 # along with this program. If not, see <http://www.gnu.org/licenses/>.
1118
1119 import argparse
1120-import fcntl
1121-import json
1122 import libertine.utils
1123-import lsb_release
1124 import getpass
1125 import os
1126-import platform
1127 import sys
1128
1129 from apt.debfile import DebPackage
1130-from distro_info import UbuntuDistroInfo, DistroDataOutdated
1131 from libertine import LibertineContainer
1132-
1133-
1134-def find_duplicate_container_entry(container_list, container_id):
1135- for container in container_list['containerList']:
1136- if container['id'] == container_id:
1137- return container
1138-
1139- return None
1140-
1141-
1142-def merge_container_config_files(filepath):
1143- merged_json = []
1144- main_config = read_container_config_file()
1145-
1146- with open(filepath, 'r') as fd:
1147- merge_source = json.load(fd)
1148-
1149- if "containerList" in main_config:
1150- # Finds any duplicate entries and assumes we want to update the main config
1151- # with entries from the merge source.
1152- for i, container in enumerate(main_config['containerList']):
1153- merge_container = find_duplicate_container_entry(merge_source, container['id'])
1154- if merge_container:
1155- main_config['containerList'][i] = merge_container
1156- merge_source['containerList'].remove(merge_container)
1157-
1158- # Merges in any remaining non-duplicate entries.
1159- for container in merge_source['containerList']:
1160- main_config['containerList'].append(container)
1161-
1162- else:
1163- main_config = merge_source
1164-
1165- write_container_config_file(main_config)
1166-
1167-
1168-def read_container_config_file():
1169- container_list = {}
1170- container_config_file = libertine.utils.get_libertine_database_file_path()
1171-
1172- if (os.path.exists(container_config_file) and
1173- os.path.getsize(container_config_file) != 0):
1174- with open(container_config_file, 'r') as fd:
1175- container_list = json.load(fd)
1176-
1177- return container_list
1178-
1179-
1180-def write_container_config_file(container_list):
1181- container_config_file = libertine.utils.get_libertine_database_file_path()
1182-
1183- with open(container_config_file, 'w') as fd:
1184- fcntl.lockf(fd, fcntl.LOCK_EX)
1185- json.dump(container_list, fd, sort_keys=True, indent=4)
1186- fd.write('\n')
1187- fcntl.lockf(fd, fcntl.LOCK_UN)
1188-
1189-
1190-def get_default_container_id():
1191- default_container_id = None
1192-
1193- container_list = read_container_config_file()
1194-
1195- if "defaultContainer" in container_list:
1196- default_container_id = container_list['defaultContainer']
1197-
1198- return default_container_id
1199-
1200-
1201-def select_container_type():
1202- kernel_release = platform.release().split('.')
1203-
1204- if int(kernel_release[0]) >= 4:
1205- return "lxc"
1206- elif int(kernel_release[0]) == 3 and int(kernel_release[1]) >= 13:
1207- return "lxc"
1208- else:
1209- return "chroot"
1210-
1211-
1212-def get_host_distro_release():
1213- distinfo = lsb_release.get_distro_information()
1214-
1215- return distinfo.get('CODENAME', 'n/a')
1216-
1217-
1218-def is_distro_valid(distro, force):
1219- if force:
1220- return UbuntuDistroInfo().valid(distro)
1221-
1222- if distro == get_host_distro_release():
1223- return True
1224-
1225- supported_distros = UbuntuDistroInfo().supported()
1226-
1227- try:
1228- supported_distros.index(distro)
1229- except ValueError:
1230- return False
1231-
1232- return True
1233-
1234-
1235-def get_distro_codename(distro):
1236- ubuntu_distro_info = UbuntuDistroInfo()
1237-
1238- for row in ubuntu_distro_info._rows:
1239- if row['series'] == distro:
1240- return row['codename']
1241-
1242- return None
1243-
1244-
1245-def update_container_install_status(container_id, new_status):
1246- container_list = read_container_config_file()
1247-
1248- for container in container_list['containerList']:
1249- if container['id'] == container_id:
1250- container['installStatus'] = new_status
1251-
1252- write_container_config_file(container_list)
1253- break
1254-
1255-
1256-def update_container_multiarch_support(container_id, multiarch):
1257- container_list = read_container_config_file()
1258-
1259- if multiarch == 'enabled' and libertine.utils.get_host_architecture() == 'i386':
1260- multiarch = 'disabled'
1261-
1262- for container in container_list['containerList']:
1263- if container['id'] == container_id:
1264- container['multiarch'] = multiarch
1265-
1266- write_container_config_file(container_list)
1267- break
1268-
1269-
1270-def get_container_multiarch_support(container_id):
1271- container_list = read_container_config_file()
1272-
1273- for container in container_list['containerList']:
1274- if container['id'] == container_id:
1275- if not 'multiarch' in container:
1276- return 'disabled'
1277- else:
1278- return container['multiarch']
1279-
1280-
1281-def update_archive_install_status(container_id, archive_name, new_status):
1282- container_list = read_container_config_file()
1283-
1284- for container in container_list['containerList']:
1285- if container['id'] == container_id:
1286- for archive in container['extraArchives']:
1287- if archive['archiveName'] == archive_name:
1288- archive['archiveStatus'] = new_status
1289- write_container_config_file(container_list)
1290- return
1291-
1292-
1293-def add_container_archive(container_id, archive_name):
1294- container_list = read_container_config_file()
1295-
1296- for container in container_list['containerList']:
1297- if container['id'] == container_id:
1298- archive_obj = {'archiveName': archive_name, 'archiveStatus': 'new'}
1299-
1300- if 'extraArchives' not in container:
1301- container['extraArchives'] = [archive_obj]
1302- else:
1303- container['extraArchives'].append(archive_obj)
1304-
1305- write_container_config_file(container_list)
1306- break
1307-
1308-
1309-def delete_container_archive(container_id, archive_name):
1310- container_list = read_container_config_file()
1311-
1312- for container in container_list['containerList']:
1313- if container['id'] == container_id:
1314- for archive in container['extraArchives']:
1315- if archive['archiveName'] == archive_name:
1316- container['extraArchives'].remove(archive)
1317- write_container_config_file(container_list)
1318- return
1319-
1320- print("%s does not exist." % archive_name)
1321- sys.exit(1)
1322-
1323-
1324-def archive_exists(container_id, archive_name):
1325- container_list = read_container_config_file()
1326-
1327- for container in container_list['containerList']:
1328- if container['id'] == container_id:
1329- if 'extraArchives' not in container:
1330- return False
1331- else:
1332- for archive in container['extraArchives']:
1333- if archive['archiveName'] == archive_name:
1334- return True
1335-
1336- return False
1337-
1338-
1339-def add_new_container(id, name, type, distro):
1340- if not os.path.exists(libertine.utils.get_libertine_database_dir_path()):
1341- os.makedirs(libertine.utils.get_libertine_database_dir_path())
1342-
1343- container_list = read_container_config_file()
1344-
1345- container_obj = {'id': id, 'installStatus': 'new', 'type': type,
1346- 'distro': distro, 'name': name, 'installedApps': []}
1347-
1348- if "defaultContainer" not in container_list:
1349- container_list['defaultContainer'] = id
1350-
1351- if "containerList" not in container_list:
1352- container_list['containerList'] = [container_obj]
1353- else:
1354- container_list['containerList'].append(container_obj)
1355-
1356- write_container_config_file(container_list)
1357-
1358-
1359-def delete_container(container_id):
1360- container_list = read_container_config_file()
1361-
1362- if not container_list:
1363- print("Unable to delete container. No containers defined.")
1364- sys.exit(1)
1365-
1366- for container in container_list['containerList']:
1367- if container['id'] == container_id:
1368- container_list['containerList'].remove(container)
1369-
1370- # Set a new defaultContainer if the current default is being deleted.
1371- if container_list['defaultContainer'] == container_id and container_list['containerList']:
1372- container_list['defaultContainer'] = container_list['containerList'][0]['id']
1373- # Remove the defaultContainer if there are no more containers left.
1374- elif not container_list['containerList']:
1375- del container_list['defaultContainer']
1376-
1377- write_container_config_file(container_list)
1378- break
1379-
1380-
1381-def package_exists(container_id, package_name):
1382- container_list = read_container_config_file()
1383-
1384- if not container_list:
1385- return False
1386-
1387- for container in container_list['containerList']:
1388- if container['id'] == container_id:
1389- for package in container['installedApps']:
1390- if package['packageName'] == package_name:
1391- return True
1392-
1393- return False
1394-
1395-
1396-def update_package_install_status(container_id, package_name, new_status):
1397- container_list = read_container_config_file()
1398-
1399- for container in container_list['containerList']:
1400- if container['id'] == container_id:
1401- for package in container['installedApps']:
1402- if package['packageName'] == package_name:
1403- package['appStatus'] = new_status
1404- write_container_config_file(container_list)
1405- return
1406-
1407-
1408-def get_package_install_status(container_id, package_name):
1409- container_list = read_container_config_file()
1410-
1411- for container in container_list['containerList']:
1412- if container['id'] == container_id:
1413- for package in container['installedApps']:
1414- if package['packageName'] == package_name:
1415- return package['appStatus']
1416-
1417-
1418-def add_new_package(container_id, package_name):
1419- container_list = read_container_config_file()
1420-
1421- if not container_list:
1422- print("No containers defined. Please create a new container before installing a package.")
1423- sys.exit(1)
1424-
1425- for container in container_list['containerList']:
1426- if container['id'] == container_id:
1427- package_obj = {'packageName': package_name, 'appStatus': 'new'}
1428-
1429- if not container['installedApps']:
1430- container['installedApps'] = [package_obj]
1431- else:
1432- container['installedApps'].append(package_obj)
1433-
1434- write_container_config_file(container_list)
1435- break
1436-
1437-
1438-def delete_package(container_id, package_name):
1439- container_list = read_container_config_file()
1440-
1441- if not container_list:
1442- print("No containers defined. Please create a new container before installing a package.")
1443- sys.exit(1)
1444-
1445- for container in container_list['containerList']:
1446- if container['id'] == container_id:
1447- for package in container['installedApps']:
1448- if package['packageName'] == package_name:
1449- container['installedApps'].remove(package)
1450- write_container_config_file(container_list)
1451- return
1452-
1453- print("Package \'%s\' does not exist." % package_name)
1454- sys.exit(1)
1455-
1456-
1457-def create(args):
1458- password = None
1459-
1460- if args.distro and not is_distro_valid(args.distro, args.force):
1461- print("Invalid distro %s" % args.distro, file=sys.stderr)
1462- sys.exit(1)
1463-
1464- if args.id and libertine.utils.container_exists(args.id):
1465- print("Container id \'%s\' is already used." % args.id, file=sys.stderr)
1466- sys.exit(1)
1467- elif not args.id:
1468- args.id = get_unique_container_id(distro)
1469-
1470- if not args.type:
1471- container_type = select_container_type()
1472- else:
1473- container_type = args.type
1474-
1475- if not args.distro:
1476- args.distro = get_host_distro_release()
1477- elif container_type == "chroot":
1478- host_distro = get_host_distro_release()
1479-
1480- if args.distro != host_distro:
1481- print("The container distribution needs to match the host ditribution for chroot"
1482- " based containers. Please either use \'%s\' or omit the -d/--distro option."
1483- % host_distro)
1484- sys.exit(1)
1485-
1486- if not args.name:
1487- args.name = "Ubuntu \'" + get_distro_codename(args.distro) + "\'"
1488-
1489- if container_type == "lxc":
1490- if args.password:
1491- password = args.password
1492- elif sys.stdin.isatty():
1493- print("Your user password is required for creating a Libertine container.")
1494- password = getpass.getpass()
1495- else:
1496- password = sys.stdin.readline().rstrip()
1497-
1498- add_new_container(args.id, args.name, container_type, args.distro)
1499-
1500- multiarch = 'disabled'
1501- if args.multiarch:
1502- multiarch = 'enabled'
1503- update_container_multiarch_support(args.id, multiarch)
1504-
1505- container = LibertineContainer(args.id)
1506- update_container_install_status(args.id, "installing")
1507- if not container.create_libertine_container(password, args.multiarch, args.verbosity):
1508- delete_container(args.id)
1509- sys.exit(1)
1510- update_container_install_status(args.id, "ready")
1511-
1512- libertine.utils.refresh_libertine_scope()
1513-
1514-
1515-def destroy_container_by_id(id):
1516- container = LibertineContainer(id)
1517- update_container_install_status(id, "removing")
1518- container.destroy_libertine_container()
1519- update_container_install_status(id, "removed")
1520- delete_container(id)
1521-
1522-
1523-def destroy(args):
1524- if args.id and not libertine.utils.container_exists(args.id):
1525- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1526- sys.exit(1)
1527- elif not args.id:
1528- args.id = get_default_container_id()
1529-
1530- destroy_container_by_id(args.id)
1531-
1532- libertine.utils.refresh_libertine_scope()
1533-
1534-
1535-def install_package(args):
1536- if args.id and not libertine.utils.container_exists(args.id):
1537- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1538- sys.exit(1)
1539- elif not args.id:
1540- args.id = get_default_container_id()
1541-
1542- is_debian_package = args.package.endswith('.deb')
1543-
1544- if is_debian_package:
1545- if os.path.exists(args.package):
1546- package = DebPackage(args.package).pkgname
1547- else:
1548- print("%s does not exist." % args.package)
1549- sys.exit(1)
1550- else:
1551- package = args.package
1552-
1553- if package_exists(args.id, package):
1554- if not is_debian_package:
1555- print("Package \'%s\' is already installed." % package)
1556- sys.exit(1)
1557- else:
1558- add_new_package(args.id, package)
1559-
1560- container = LibertineContainer(args.id)
1561-
1562- update_package_install_status(args.id, package, "installing")
1563- if not container.install_package(args.package, args.verbosity, args.readline):
1564- delete_package(args.id, package)
1565- sys.exit(1)
1566-
1567- update_package_install_status(args.id, package, "installed")
1568-
1569- libertine.utils.refresh_libertine_scope()
1570-
1571-
1572-def remove_package_by_name(container_id, package_name, verbosity=1, readline=False):
1573- fallback_status = get_package_install_status(container_id, package_name)
1574- update_package_install_status(container_id, package_name, "removing")
1575-
1576- container = LibertineContainer(container_id)
1577- if not container.remove_package(package_name, verbosity, readline):
1578- update_package_install_status(container_id, package_name, fallback_status)
1579- return False
1580-
1581- update_package_install_status(container_id, package_name, "removed")
1582- delete_package(container_id, package_name)
1583-
1584- return True
1585-
1586-
1587-def remove_package(args):
1588- if args.id and not libertine.utils.container_exists(args.id):
1589- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1590- sys.exit(1)
1591- elif not args.id:
1592- args.id = get_default_container_id()
1593-
1594- if get_package_install_status(args.id, args.package) != 'installed':
1595- print("Package \'%s\' is not installed." % args.package)
1596- sys.exit(1)
1597-
1598- if not remove_package_by_name(args.id, args.package, args.verbosity, args.readline):
1599- sys.exit(1)
1600-
1601- libertine.utils.refresh_libertine_scope()
1602-
1603-
1604-def search_cache(args):
1605- if args.id and not libertine.utils.container_exists(args.id):
1606- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1607- sys.exit(1)
1608- elif not args.id:
1609- args.id = get_default_container_id()
1610-
1611- container = LibertineContainer(args.id)
1612- if container.search_package_cache(args.search_string) is not 0:
1613- sys.exit(1)
1614-
1615-
1616-def update(args):
1617- if args.id and not libertine.utils.container_exists(args.id):
1618- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1619- sys.exit(1)
1620- elif not args.id:
1621- args.id = get_default_container_id()
1622-
1623- container = LibertineContainer(args.id)
1624-
1625- update_container_install_status(args.id, "updating")
1626- if container.update_libertine_container(args.verbosity) is not 0:
1627- update_container_install_status(args.id, "ready")
1628- sys.exit(1)
1629-
1630- update_container_install_status(args.id, "ready")
1631-
1632-
1633-def list(args):
1634- containers = libertine.utils.Libertine.list_containers()
1635- for container in containers:
1636- print("%s" % container)
1637-
1638-
1639-def list_apps(args):
1640- if args.id and not libertine.utils.container_exists(args.id):
1641- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1642- sys.exit(1)
1643- elif not args.id:
1644- args.id = get_default_container_id()
1645-
1646- container = LibertineContainer(args.id)
1647- print(container.list_app_launchers(use_json=args.json))
1648-
1649-
1650-def exec(args):
1651- if args.id and not libertine.utils.container_exists(args.id):
1652- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1653- sys.exit(1)
1654- elif not args.id:
1655- args.id = get_default_container_id()
1656-
1657- container = LibertineContainer(args.id)
1658-
1659- if not container.exec_command(args.command):
1660- sys.exit(1)
1661-
1662-
1663-def delete_archive_by_name(container_id, archive_name):
1664- update_archive_install_status(container_id, archive_name, 'removing')
1665- if LibertineContainer(container_id).configure_command('delete-archive', archive_name) is not 0:
1666- return False
1667- delete_container_archive(container_id, archive_name)
1668- return True
1669-
1670-
1671-def configure(args):
1672- if args.id and not libertine.utils.container_exists(args.id):
1673- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1674- sys.exit(1)
1675- elif not args.id:
1676- args.id = get_default_container_id()
1677-
1678- container = LibertineContainer(args.id)
1679-
1680- if args.multiarch and libertine.utils.get_host_architecture() == 'amd64':
1681+from libertine.ContainersConfig import ContainersConfig
1682+from libertine.HostInfo import HostInfo
1683+
1684+
1685+class LibertineContainerManager(object):
1686+
1687+ def __init__(self):
1688+ self.containers_config = ContainersConfig()
1689+ self.host_info = HostInfo()
1690+
1691+ def create(self, args):
1692+ password = None
1693+
1694+ if args.distro and not self.host_info.is_distro_valid(args.distro, args.force):
1695+ print("Invalid distro %s" % args.distro, file=sys.stderr)
1696+ sys.exit(1)
1697+
1698+ if args.id and self.containers_config.container_exists(args.id):
1699+ print("Container id \'%s\' is already used." % args.id, file=sys.stderr)
1700+ sys.exit(1)
1701+ elif not args.id:
1702+ args.id = get_unique_container_id(distro)
1703+
1704+ if not args.type:
1705+ container_type = self.host_info.select_container_type_by_kernel()
1706+ else:
1707+ if args.type == 'lxc' and not self.host_info.has_lxc_support():
1708+ print("System kernel does not support lxc type containers. "
1709+ "Please either use chroot or omit the -t option.")
1710+ sys.exit(1)
1711+ container_type = args.type
1712+
1713+ if not args.distro:
1714+ args.distro = self.host_info.get_host_distro_release()
1715+ elif container_type == "chroot":
1716+ host_distro = self.host_info.get_host_distro_release()
1717+
1718+ if args.distro != host_distro:
1719+ print("The container distribution needs to match the host ditribution for chroot"
1720+ " based containers. Please either use \'%s\' or omit the -d/--distro option."
1721+ % host_distro)
1722+ sys.exit(1)
1723+
1724+ if not args.name:
1725+ args.name = "Ubuntu \'" + self.host_info.get_distro_codename(args.distro) + "\'"
1726+
1727+ if container_type == "lxc":
1728+ if args.password:
1729+ password = args.password
1730+ elif sys.stdin.isatty():
1731+ print("Your user password is required for creating a Libertine container.")
1732+ password = getpass.getpass()
1733+ else:
1734+ password = sys.stdin.readline().rstrip()
1735+
1736+ self.containers_config.add_new_container(args.id, args.name, container_type, args.distro)
1737+
1738 multiarch = 'disabled'
1739 if args.multiarch == 'enable':
1740 multiarch = 'enabled'
1741-
1742- current_multiarch = get_container_multiarch_support(args.id)
1743- if current_multiarch == multiarch:
1744- print("i386 multiarch support is already %s" % multiarch)
1745- sys.exit(1)
1746-
1747- if container.configure_command('multiarch', args.multiarch) is not 0:
1748- sys.exit(1)
1749-
1750- update_container_multiarch_support(args.id, multiarch)
1751-
1752- elif args.add_archive:
1753- if archive_exists(args.id, args.add_archive):
1754- print("%s already added in container." % args.add_archive)
1755- sys.exit(1)
1756-
1757- add_container_archive(args.id, args.add_archive)
1758- update_archive_install_status(args.id, args.add_archive, 'installing')
1759- if container.configure_command('add-archive', args.add_archive) is not 0:
1760- delete_container_archive(args.id, args.add_archive)
1761- sys.exit(1)
1762-
1763- update_archive_install_status(args.id, args.add_archive, 'installed')
1764-
1765- elif args.delete_archive:
1766- if not archive_exists(args.id, args.delete_archive):
1767- print("%s is not added in container." % args.delete_archive)
1768- sys.exit(1)
1769-
1770- if not delete_archive_by_name(args.id, args.delete_archive):
1771- sys.exit(1)
1772-
1773-
1774-def merge(args):
1775- merge_container_config_files(args.file)
1776-
1777-
1778-def fix_integrity(args):
1779- for container in read_container_config_file()['containerList']:
1780- if container['installStatus'] != 'ready':
1781- destroy_container_by_id(container['id'])
1782- continue
1783- LibertineContainer(container['id']).exec_command('dpkg --configure -a')
1784-
1785- for package in container['installedApps']:
1786- if package['appStatus'] != 'installed':
1787- remove_package_by_name(container['id'], package['packageName'])
1788- if 'extraArchives' in container:
1789- for archive in container['extraArchives']:
1790- if archive['archiveStatus'] != 'installed':
1791- delete_archive_by_name(container['id'], archive['archiveName'])
1792-
1793-
1794-def set_default(args):
1795- if args.clear:
1796- container_list = read_container_config_file()
1797- container_list.pop('defaultContainer', None)
1798- write_container_config_file(container_list)
1799- sys.exit(0)
1800-
1801- if not libertine.utils.container_exists(args.id):
1802- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
1803- sys.exit(1)
1804-
1805- container_list = read_container_config_file()
1806- container_list['defaultContainer'] = args.id
1807- write_container_config_file(container_list)
1808+ self.containers_config.update_container_multiarch_support(args.id, multiarch)
1809+
1810+ container = LibertineContainer(args.id)
1811+ self.containers_config.update_container_install_status(args.id, "installing")
1812+ if not container.create_libertine_container(password, args.multiarch, args.verbosity):
1813+ self.containers_config.delete_container(args.id)
1814+ sys.exit(1)
1815+ self.containers_config.update_container_install_status(args.id, "ready")
1816+
1817+ libertine.utils.refresh_libertine_scope()
1818+
1819+ def destroy_container_by_id(self, id):
1820+ container = LibertineContainer(id)
1821+
1822+ self.containers_config.update_container_install_status(id, "removing")
1823+ container.destroy_libertine_container()
1824+ self.containers_config.update_container_install_status(id, "removed")
1825+ self.containers_config.delete_container(id)
1826+
1827+ def destroy(self, args):
1828+ args.id = self.containers_config.check_container_id(args.id)
1829+
1830+ self.destroy_container_by_id(args.id)
1831+
1832+ libertine.utils.refresh_libertine_scope()
1833+
1834+ def install_package(self, args):
1835+ container_id = self.containers_config.check_container_id(args.id)
1836+
1837+ is_debian_package = args.package.endswith('.deb')
1838+
1839+ if is_debian_package:
1840+ if os.path.exists(args.package):
1841+ package = DebPackage(args.package).pkgname
1842+ else:
1843+ print("%s does not exist." % args.package)
1844+ sys.exit(1)
1845+ else:
1846+ package = args.package
1847+
1848+ if self.containers_config.package_exists(container_id, package):
1849+ if not is_debian_package:
1850+ print("Package \'%s\' is already installed." % package)
1851+ sys.exit(1)
1852+ else:
1853+ self.containers_config.add_new_package(container_id, package)
1854+
1855+ container = LibertineContainer(container_id)
1856+
1857+ self.containers_config.update_package_install_status(container_id, package, "installing")
1858+ if not container.install_package(args.package, args.verbosity, args.readline):
1859+ self.containers_config.delete_package(container_id, package)
1860+ sys.exit(1)
1861+
1862+ self.containers_config.update_package_install_status(container_id, package, "installed")
1863+
1864+ libertine.utils.refresh_libertine_scope()
1865+
1866+ def remove_package_by_name(self, container_id, package_name, verbosity=1, readline=False):
1867+ fallback_status = self.containers_config.get_package_install_status(container_id, package_name)
1868+ self.containers_config.update_package_install_status(container_id, package_name, "removing")
1869+
1870+ container = LibertineContainer(container_id)
1871+ if not container.remove_package(package_name, verbosity, readline) and fallback_status == 'installed':
1872+ self.containers_config.update_package_install_status(container_id, package_name, fallback_status)
1873+ return False
1874+
1875+ self.containers_config.update_package_install_status(container_id, package_name, "removed")
1876+ self.containers_config.delete_package(container_id, package_name)
1877+
1878+ return True
1879+
1880+ def remove_package(self, args):
1881+ container_id = self.containers_config.check_container_id(args.id)
1882+
1883+ if self.containers_config.get_package_install_status(container_id, args.package) != 'installed':
1884+ print("Package \'%s\' is not installed." % args.package)
1885+ sys.exit(1)
1886+
1887+ if not self.remove_package_by_name(container_id, args.package, args.verbosity, args.readline):
1888+ sys.exit(1)
1889+
1890+ libertine.utils.refresh_libertine_scope()
1891+
1892+ def search_cache(self, args):
1893+ container_id = self.containers_config.check_container_id(args.id)
1894+
1895+ container = LibertineContainer(container_id)
1896+ if container.search_package_cache(args.search_string) is not 0:
1897+ sys.exit(1)
1898+
1899+ def update(self, args):
1900+ container_id = self.containers_config.check_container_id(args.id)
1901+
1902+ container = LibertineContainer(container_id)
1903+
1904+ self.containers_config.update_container_install_status(container_id, "updating")
1905+ if container.update_libertine_container(args.verbosity) is not 0:
1906+ self.containers_config.update_container_install_status(container_id, "ready")
1907+ sys.exit(1)
1908+
1909+ self.containers_config.update_container_install_status(container_id, "ready")
1910+
1911+ def list(self, args):
1912+ containers = libertine.utils.Libertine.list_containers()
1913+ for container in containers:
1914+ print("%s" % container)
1915+
1916+ def list_apps(self, args):
1917+ container_id = self.containers_config.check_container_id(args.id)
1918+
1919+ container = LibertineContainer(container_id)
1920+ print(container.list_app_launchers(use_json=args.json))
1921+
1922+ def exec(self, args):
1923+ container_id = self.containers_config.check_container_id(args.id)
1924+
1925+ container = LibertineContainer(container_id)
1926+
1927+ if not container.exec_command(args.command):
1928+ sys.exit(1)
1929+
1930+ def delete_archive_by_name(self, container_id, archive_name):
1931+ self.containers_config.update_archive_install_status(container_id, archive_name, 'removing')
1932+ if LibertineContainer(container_id).configure_command('delete-archive', archive_name) is not 0:
1933+ return False
1934+ self.containers_config.delete_container_archive(container_id, archive_name)
1935+ return True
1936+
1937+ def configure(self, args):
1938+ container_id = self.containers_config.check_container_id(args.id)
1939+
1940+ container = LibertineContainer(container_id)
1941+
1942+ if args.multiarch and self.host_info.get_host_architecture() == 'amd64':
1943+ multiarch = 'disabled'
1944+ if args.multiarch == 'enable':
1945+ multiarch = 'enabled'
1946+
1947+ current_multiarch = self.containers_config.get_container_multiarch_support(container_id)
1948+ if current_multiarch == multiarch:
1949+ print("i386 multiarch support is already %s" % multiarch)
1950+ sys.exit(1)
1951+
1952+ if container.configure_command('multiarch', args.multiarch) is not 0:
1953+ sys.exit(1)
1954+
1955+ self.containers_config.update_container_multiarch_support(container_id, multiarch)
1956+
1957+ elif args.add_archive:
1958+ if self.containers_config.archive_exists(container_id, args.add_archive):
1959+ print("%s already added in container." % args.add_archive)
1960+ sys.exit(1)
1961+
1962+ self.containers_config.add_container_archive(container_id, args.add_archive)
1963+ self.containers_config.update_archive_install_status(container_id, args.add_archive, 'installing')
1964+ if container.configure_command('add-archive', args.add_archive) is not 0:
1965+ self.containers_config.delete_container_archive(container_id, args.add_archive)
1966+ sys.exit(1)
1967+
1968+ self.containers_config.update_archive_install_status(container_id, args.add_archive, 'installed')
1969+
1970+ elif args.delete_archive:
1971+ if not self.containers_config.archive_exists(container_id, args.delete_archive):
1972+ print("%s is not added in container." % args.delete_archive)
1973+ sys.exit(1)
1974+
1975+ if not self.delete_archive_by_name(container_id, args.delete_archive):
1976+ sys.exit(1)
1977+
1978+ def merge(self, args):
1979+ self.containers_config.merge_container_config_files(args.file)
1980+
1981+ def fix_integrity(self, args):
1982+ for container in self.containers_config.container_list['containerList']:
1983+ if 'installStatus' not in container or container['installStatus'] != 'ready':
1984+ self.destroy_container_by_id(container['id'])
1985+ continue
1986+ LibertineContainer(container['id']).exec_command('dpkg --configure -a')
1987+
1988+ for package in container['installedApps']:
1989+ if package['appStatus'] != 'installed':
1990+ self.remove_package_by_name(container['id'], package['packageName'])
1991+
1992+ if 'extraArchives' in container:
1993+ for archive in container['extraArchives']:
1994+ if archive['archiveStatus'] != 'installed':
1995+ self.delete_archive_by_name(container['id'], archive['archiveName'])
1996+
1997+ def set_default(self, args):
1998+ if args.clear:
1999+ self.containers_config.clear_default_container_id(True)
2000+ sys.exit(0)
2001+
2002+ container_id = self.containers_config.check_container_id(args.id)
2003+
2004+ self.containers_config.set_default_container_id(container_id, True)
2005
2006
2007 if __name__ == '__main__':
2008@@ -657,6 +290,8 @@
2009 print("Please do not run %s using sudo" % parser.prog)
2010 sys.exit(1)
2011
2012+ container_manager = LibertineContainerManager()
2013+
2014 parser.add_argument('-q', '--quiet',
2015 action='store_const', dest='verbosity', const=0,
2016 help=('do not print status updates on stdout'))
2017@@ -696,7 +331,7 @@
2018 '--password',
2019 help=("Pass in the user's password when creating an LXC container. This "
2020 "is intended for testing only and is very insecure."))
2021- parser_create.set_defaults(func=create)
2022+ parser_create.set_defaults(func=container_manager.create)
2023
2024 # Handle the destroy command and its options
2025 parser_destroy = subparsers.add_parser(
2026@@ -705,7 +340,7 @@
2027 parser_destroy.add_argument(
2028 '-i', '--id',
2029 help=("Container identifier. Default container is used if omitted."))
2030- parser_destroy.set_defaults(func=destroy)
2031+ parser_destroy.set_defaults(func=container_manager.destroy)
2032
2033 # Handle the install-package command and its options
2034 parser_install = subparsers.add_parser(
2035@@ -721,7 +356,7 @@
2036 parser_install.add_argument(
2037 '-r', '--readline', action='store_true',
2038 help=("Readline mode. Use text-based frontend during debconf interactions."))
2039- parser_install.set_defaults(func=install_package)
2040+ parser_install.set_defaults(func=container_manager.install_package)
2041
2042 # Handle the remove-package command and its options
2043 parser_remove = subparsers.add_parser(
2044@@ -737,7 +372,7 @@
2045 parser_remove.add_argument(
2046 '-r', '--readline', action='store_true',
2047 help=("Readline mode. Use text-based frontend during debconf interactions."))
2048- parser_remove.set_defaults(func=remove_package)
2049+ parser_remove.set_defaults(func=container_manager.remove_package)
2050
2051 # Handle the search-cache command and its options
2052 parser_search = subparsers.add_parser(
2053@@ -750,7 +385,7 @@
2054 parser_search.add_argument(
2055 '-i', '--id',
2056 help=("Container identifier. Default container is used if omitted."))
2057- parser_search.set_defaults(func=search_cache)
2058+ parser_search.set_defaults(func=container_manager.search_cache)
2059
2060 # Handle the update command and its options
2061 parser_update = subparsers.add_parser(
2062@@ -759,13 +394,13 @@
2063 parser_update.add_argument(
2064 '-i', '--id',
2065 help=("Container identifier. Default container is used if omitted."))
2066- parser_update.set_defaults(func=update)
2067+ parser_update.set_defaults(func=container_manager.update)
2068
2069 # Handle the list command
2070 parser_list = subparsers.add_parser(
2071 "list",
2072 help=("List all Libertine containers."))
2073- parser_list.set_defaults(func=list)
2074+ parser_list.set_defaults(func=container_manager.list)
2075
2076 # Handle the list-apps command and its options
2077 parser_list_apps = subparsers.add_parser(
2078@@ -778,7 +413,7 @@
2079 '-j', '--json',
2080 action='store_true',
2081 help=("use JSON output format."))
2082- parser_list_apps.set_defaults(func=list_apps)
2083+ parser_list_apps.set_defaults(func=container_manager.list_apps)
2084
2085 # Handle the execute command and it's options
2086 parser_exec = subparsers.add_parser(
2087@@ -791,7 +426,7 @@
2088 parser_exec.add_argument(
2089 '-c', '--command',
2090 help=("The command to run in the specified container."))
2091- parser_exec.set_defaults(func=exec)
2092+ parser_exec.set_defaults(func=container_manager.exec)
2093
2094 # Handle the configure command and it's options
2095 parser_configure = subparsers.add_parser(
2096@@ -816,7 +451,7 @@
2097 metavar='Archive name',
2098 help=("Deletes an existing archive (PPA) in the specified Libertine container. "
2099 "Needs to be in the form of \"ppa:user/ppa-name\"."))
2100- parser_configure.set_defaults(func=configure)
2101+ parser_configure.set_defaults(func=container_manager.configure)
2102
2103 # Handle merging another ContainersConfig.json file into the main ContainersConfig.json file
2104 parser_merge = subparsers.add_parser(
2105@@ -825,13 +460,13 @@
2106 parser_merge.add_argument(
2107 '-f', '--file',
2108 required=True)
2109- parser_merge.set_defaults(func=merge)
2110+ parser_merge.set_defaults(func=container_manager.merge)
2111
2112 # Indiscriminately destroy containers, packages, and archives which are not fully installed
2113 parser_integrity = subparsers.add_parser(
2114 'fix-integrity',
2115 add_help=False)
2116- parser_integrity.set_defaults(func=fix_integrity)
2117+ parser_integrity.set_defaults(func=container_manager.fix_integrity)
2118
2119 # Set the default container in ContainersConfig
2120 parser_default = subparsers.add_parser(
2121@@ -844,7 +479,7 @@
2122 parser_default.add_argument(
2123 '-c', '--clear', action='store_true',
2124 help=("Clear the default container."))
2125- parser_default.set_defaults(func=set_default)
2126+ parser_default.set_defaults(func=container_manager.set_default)
2127
2128 # Actually parse the args
2129 args = parser.parse_args()
2130
2131=== modified file 'tools/libertine-launch'
2132--- tools/libertine-launch 2016-05-10 20:17:44 +0000
2133+++ tools/libertine-launch 2016-07-07 20:14:07 +0000
2134@@ -18,21 +18,24 @@
2135
2136 import argparse
2137 import os
2138+import random
2139+import string
2140 import libertine.utils
2141 import psutil
2142 import shlex
2143 import time
2144+
2145 from libertine import LibertineContainer
2146
2147
2148 def get_session_socket_path(session_socket_name):
2149- unique_id = os.environ['DISPLAY'].strip(':')
2150+ unique_id = ''.join(random.choice(string.ascii_lowercase + string.digits) for i in range(8))
2151
2152 if not os.path.exists(libertine.utils.get_libertine_runtime_dir()):
2153 os.makedirs(libertine.utils.get_libertine_runtime_dir())
2154
2155 session_socket_path = (
2156- os.path.join(libertine.utils.get_libertine_runtime_dir(), session_socket_name + unique_id))
2157+ os.path.join(libertine.utils.get_libertine_runtime_dir(), session_socket_name + '-' + unique_id))
2158
2159 return session_socket_path
2160
2161@@ -69,8 +72,8 @@
2162
2163 while not os.path.exists(session_socket_path):
2164 if retries >= 10:
2165- raise RuntimeError("Timeout waiting for Libertine Dbus session bridge socket")
2166-
2167+ raise RuntimeError("Timeout waiting for Libertine Dbus session bridge socket")
2168+
2169 print("Libertine Dbus session bridge socket is not ready. Waiting...")
2170 retries += 1
2171 time.sleep(.5)
2172@@ -84,9 +87,6 @@
2173 help='exec line')
2174 args = arg_parser.parse_args()
2175
2176- if not libertine.utils.container_exists(args.container_id):
2177- raise RuntimeError("Container ID %s does not exist." % args.container_id)
2178-
2179 # remove problematic environment variables
2180 for e in ['QT_QPA_PLATFORM', 'LD_LIBRARY_PATH', 'FAKECHROOT_BASE', 'FAKECHROOT_CMD_SUBST']:
2181 if e in os.environ:
2182@@ -104,7 +104,7 @@
2183 # should detect the maliit socket, but dont know if its around or not here.
2184 detect_session_bridge_socket(dbus_socket_path)
2185
2186- container = LibertineContainer(args.container_id)
2187+ container = LibertineContainer(args.container_id)
2188
2189 try:
2190 container.launch_application(args.app_exec_line)
2191
2192=== modified file 'tools/libertine-session-bridge'
2193--- tools/libertine-session-bridge 2016-05-19 20:00:22 +0000
2194+++ tools/libertine-session-bridge 2016-07-07 20:14:07 +0000
2195@@ -170,6 +170,7 @@
2196 except:
2197 container_session_sock.close()
2198 container_session_sock = None
2199+ os.remove(session_socket_path)
2200 raise
2201 else:
2202 host_session_socket_path_map.update({container_session_sock:host_session_path})

Subscribers

People subscribed via source and target branches