Merge lp:~townsend/libertine/refactor-lcm into lp:libertine

Proposed by Christopher Townsend
Status: Merged
Approved by: Larry Price
Approved revision: 258
Merged at revision: 257
Proposed branch: lp:~townsend/libertine/refactor-lcm
Merge into: lp:libertine
Diff against target: 1274 lines (+561/-586)
2 files modified
python/libertine/ContainersConfig.py (+299/-0)
tools/libertine-container-manager (+262/-586)
To merge this branch: bzr merge lp:~townsend/libertine/refactor-lcm
Reviewer Review Type Date Requested Status
Larry Price Approve
Libertine CI Bot continuous-integration Approve
Review via email: mp+298252@code.launchpad.net

Commit message

Add a new ContainersConfig Python class for managing all things ContainersConfig.json.
Add a new LibertineContainerManager Python class for handling the functions of l-c-m.

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

PASSED: Continuous integration, rev:255
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/12/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/94
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/62
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/62
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/62
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/62
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/62
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/62
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/78/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/97
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/82
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/82
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/82
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/75
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/75/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/75
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/75/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/75
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/75/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/75
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/75/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/75
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/75/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/75
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/75/artifact/output/*zip*/output.zip

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

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

See inline diff comments.

Also, were we in the habit of two newlines between functions? It's all good to me as long as we stay consistent.

lp:~townsend/libertine/refactor-lcm updated
256. By Christopher Townsend

Some more refactoring based on review comments.

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

PASSED: Continuous integration, rev:256
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/14/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/98
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/66
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/66
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/66
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/66
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/66
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/66
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/81/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/101
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/86
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/86
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/86
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/79
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/79/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/79
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/79/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/79
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/79/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/79
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/79/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/79
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/79/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/79
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/79/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Christopher Townsend (townsend) wrote :

Thanks!

As discussed on IRC, double space vs. single space is a pyflakes thing of functions outside a class vs. inside a class.

I did not merge _test_key_value_exists() and _test_array_object_key_value_exists() as you suggested because I think doing so may introduce more complexity in what I'm trying to do there:)

lp:~townsend/libertine/refactor-lcm updated
257. By Christopher Townsend

Handle some cases where containers may not exist.

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

PASSED: Continuous integration, rev:257
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/16/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/100
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/67
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/67
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/67
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/67
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/67
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/67
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/83/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/103
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/88
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/88
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/88
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/81
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/81/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/81
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/81/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/81
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/81/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/81
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/81/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/81
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/81/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/81
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/81/artifact/output/*zip*/output.zip

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

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

been poking around at some error cases and found a couple of places that need fixing (see inline)

review: Needs Fixing
lp:~townsend/libertine/refactor-lcm updated
258. By Christopher Townsend

Add missing sys module.
Fix typo.

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

PASSED: Continuous integration, rev:258
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/18/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/104
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/71
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/71
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/71
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/71
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/71
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/71
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/85/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/107
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/92
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/92
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/92
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/85
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/85/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/85
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/85/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/85
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/85/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/85
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/85/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/85
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/85/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/85
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/85/artifact/output/*zip*/output.zip

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

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

lgtm!

i also filed a bug for unrelated issues with accessing the log files of corrupt containers: https://bugs.launchpad.net/libertine/+bug/1596661

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'python/libertine/ContainersConfig.py'
2--- python/libertine/ContainersConfig.py 1970-01-01 00:00:00 +0000
3+++ python/libertine/ContainersConfig.py 2016-06-27 17:59:37 +0000
4@@ -0,0 +1,299 @@
5+# Copyright 2016 Canonical Ltd.
6+#
7+# This program is free software: you can redistribute it and/or modify it
8+# under the terms of the GNU General Public License version 3, as published
9+# by the Free Software Foundation.
10+#
11+# This program is distributed in the hope that it will be useful, but
12+# WITHOUT ANY WARRANTY; without even the implied warranties of
13+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14+# PURPOSE. See the GNU General Public License for more details.
15+#
16+# You should have received a copy of the GNU General Public License along
17+# with this program. If not, see <http://www.gnu.org/licenses/>.
18+
19+import fcntl
20+import json
21+import libertine.utils
22+import os
23+import sys
24+
25+
26+def read_container_config_file():
27+ container_list = {}
28+ container_config_file = libertine.utils.get_libertine_database_file_path()
29+
30+ if (os.path.exists(container_config_file) and
31+ os.path.getsize(container_config_file) != 0):
32+ with open(container_config_file, 'r') as fd:
33+ container_list = json.load(fd)
34+
35+ return container_list
36+
37+
38+def write_container_config_file(container_list):
39+ container_config_file = libertine.utils.get_libertine_database_file_path()
40+
41+ with open(container_config_file, 'w') as fd:
42+ fcntl.lockf(fd, fcntl.LOCK_EX)
43+ json.dump(container_list, fd, sort_keys=True, indent=4)
44+ fd.write('\n')
45+ fcntl.lockf(fd, fcntl.LOCK_UN)
46+
47+
48+class ContainersConfig(object):
49+
50+ def __init__(self):
51+ self.container_list = read_container_config_file()
52+
53+ if "defaultContainer" in self.container_list:
54+ self.default_container_id = self.container_list['defaultContainer']
55+ else:
56+ self.default_container_id = None
57+
58+ """
59+ Private helper methods
60+ """
61+ def _get_container_entry(self, container_id):
62+ if not self.container_list:
63+ return None
64+
65+ for container in self.container_list['containerList']:
66+ if container['id'] == container_id:
67+ return container
68+
69+ return None
70+
71+ def _get_value_by_key(self, container_id, key):
72+ container = self._get_container_entry(container_id)
73+
74+ if not container or key not in container:
75+ return None
76+ else:
77+ return container[key]
78+
79+ def _get_array_object_value_by_key(self, container_id, array_key, object_key, matcher, key):
80+ for item in self._get_value_by_key(container_id, array_key):
81+ if item[object_key] == matcher:
82+ return item[key]
83+
84+ def _set_value_by_key(self, container_id, key, value):
85+ container = self._get_container_entry(container_id)
86+
87+ if not container:
88+ return
89+
90+ if type(value) is str:
91+ container[key] = value
92+ elif type(value) is dict:
93+ if key not in container:
94+ container[key] = [value]
95+ else:
96+ container[key].append(value)
97+
98+ write_container_config_file(self.container_list)
99+
100+ def _set_array_object_value_by_key(self, container_id, array_key, object_key, matcher, key, value):
101+ container = self._get_container_entry(container_id)
102+
103+ if not container:
104+ return
105+
106+ for item in container[array_key]:
107+ if item[object_key] == matcher:
108+ item[key] = value
109+ write_container_config_file(self.container_list)
110+ return
111+
112+ def _delete_array_object_by_key_value(self, container_id, array_key, object_key, value):
113+ container = self._get_container_entry(container_id)
114+
115+ if not container:
116+ return
117+
118+ for item in container[array_key]:
119+ if item[object_key] == value:
120+ container[array_key].remove(item)
121+ write_container_config_file(self.container_list)
122+ return
123+
124+ def _test_key_value_exists(self, container_id, key, value=None):
125+ key_value = self._get_value_by_key(container_id, key)
126+
127+ if not key_value:
128+ return False
129+ elif key == 'id':
130+ return True
131+ elif key_value == value:
132+ return True
133+ else:
134+ return False
135+
136+ def _test_array_object_key_value_exists(self, container_id, array_key, object_key, value):
137+ array = self._get_value_by_key(container_id, array_key)
138+
139+ if not array:
140+ return False
141+
142+ for item in array:
143+ if item[object_key] == value:
144+ return True
145+
146+ return False
147+
148+ """
149+ Miscellaneous ContainersConfig.json operations
150+ """
151+ def _find_duplicate_container_entry(self, container_list, container_id):
152+ for container in container_list['containerList']:
153+ if container['id'] == container_id:
154+ return container
155+
156+ return None
157+
158+ def merge_container_config_files(self, filepath):
159+ merged_json = []
160+
161+ with open(filepath, 'r') as fd:
162+ merge_source = json.load(fd)
163+
164+ if "containerList" in self.container_list:
165+ # Finds any duplicate entries and assumes we want to update the main config
166+ # with entries from the merge source.
167+ for i, container in enumerate(self.container_list['containerList']):
168+ merge_container = self._find_duplicate_container_entry(merge_source, container['id'])
169+ if merge_container:
170+ self.container_list['containerList'][i] = merge_container
171+ merge_source['containerList'].remove(merge_container)
172+
173+ # Merges in any remaining non-duplicate entries.
174+ for container in merge_source['containerList']:
175+ self.container_list['containerList'].append(container)
176+
177+ else:
178+ self.container_list = merge_source
179+
180+ write_container_config_file(self.container_list)
181+
182+ def check_container_id(self, container_id):
183+ if container_id and not self.container_exists(container_id):
184+ print("Container id \'%s\' does not exist." % container_id, file=sys.stderr)
185+ sys.exit(1)
186+ elif not container_id:
187+ return self.get_default_container_id()
188+
189+ return container_id
190+
191+ def get_default_container_id(self):
192+ return self.default_container_id
193+
194+ def set_default_container_id(self, container_id, write_json=False):
195+ self.default_container_id = container_id
196+ self.container_list['defaultContainer'] = container_id
197+
198+ if write_json:
199+ write_container_config_file(self.container_list)
200+
201+ def clear_default_container_id(self, write_json=False):
202+ self.default_container_id = None
203+ self.container_list.pop('defaultContainer', None)
204+
205+ if write_json:
206+ write_container_config_file(self.container_list)
207+
208+ """
209+ Operations for the container itself.
210+ """
211+ def add_new_container(self, container_id, container_name, container_type, container_distro):
212+ container_obj = {'id': container_id, 'installStatus': 'new', 'type': container_type,
213+ 'distro': container_distro, 'name': container_name, 'installedApps': []}
214+
215+ if "defaultContainer" not in self.container_list:
216+ self.set_default_container_id(container_id)
217+
218+ if "containerList" not in self.container_list:
219+ self.container_list['containerList'] = [container_obj]
220+ else:
221+ self.container_list['containerList'].append(container_obj)
222+
223+ write_container_config_file(self.container_list)
224+
225+ def delete_container(self, container_id):
226+ if not self.container_list:
227+ print("Unable to delete container. No containers defined.")
228+ sys.exit(1)
229+
230+ container = self._get_container_entry(container_id)
231+
232+ self.container_list['containerList'].remove(container)
233+
234+ # Set a new defaultContainer if the current default is being deleted.
235+ if self.container_list['defaultContainer'] == container_id and self.container_list['containerList']:
236+ self.set_default_container_id(self.container_list['containerList'][0]['id'])
237+ # Remove the defaultContainer if there are no more containers left.
238+ elif not self.container_list['containerList']:
239+ self.clear_default_container_id()
240+
241+ write_container_config_file(self.container_list)
242+
243+ def update_container_install_status(self, container_id, new_status):
244+ self._set_value_by_key(container_id, 'installStatus', new_status)
245+
246+ def container_exists(self, container_id):
247+ return self._test_key_value_exists(container_id, 'id')
248+
249+ def update_container_multiarch_support(self, container_id, multiarch):
250+ if multiarch == 'enabled' and libertine.utils.get_host_architecture() == 'i386':
251+ multiarch = 'disabled'
252+
253+ self._set_value_by_key(container_id, 'multiarch', multiarch)
254+
255+ def get_container_multiarch_support(self, container_id):
256+ multiarch_support = self._get_value_by_key(container_id, 'multiarch')
257+
258+ if multiarch_support == None:
259+ return 'disabled'
260+ else:
261+ return multiarch_support
262+
263+ """
264+ Operations for archive (PPA) maintenance in a Libertine container.
265+ """
266+ def add_container_archive(self, container_id, archive_name):
267+ archive_obj = {'archiveName': archive_name, 'archiveStatus': 'new'}
268+ self._set_value_by_key(container_id, 'extraArchives', archive_obj)
269+
270+ def delete_container_archive(self, container_id, archive_name):
271+ self._delete_array_object_by_key_value(container_id, 'extraArchives',
272+ 'archiveName', archive_name)
273+
274+ def update_archive_install_status(self, container_id, archive_name, new_status):
275+ self._set_array_object_value_by_key(container_id, 'extraArchives', 'archiveName',
276+ archive_name, 'archiveStatus', new_status)
277+
278+ def archive_exists(self, container_id, archive_name):
279+ return self._test_array_object_key_value_exists(container_id, 'extraArchives', 'archiveName',
280+ archive_name)
281+
282+ """
283+ Operations for package maintenance in a Libertine container.
284+ """
285+ def add_new_package(self, container_id, package_name):
286+ package_obj = {'packageName': package_name, 'appStatus': 'new'}
287+ self._set_value_by_key(container_id, 'installedApps', package_obj)
288+
289+ def delete_package(self, container_id, package_name):
290+ self._delete_array_object_by_key_value(container_id, 'installedApps',
291+ 'packageName', package_name)
292+
293+ def update_package_install_status(self, container_id, package_name, new_status):
294+ self._set_array_object_value_by_key(container_id, 'installedApps', 'packageName',
295+ package_name, 'appStatus', new_status)
296+
297+ def get_package_install_status(self, container_id, package_name):
298+ return self._get_array_object_value_by_key(container_id, 'installedApps', 'packageName',
299+ package_name, 'appStatus')
300+
301+ def package_exists(self, container_id, package_name):
302+ return self._test_array_object_key_value_exists(container_id, 'installedApps', 'packageName',
303+ package_name)
304
305=== modified file 'tools/libertine-container-manager'
306--- tools/libertine-container-manager 2016-06-20 15:15:38 +0000
307+++ tools/libertine-container-manager 2016-06-27 17:59:37 +0000
308@@ -17,8 +17,6 @@
309 # along with this program. If not, see <http://www.gnu.org/licenses/>.
310
311 import argparse
312-import fcntl
313-import json
314 import libertine.utils
315 import lsb_release
316 import getpass
317@@ -27,75 +25,9 @@
318 import sys
319
320 from apt.debfile import DebPackage
321-from distro_info import UbuntuDistroInfo, DistroDataOutdated
322+from distro_info import UbuntuDistroInfo
323 from libertine import LibertineContainer
324-
325-
326-def find_duplicate_container_entry(container_list, container_id):
327- for container in container_list['containerList']:
328- if container['id'] == container_id:
329- return container
330-
331- return None
332-
333-
334-def merge_container_config_files(filepath):
335- merged_json = []
336- main_config = read_container_config_file()
337-
338- with open(filepath, 'r') as fd:
339- merge_source = json.load(fd)
340-
341- if "containerList" in main_config:
342- # Finds any duplicate entries and assumes we want to update the main config
343- # with entries from the merge source.
344- for i, container in enumerate(main_config['containerList']):
345- merge_container = find_duplicate_container_entry(merge_source, container['id'])
346- if merge_container:
347- main_config['containerList'][i] = merge_container
348- merge_source['containerList'].remove(merge_container)
349-
350- # Merges in any remaining non-duplicate entries.
351- for container in merge_source['containerList']:
352- main_config['containerList'].append(container)
353-
354- else:
355- main_config = merge_source
356-
357- write_container_config_file(main_config)
358-
359-
360-def read_container_config_file():
361- container_list = {}
362- container_config_file = libertine.utils.get_libertine_database_file_path()
363-
364- if (os.path.exists(container_config_file) and
365- os.path.getsize(container_config_file) != 0):
366- with open(container_config_file, 'r') as fd:
367- container_list = json.load(fd)
368-
369- return container_list
370-
371-
372-def write_container_config_file(container_list):
373- container_config_file = libertine.utils.get_libertine_database_file_path()
374-
375- with open(container_config_file, 'w') as fd:
376- fcntl.lockf(fd, fcntl.LOCK_EX)
377- json.dump(container_list, fd, sort_keys=True, indent=4)
378- fd.write('\n')
379- fcntl.lockf(fd, fcntl.LOCK_UN)
380-
381-
382-def get_default_container_id():
383- default_container_id = None
384-
385- container_list = read_container_config_file()
386-
387- if "defaultContainer" in container_list:
388- default_container_id = container_list['defaultContainer']
389-
390- return default_container_id
391+from libertine.ContainersConfig import ContainersConfig
392
393
394 def select_container_type():
395@@ -142,512 +74,254 @@
396 return None
397
398
399-def update_container_install_status(container_id, new_status):
400- container_list = read_container_config_file()
401-
402- for container in container_list['containerList']:
403- if container['id'] == container_id:
404- container['installStatus'] = new_status
405-
406- write_container_config_file(container_list)
407- break
408-
409-
410-def update_container_multiarch_support(container_id, multiarch):
411- container_list = read_container_config_file()
412-
413- if multiarch == 'enabled' and libertine.utils.get_host_architecture() == 'i386':
414- multiarch = 'disabled'
415-
416- for container in container_list['containerList']:
417- if container['id'] == container_id:
418- container['multiarch'] = multiarch
419-
420- write_container_config_file(container_list)
421- break
422-
423-
424-def get_container_multiarch_support(container_id):
425- container_list = read_container_config_file()
426-
427- for container in container_list['containerList']:
428- if container['id'] == container_id:
429- if not 'multiarch' in container:
430- return 'disabled'
431- else:
432- return container['multiarch']
433-
434-
435-def update_archive_install_status(container_id, archive_name, new_status):
436- container_list = read_container_config_file()
437-
438- for container in container_list['containerList']:
439- if container['id'] == container_id:
440- for archive in container['extraArchives']:
441- if archive['archiveName'] == archive_name:
442- archive['archiveStatus'] = new_status
443- write_container_config_file(container_list)
444- return
445-
446-
447-def add_container_archive(container_id, archive_name):
448- container_list = read_container_config_file()
449-
450- for container in container_list['containerList']:
451- if container['id'] == container_id:
452- archive_obj = {'archiveName': archive_name, 'archiveStatus': 'new'}
453-
454- if 'extraArchives' not in container:
455- container['extraArchives'] = [archive_obj]
456- else:
457- container['extraArchives'].append(archive_obj)
458-
459- write_container_config_file(container_list)
460- break
461-
462-
463-def delete_container_archive(container_id, archive_name):
464- container_list = read_container_config_file()
465-
466- for container in container_list['containerList']:
467- if container['id'] == container_id:
468- for archive in container['extraArchives']:
469- if archive['archiveName'] == archive_name:
470- container['extraArchives'].remove(archive)
471- write_container_config_file(container_list)
472- return
473-
474- print("%s does not exist." % archive_name)
475- sys.exit(1)
476-
477-
478-def archive_exists(container_id, archive_name):
479- container_list = read_container_config_file()
480-
481- for container in container_list['containerList']:
482- if container['id'] == container_id:
483- if 'extraArchives' not in container:
484- return False
485- else:
486- for archive in container['extraArchives']:
487- if archive['archiveName'] == archive_name:
488- return True
489-
490- return False
491-
492-
493-def add_new_container(id, name, type, distro):
494- if not os.path.exists(libertine.utils.get_libertine_database_dir_path()):
495- os.makedirs(libertine.utils.get_libertine_database_dir_path())
496-
497- container_list = read_container_config_file()
498-
499- container_obj = {'id': id, 'installStatus': 'new', 'type': type,
500- 'distro': distro, 'name': name, 'installedApps': []}
501-
502- if "defaultContainer" not in container_list:
503- container_list['defaultContainer'] = id
504-
505- if "containerList" not in container_list:
506- container_list['containerList'] = [container_obj]
507- else:
508- container_list['containerList'].append(container_obj)
509-
510- write_container_config_file(container_list)
511-
512-
513-def delete_container(container_id):
514- container_list = read_container_config_file()
515-
516- if not container_list:
517- print("Unable to delete container. No containers defined.")
518- sys.exit(1)
519-
520- for container in container_list['containerList']:
521- if container['id'] == container_id:
522- container_list['containerList'].remove(container)
523-
524- # Set a new defaultContainer if the current default is being deleted.
525- if container_list['defaultContainer'] == container_id and container_list['containerList']:
526- container_list['defaultContainer'] = container_list['containerList'][0]['id']
527- # Remove the defaultContainer if there are no more containers left.
528- elif not container_list['containerList']:
529- del container_list['defaultContainer']
530-
531- write_container_config_file(container_list)
532- break
533-
534-
535-def package_exists(container_id, package_name):
536- container_list = read_container_config_file()
537-
538- if not container_list:
539- return False
540-
541- for container in container_list['containerList']:
542- if container['id'] == container_id:
543- for package in container['installedApps']:
544- if package['packageName'] == package_name:
545- return True
546-
547- return False
548-
549-
550-def update_package_install_status(container_id, package_name, new_status):
551- container_list = read_container_config_file()
552-
553- for container in container_list['containerList']:
554- if container['id'] == container_id:
555- for package in container['installedApps']:
556- if package['packageName'] == package_name:
557- package['appStatus'] = new_status
558- write_container_config_file(container_list)
559- return
560-
561-
562-def get_package_install_status(container_id, package_name):
563- container_list = read_container_config_file()
564-
565- for container in container_list['containerList']:
566- if container['id'] == container_id:
567- for package in container['installedApps']:
568- if package['packageName'] == package_name:
569- return package['appStatus']
570-
571-
572-def add_new_package(container_id, package_name):
573- container_list = read_container_config_file()
574-
575- if not container_list:
576- print("No containers defined. Please create a new container before installing a package.")
577- sys.exit(1)
578-
579- for container in container_list['containerList']:
580- if container['id'] == container_id:
581- package_obj = {'packageName': package_name, 'appStatus': 'new'}
582-
583- if not container['installedApps']:
584- container['installedApps'] = [package_obj]
585- else:
586- container['installedApps'].append(package_obj)
587-
588- write_container_config_file(container_list)
589- break
590-
591-
592-def delete_package(container_id, package_name):
593- container_list = read_container_config_file()
594-
595- if not container_list:
596- print("No containers defined. Please create a new container before installing a package.")
597- sys.exit(1)
598-
599- for container in container_list['containerList']:
600- if container['id'] == container_id:
601- for package in container['installedApps']:
602- if package['packageName'] == package_name:
603- container['installedApps'].remove(package)
604- write_container_config_file(container_list)
605- return
606-
607- print("Package \'%s\' does not exist." % package_name)
608- sys.exit(1)
609-
610-
611-def create(args):
612- password = None
613-
614- if args.distro and not is_distro_valid(args.distro, args.force):
615- print("Invalid distro %s" % args.distro, file=sys.stderr)
616- sys.exit(1)
617-
618- if args.id and libertine.utils.container_exists(args.id):
619- print("Container id \'%s\' is already used." % args.id, file=sys.stderr)
620- sys.exit(1)
621- elif not args.id:
622- args.id = get_unique_container_id(distro)
623-
624- if not args.type:
625- container_type = select_container_type()
626- else:
627- container_type = args.type
628-
629- if not args.distro:
630- args.distro = get_host_distro_release()
631- elif container_type == "chroot":
632- host_distro = get_host_distro_release()
633-
634- if args.distro != host_distro:
635- print("The container distribution needs to match the host ditribution for chroot"
636- " based containers. Please either use \'%s\' or omit the -d/--distro option."
637- % host_distro)
638- sys.exit(1)
639-
640- if not args.name:
641- args.name = "Ubuntu \'" + get_distro_codename(args.distro) + "\'"
642-
643- if container_type == "lxc":
644- if args.password:
645- password = args.password
646- elif sys.stdin.isatty():
647- print("Your user password is required for creating a Libertine container.")
648- password = getpass.getpass()
649- else:
650- password = sys.stdin.readline().rstrip()
651-
652- add_new_container(args.id, args.name, container_type, args.distro)
653-
654- multiarch = 'disabled'
655- if args.multiarch:
656- multiarch = 'enabled'
657- update_container_multiarch_support(args.id, multiarch)
658-
659- container = LibertineContainer(args.id)
660- update_container_install_status(args.id, "installing")
661- if not container.create_libertine_container(password, args.multiarch, args.verbosity):
662- delete_container(args.id)
663- sys.exit(1)
664- update_container_install_status(args.id, "ready")
665-
666- libertine.utils.refresh_libertine_scope()
667-
668-
669-def destroy_container_by_id(id):
670- container = LibertineContainer(id)
671- update_container_install_status(id, "removing")
672- container.destroy_libertine_container()
673- update_container_install_status(id, "removed")
674- delete_container(id)
675-
676-
677-def destroy(args):
678- if args.id and not libertine.utils.container_exists(args.id):
679- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
680- sys.exit(1)
681- elif not args.id:
682- args.id = get_default_container_id()
683-
684- destroy_container_by_id(args.id)
685-
686- libertine.utils.refresh_libertine_scope()
687-
688-
689-def install_package(args):
690- if args.id and not libertine.utils.container_exists(args.id):
691- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
692- sys.exit(1)
693- elif not args.id:
694- args.id = get_default_container_id()
695-
696- is_debian_package = args.package.endswith('.deb')
697-
698- if is_debian_package:
699- if os.path.exists(args.package):
700- package = DebPackage(args.package).pkgname
701- else:
702- print("%s does not exist." % args.package)
703- sys.exit(1)
704- else:
705- package = args.package
706-
707- if package_exists(args.id, package):
708- if not is_debian_package:
709- print("Package \'%s\' is already installed." % package)
710- sys.exit(1)
711- else:
712- add_new_package(args.id, package)
713-
714- container = LibertineContainer(args.id)
715-
716- update_package_install_status(args.id, package, "installing")
717- if not container.install_package(args.package, args.verbosity, args.readline):
718- delete_package(args.id, package)
719- sys.exit(1)
720-
721- update_package_install_status(args.id, package, "installed")
722-
723- libertine.utils.refresh_libertine_scope()
724-
725-
726-def remove_package_by_name(container_id, package_name, verbosity=1, readline=False):
727- fallback_status = get_package_install_status(container_id, package_name)
728- update_package_install_status(container_id, package_name, "removing")
729-
730- container = LibertineContainer(container_id)
731- if not container.remove_package(package_name, verbosity, readline):
732- update_package_install_status(container_id, package_name, fallback_status)
733- return False
734-
735- update_package_install_status(container_id, package_name, "removed")
736- delete_package(container_id, package_name)
737-
738- return True
739-
740-
741-def remove_package(args):
742- if args.id and not libertine.utils.container_exists(args.id):
743- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
744- sys.exit(1)
745- elif not args.id:
746- args.id = get_default_container_id()
747-
748- if get_package_install_status(args.id, args.package) != 'installed':
749- print("Package \'%s\' is not installed." % args.package)
750- sys.exit(1)
751-
752- if not remove_package_by_name(args.id, args.package, args.verbosity, args.readline):
753- sys.exit(1)
754-
755- libertine.utils.refresh_libertine_scope()
756-
757-
758-def search_cache(args):
759- if args.id and not libertine.utils.container_exists(args.id):
760- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
761- sys.exit(1)
762- elif not args.id:
763- args.id = get_default_container_id()
764-
765- container = LibertineContainer(args.id)
766- if container.search_package_cache(args.search_string) is not 0:
767- sys.exit(1)
768-
769-
770-def update(args):
771- if args.id and not libertine.utils.container_exists(args.id):
772- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
773- sys.exit(1)
774- elif not args.id:
775- args.id = get_default_container_id()
776-
777- container = LibertineContainer(args.id)
778-
779- update_container_install_status(args.id, "updating")
780- if container.update_libertine_container(args.verbosity) is not 0:
781- update_container_install_status(args.id, "ready")
782- sys.exit(1)
783-
784- update_container_install_status(args.id, "ready")
785-
786-
787-def list(args):
788- containers = libertine.utils.Libertine.list_containers()
789- for container in containers:
790- print("%s" % container)
791-
792-
793-def list_apps(args):
794- if args.id and not libertine.utils.container_exists(args.id):
795- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
796- sys.exit(1)
797- elif not args.id:
798- args.id = get_default_container_id()
799-
800- container = LibertineContainer(args.id)
801- print(container.list_app_launchers(use_json=args.json))
802-
803-
804-def exec(args):
805- if args.id and not libertine.utils.container_exists(args.id):
806- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
807- sys.exit(1)
808- elif not args.id:
809- args.id = get_default_container_id()
810-
811- container = LibertineContainer(args.id)
812-
813- if not container.exec_command(args.command):
814- sys.exit(1)
815-
816-
817-def delete_archive_by_name(container_id, archive_name):
818- update_archive_install_status(container_id, archive_name, 'removing')
819- if LibertineContainer(container_id).configure_command('delete-archive', archive_name) is not 0:
820- return False
821- delete_container_archive(container_id, archive_name)
822- return True
823-
824-
825-def configure(args):
826- if args.id and not libertine.utils.container_exists(args.id):
827- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
828- sys.exit(1)
829- elif not args.id:
830- args.id = get_default_container_id()
831-
832- container = LibertineContainer(args.id)
833-
834- if args.multiarch and libertine.utils.get_host_architecture() == 'amd64':
835+class LibertineContainerManager(object):
836+
837+ def __init__(self):
838+ self.containers_config = ContainersConfig()
839+
840+ def create(self, args):
841+ password = None
842+
843+ if args.distro and not is_distro_valid(args.distro, args.force):
844+ print("Invalid distro %s" % args.distro, file=sys.stderr)
845+ sys.exit(1)
846+
847+ if args.id and self.containers_config.container_exists(args.id):
848+ print("Container id \'%s\' is already used." % args.id, file=sys.stderr)
849+ sys.exit(1)
850+ elif not args.id:
851+ args.id = get_unique_container_id(distro)
852+
853+ if not args.type:
854+ container_type = select_container_type()
855+ else:
856+ container_type = args.type
857+
858+ if not args.distro:
859+ args.distro = get_host_distro_release()
860+ elif container_type == "chroot":
861+ host_distro = get_host_distro_release()
862+
863+ if args.distro != host_distro:
864+ print("The container distribution needs to match the host ditribution for chroot"
865+ " based containers. Please either use \'%s\' or omit the -d/--distro option."
866+ % host_distro)
867+ sys.exit(1)
868+
869+ if not args.name:
870+ args.name = "Ubuntu \'" + get_distro_codename(args.distro) + "\'"
871+
872+ if container_type == "lxc":
873+ if args.password:
874+ password = args.password
875+ elif sys.stdin.isatty():
876+ print("Your user password is required for creating a Libertine container.")
877+ password = getpass.getpass()
878+ else:
879+ password = sys.stdin.readline().rstrip()
880+
881+ self.containers_config.add_new_container(args.id, args.name, container_type, args.distro)
882+
883 multiarch = 'disabled'
884 if args.multiarch == 'enable':
885 multiarch = 'enabled'
886-
887- current_multiarch = get_container_multiarch_support(args.id)
888- if current_multiarch == multiarch:
889- print("i386 multiarch support is already %s" % multiarch)
890- sys.exit(1)
891-
892- if container.configure_command('multiarch', args.multiarch) is not 0:
893- sys.exit(1)
894-
895- update_container_multiarch_support(args.id, multiarch)
896-
897- elif args.add_archive:
898- if archive_exists(args.id, args.add_archive):
899- print("%s already added in container." % args.add_archive)
900- sys.exit(1)
901-
902- add_container_archive(args.id, args.add_archive)
903- update_archive_install_status(args.id, args.add_archive, 'installing')
904- if container.configure_command('add-archive', args.add_archive) is not 0:
905- delete_container_archive(args.id, args.add_archive)
906- sys.exit(1)
907-
908- update_archive_install_status(args.id, args.add_archive, 'installed')
909-
910- elif args.delete_archive:
911- if not archive_exists(args.id, args.delete_archive):
912- print("%s is not added in container." % args.delete_archive)
913- sys.exit(1)
914-
915- if not delete_archive_by_name(args.id, args.delete_archive):
916- sys.exit(1)
917-
918-
919-def merge(args):
920- merge_container_config_files(args.file)
921-
922-
923-def fix_integrity(args):
924- for container in read_container_config_file()['containerList']:
925- if container['installStatus'] != 'ready':
926- destroy_container_by_id(container['id'])
927- continue
928- LibertineContainer(container['id']).exec_command('dpkg --configure -a')
929-
930- for package in container['installedApps']:
931- if package['appStatus'] != 'installed':
932- remove_package_by_name(container['id'], package['packageName'])
933- if 'extraArchives' in container:
934- for archive in container['extraArchives']:
935- if archive['archiveStatus'] != 'installed':
936- delete_archive_by_name(container['id'], archive['archiveName'])
937-
938-
939-def set_default(args):
940- if args.clear:
941- container_list = read_container_config_file()
942- container_list.pop('defaultContainer', None)
943- write_container_config_file(container_list)
944- sys.exit(0)
945-
946- if not libertine.utils.container_exists(args.id):
947- print("Container id \'%s\' does not exist." % args.id, file=sys.stderr)
948- sys.exit(1)
949-
950- container_list = read_container_config_file()
951- container_list['defaultContainer'] = args.id
952- write_container_config_file(container_list)
953+ self.containers_config.update_container_multiarch_support(args.id, multiarch)
954+
955+ container = LibertineContainer(args.id)
956+ self.containers_config.update_container_install_status(args.id, "installing")
957+ if not container.create_libertine_container(password, args.multiarch, args.verbosity):
958+ self.containers_config.delete_container(args.id)
959+ sys.exit(1)
960+ self.containers_config.update_container_install_status(args.id, "ready")
961+
962+ libertine.utils.refresh_libertine_scope()
963+
964+ def destroy_container_by_id(self, id):
965+ container = LibertineContainer(id)
966+
967+ self.containers_config.update_container_install_status(id, "removing")
968+ container.destroy_libertine_container()
969+ self.containers_config.update_container_install_status(id, "removed")
970+ self.containers_config.delete_container(id)
971+
972+ def destroy(self, args):
973+ args.id = self.containers_config.check_container_id(args.id)
974+
975+ self.destroy_container_by_id(args.id)
976+
977+ libertine.utils.refresh_libertine_scope()
978+
979+ def install_package(self, args):
980+ container_id = self.containers_config.check_container_id(args.id)
981+
982+ is_debian_package = args.package.endswith('.deb')
983+
984+ if is_debian_package:
985+ if os.path.exists(args.package):
986+ package = DebPackage(args.package).pkgname
987+ else:
988+ print("%s does not exist." % args.package)
989+ sys.exit(1)
990+ else:
991+ package = args.package
992+
993+ if self.containers_config.package_exists(container_id, package):
994+ if not is_debian_package:
995+ print("Package \'%s\' is already installed." % package)
996+ sys.exit(1)
997+ else:
998+ self.containers_config.add_new_package(container_id, package)
999+
1000+ container = LibertineContainer(container_id)
1001+
1002+ self.containers_config.update_package_install_status(container_id, package, "installing")
1003+ if not container.install_package(args.package, args.verbosity, args.readline):
1004+ self.containers_config.delete_package(container_id, package)
1005+ sys.exit(1)
1006+
1007+ self.containers_config.update_package_install_status(container_id, package, "installed")
1008+
1009+ libertine.utils.refresh_libertine_scope()
1010+
1011+ def remove_package_by_name(self, container_id, package_name, verbosity=1, readline=False):
1012+ fallback_status = self.containers_config.get_package_install_status(container_id, package_name)
1013+ self.containers_config.update_package_install_status(container_id, package_name, "removing")
1014+
1015+ container = LibertineContainer(container_id)
1016+ if not container.remove_package(package_name, verbosity, readline):
1017+ self.containers_config.update_package_install_status(container_id, package_name, fallback_status)
1018+ return False
1019+
1020+ self.containers_config.update_package_install_status(container_id, package_name, "removed")
1021+ self.containers_config.delete_package(container_id, package_name)
1022+
1023+ return True
1024+
1025+ def remove_package(self, args):
1026+ container_id = self.containers_config.check_container_id(args.id)
1027+
1028+ if self.containers_config.get_package_install_status(container_id, args.package) != 'installed':
1029+ print("Package \'%s\' is not installed." % args.package)
1030+ sys.exit(1)
1031+
1032+ if not self.remove_package_by_name(container_id, args.package, args.verbosity, args.readline):
1033+ sys.exit(1)
1034+
1035+ libertine.utils.refresh_libertine_scope()
1036+
1037+ def search_cache(self, args):
1038+ container_id = self.containers_config.check_container_id(args.id)
1039+
1040+ container = LibertineContainer(container_id)
1041+ if container.search_package_cache(args.search_string) is not 0:
1042+ sys.exit(1)
1043+
1044+ def update(self, args):
1045+ container_id = self.containers_config.check_container_id(args.id)
1046+
1047+ container = LibertineContainer(container_id)
1048+
1049+ self.containers_config.update_container_install_status(container_id, "updating")
1050+ if container.update_libertine_container(args.verbosity) is not 0:
1051+ self.containers_config.update_container_install_status(container_id, "ready")
1052+ sys.exit(1)
1053+
1054+ self.containers_config.update_container_install_status(container_id, "ready")
1055+
1056+ def list(self, args):
1057+ containers = libertine.utils.Libertine.list_containers()
1058+ for container in containers:
1059+ print("%s" % container)
1060+
1061+ def list_apps(self, args):
1062+ container_id = self.containers_config.check_container_id(args.id)
1063+
1064+ container = LibertineContainer(container_id)
1065+ print(container.list_app_launchers(use_json=args.json))
1066+
1067+ def exec(self, args):
1068+ container_id = self.containers_config.check_container_id(args.id)
1069+
1070+ container = LibertineContainer(container_id)
1071+
1072+ if not container.exec_command(args.command):
1073+ sys.exit(1)
1074+
1075+ def delete_archive_by_name(self, container_id, archive_name):
1076+ self.containers_config.update_archive_install_status(container_id, archive_name, 'removing')
1077+ if LibertineContainer(container_id).configure_command('delete-archive', archive_name) is not 0:
1078+ return False
1079+ self.containers_config.delete_container_archive(container_id, archive_name)
1080+ return True
1081+
1082+ def configure(self, args):
1083+ container_id = self.containers_config.check_container_id(args.id)
1084+
1085+ container = LibertineContainer(container_id)
1086+
1087+ if args.multiarch and libertine.utils.get_host_architecture() == 'amd64':
1088+ multiarch = 'disabled'
1089+ if args.multiarch == 'enable':
1090+ multiarch = 'enabled'
1091+
1092+ current_multiarch = self.containers_config.get_container_multiarch_support(container_id)
1093+ if current_multiarch == multiarch:
1094+ print("i386 multiarch support is already %s" % multiarch)
1095+ sys.exit(1)
1096+
1097+ if container.configure_command('multiarch', args.multiarch) is not 0:
1098+ sys.exit(1)
1099+
1100+ self.containers_config.update_container_multiarch_support(container_id, multiarch)
1101+
1102+ elif args.add_archive:
1103+ if self.containers_config.archive_exists(container_id, args.add_archive):
1104+ print("%s already added in container." % args.add_archive)
1105+ sys.exit(1)
1106+
1107+ self.containers_config.add_container_archive(container_id, args.add_archive)
1108+ self.containers_config.update_archive_install_status(container_id, args.add_archive, 'installing')
1109+ if container.configure_command('add-archive', args.add_archive) is not 0:
1110+ self.containers_config.delete_container_archive(container_id, args.add_archive)
1111+ sys.exit(1)
1112+
1113+ self.containers_config.update_archive_install_status(container_id, args.add_archive, 'installed')
1114+
1115+ elif args.delete_archive:
1116+ if not self.containers_config.archive_exists(container_id, args.delete_archive):
1117+ print("%s is not added in container." % args.delete_archive)
1118+ sys.exit(1)
1119+
1120+ if not self.delete_archive_by_name(container_id, args.delete_archive):
1121+ sys.exit(1)
1122+
1123+ def merge(self, args):
1124+ self.containers_config.merge_container_config_files(args.file)
1125+
1126+ def fix_integrity(self, args):
1127+ for container in self.containers_config.container_list['containerList']:
1128+ if container['installStatus'] != 'ready':
1129+ self.destroy_container_by_id(container['id'])
1130+ continue
1131+ LibertineContainer(container['id']).exec_command('dpkg --configure -a')
1132+
1133+ for package in container['installedApps']:
1134+ if package['appStatus'] != 'installed':
1135+ self.remove_package_by_name(container['id'], package['packageName'])
1136+
1137+ if 'extraArchives' in container:
1138+ for archive in container['extraArchives']:
1139+ if archive['archiveStatus'] != 'installed':
1140+ self.delete_archive_by_name(container['id'], archive['archiveName'])
1141+
1142+ def set_default(self, args):
1143+ if args.clear:
1144+ self.containers_config.clear_default_container_id(True)
1145+ sys.exit(0)
1146+
1147+ container_id = self.containers_config.check_container_id(args.id)
1148+
1149+ self.containers_config.set_default_container_id(container_id, True)
1150
1151
1152 if __name__ == '__main__':
1153@@ -657,6 +331,8 @@
1154 print("Please do not run %s using sudo" % parser.prog)
1155 sys.exit(1)
1156
1157+ container_manager = LibertineContainerManager()
1158+
1159 parser.add_argument('-q', '--quiet',
1160 action='store_const', dest='verbosity', const=0,
1161 help=('do not print status updates on stdout'))
1162@@ -696,7 +372,7 @@
1163 '--password',
1164 help=("Pass in the user's password when creating an LXC container. This "
1165 "is intended for testing only and is very insecure."))
1166- parser_create.set_defaults(func=create)
1167+ parser_create.set_defaults(func=container_manager.create)
1168
1169 # Handle the destroy command and its options
1170 parser_destroy = subparsers.add_parser(
1171@@ -705,7 +381,7 @@
1172 parser_destroy.add_argument(
1173 '-i', '--id',
1174 help=("Container identifier. Default container is used if omitted."))
1175- parser_destroy.set_defaults(func=destroy)
1176+ parser_destroy.set_defaults(func=container_manager.destroy)
1177
1178 # Handle the install-package command and its options
1179 parser_install = subparsers.add_parser(
1180@@ -721,7 +397,7 @@
1181 parser_install.add_argument(
1182 '-r', '--readline', action='store_true',
1183 help=("Readline mode. Use text-based frontend during debconf interactions."))
1184- parser_install.set_defaults(func=install_package)
1185+ parser_install.set_defaults(func=container_manager.install_package)
1186
1187 # Handle the remove-package command and its options
1188 parser_remove = subparsers.add_parser(
1189@@ -737,7 +413,7 @@
1190 parser_remove.add_argument(
1191 '-r', '--readline', action='store_true',
1192 help=("Readline mode. Use text-based frontend during debconf interactions."))
1193- parser_remove.set_defaults(func=remove_package)
1194+ parser_remove.set_defaults(func=container_manager.remove_package)
1195
1196 # Handle the search-cache command and its options
1197 parser_search = subparsers.add_parser(
1198@@ -750,7 +426,7 @@
1199 parser_search.add_argument(
1200 '-i', '--id',
1201 help=("Container identifier. Default container is used if omitted."))
1202- parser_search.set_defaults(func=search_cache)
1203+ parser_search.set_defaults(func=container_manager.search_cache)
1204
1205 # Handle the update command and its options
1206 parser_update = subparsers.add_parser(
1207@@ -759,13 +435,13 @@
1208 parser_update.add_argument(
1209 '-i', '--id',
1210 help=("Container identifier. Default container is used if omitted."))
1211- parser_update.set_defaults(func=update)
1212+ parser_update.set_defaults(func=container_manager.update)
1213
1214 # Handle the list command
1215 parser_list = subparsers.add_parser(
1216 "list",
1217 help=("List all Libertine containers."))
1218- parser_list.set_defaults(func=list)
1219+ parser_list.set_defaults(func=container_manager.list)
1220
1221 # Handle the list-apps command and its options
1222 parser_list_apps = subparsers.add_parser(
1223@@ -778,7 +454,7 @@
1224 '-j', '--json',
1225 action='store_true',
1226 help=("use JSON output format."))
1227- parser_list_apps.set_defaults(func=list_apps)
1228+ parser_list_apps.set_defaults(func=container_manager.list_apps)
1229
1230 # Handle the execute command and it's options
1231 parser_exec = subparsers.add_parser(
1232@@ -791,7 +467,7 @@
1233 parser_exec.add_argument(
1234 '-c', '--command',
1235 help=("The command to run in the specified container."))
1236- parser_exec.set_defaults(func=exec)
1237+ parser_exec.set_defaults(func=container_manager.exec)
1238
1239 # Handle the configure command and it's options
1240 parser_configure = subparsers.add_parser(
1241@@ -816,7 +492,7 @@
1242 metavar='Archive name',
1243 help=("Deletes an existing archive (PPA) in the specified Libertine container. "
1244 "Needs to be in the form of \"ppa:user/ppa-name\"."))
1245- parser_configure.set_defaults(func=configure)
1246+ parser_configure.set_defaults(func=container_manager.configure)
1247
1248 # Handle merging another ContainersConfig.json file into the main ContainersConfig.json file
1249 parser_merge = subparsers.add_parser(
1250@@ -825,13 +501,13 @@
1251 parser_merge.add_argument(
1252 '-f', '--file',
1253 required=True)
1254- parser_merge.set_defaults(func=merge)
1255+ parser_merge.set_defaults(func=container_manager.merge)
1256
1257 # Indiscriminately destroy containers, packages, and archives which are not fully installed
1258 parser_integrity = subparsers.add_parser(
1259 'fix-integrity',
1260 add_help=False)
1261- parser_integrity.set_defaults(func=fix_integrity)
1262+ parser_integrity.set_defaults(func=container_manager.fix_integrity)
1263
1264 # Set the default container in ContainersConfig
1265 parser_default = subparsers.add_parser(
1266@@ -844,7 +520,7 @@
1267 parser_default.add_argument(
1268 '-c', '--clear', action='store_true',
1269 help=("Clear the default container."))
1270- parser_default.set_defaults(func=set_default)
1271+ parser_default.set_defaults(func=container_manager.set_default)
1272
1273 # Actually parse the args
1274 args = parser.parse_args()

Subscribers

People subscribed via source and target branches