Merge lp:~larryprice/libertine/libertined-input into lp:libertine

Proposed by Larry Price
Status: Needs review
Proposed branch: lp:~larryprice/libertine/libertined-input
Merge into: lp:libertine
Prerequisite: lp:~larryprice/libertine/libertined-output
Diff against target: 595 lines (+117/-75)
14 files modified
python/libertine/ChrootContainer.py (+8/-5)
python/libertine/Libertine.py (+41/-12)
python/libertine/LxcContainer.py (+8/-10)
python/libertine/LxdContainer.py (+4/-3)
python/libertine/service/download.py (+5/-1)
python/libertine/service/operations_monitor.py (+2/-2)
python/libertine/service/task_dispatcher_base.py (+1/-1)
python/libertine/service/tasks/base_task.py (+12/-5)
python/libertine/service/tasks/create_task.py (+1/-2)
python/libertine/service/tasks/install_task.py (+1/-1)
python/libertine/service/tasks/remove_task.py (+1/-1)
python/libertine/service/tasks/update_task.py (+1/-1)
tests/unit/service/test_operations_monitor.py (+12/-11)
tools/libertine-container-manager (+20/-20)
To merge this branch: bzr merge lp:~larryprice/libertine/libertined-input
Reviewer Review Type Date Requested Status
Libertine CI Bot continuous-integration Needs Fixing
Libertine Developers Pending
Review via email: mp+321764@code.launchpad.net

Commit message

Allow sending input data to libertined during certain container operations.

Description of the change

Allow sending input data to libertined during certain container operations.

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

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

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

review: Approve (continuous-integration)
465. By Larry Price

merge

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

chmod

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

Unmerged revisions

466. By Larry Price

chmod

465. By Larry Price

merge

464. By Larry Price

fixing up merge and tests

463. By Larry Price

merge

462. By Larry Price

create with password separate

461. By Larry Price

chroot and lxc

460. By Larry Price

INPUT! At least for lxd on install/remove...

459. By Larry Price

minor changes

458. By Larry Price

well these are good ideas but don't work for lxc

457. By Larry Price

at some point everything broke?

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'python/libertine/ChrootContainer.py'
2--- python/libertine/ChrootContainer.py 2017-03-23 19:23:20 +0000
3+++ python/libertine/ChrootContainer.py 2017-04-07 17:23:06 +0000
4@@ -47,8 +47,8 @@
5 A concrete container type implemented using a plain old chroot.
6 """
7
8- def __init__(self, container_id, config, service):
9- super().__init__(container_id, 'chroot', config, service)
10+ def __init__(self, container_id, config, service, stdin):
11+ super().__init__(container_id, 'chroot', config, service, stdin)
12 # FIXME: Disabling seccomp is a temporary measure until we fully understand why we need
13 # it or figure out when we need it.
14 os.environ['PROOT_NO_SECCOMP'] = '1'
15@@ -60,13 +60,13 @@
16 command_prefix = "{} fakeroot chroot {}".format(
17 self._build_fakechroot_command(), self.root_path)
18 args = shlex.split(command_prefix + ' ' + command_string)
19- cmd = subprocess.Popen(args)
20- return cmd.wait()
21+
22+ return self._run_with_stdin(args) or subprocess.Popen(args).wait()
23
24 def destroy_libertine_container(self, force):
25 return self._delete_rootfs()
26
27- def create_libertine_container(self, password=None, multiarch=False):
28+ def create_libertine_container(self, multiarch=False):
29 # Create the actual chroot
30 command_line = "{} fakeroot debootstrap --verbose --variant=fakechroot {} {}".format(
31 self._build_fakechroot_command(), self.installed_release, self.root_path)
32@@ -231,6 +231,9 @@
33 def finish_application(self, app):
34 app.wait()
35
36+ def set_password(self, password):
37+ pass # No passwords in chroot containers
38+
39 def _run_ldconfig(self):
40 utils.get_logger().info(utils._("Refreshing the container's dynamic linker run-time bindings..."))
41
42
43=== modified file 'python/libertine/Libertine.py'
44--- python/libertine/Libertine.py 2017-04-07 17:23:05 +0000
45+++ python/libertine/Libertine.py 2017-04-07 17:23:06 +0000
46@@ -16,6 +16,8 @@
47 import contextlib
48 import os
49 import shutil
50+import subprocess
51+import time
52
53 from . import utils, ContainerControlClient
54 from libertine.ContainersConfig import ContainersConfig
55@@ -79,11 +81,12 @@
56
57 :param container_id: The machine-readable container name.
58 """
59- def __init__(self, container_id, container_type, config, service):
60+ def __init__(self, container_id, container_type, config, service, stdin):
61 self.container_type = container_type
62 self.container_id = container_id
63 self._config = config
64 self._service = service
65+ self._stdin = stdin
66 self._app_name = ''
67 self._pid = 0
68 self.root_path = utils.get_libertine_container_rootfs_path(self.container_id)
69@@ -145,7 +148,7 @@
70 for language_pack in [p.format(self.language) for p in base_language_packs]:
71 self.install_package(language_pack, update_cache=False)
72
73- def create_libertine_container(self, password=None, multiarch=False):
74+ def create_libertine_container(self, multiarch=False):
75 self.install_base_language_packs()
76
77 def destroy_libertine_container(self, force):
78@@ -204,6 +207,20 @@
79 """
80 pass
81
82+ def _run_with_stdin(self, command):
83+ if self._stdin:
84+ p = subprocess.Popen(command, stdin=subprocess.PIPE)
85+ while p.poll() is None:
86+ if not self._stdin.empty():
87+ p.stdin.write(self._stdin.get())
88+ p.stdin.flush()
89+
90+ time.sleep(.1)
91+
92+ return p.returncode
93+
94+ return None
95+
96 def update_apt_cache(self):
97 """
98 Updates the apt cache in the container.
99@@ -270,6 +287,11 @@
100 return False
101 return self.run_in_container(_apt_command_prefix() + "autoremove --purge") == 0
102
103+ def set_password(self, password):
104+ if password:
105+ import crypt
106+ return self.run_in_container("usermod -p {password} {username}".format(username=os.environ['USER'], password=crypt.crypt(password)))
107+
108 def configure_multiarch(self, should_enable):
109 """
110 Enables or disables multiarch repositories.
111@@ -335,10 +357,10 @@
112 """
113 A concrete mock container type. Used for unit testing.
114 """
115- def __init__(self, container_id, config, service):
116- super().__init__(container_id, 'mock', config, service)
117+ def __init__(self, container_id, config, service, stdin):
118+ super().__init__(container_id, 'mock', config, service, stdin)
119
120- def create_libertine_container(self, password=None, multiarch=False):
121+ def create_libertine_container(self, multiarch=False):
122 return True
123
124 def destroy_libertine_container(self, force):
125@@ -389,7 +411,7 @@
126 A sandbox for DEB-packaged X11-based applications.
127 """
128
129- def __init__(self, container_id, containers_config=None, service=None):
130+ def __init__(self, container_id, containers_config=None, service=None, stdin=None):
131 """
132 Initializes the container object.
133
134@@ -404,15 +426,15 @@
135
136 if container_type == "lxc":
137 from libertine.LxcContainer import LibertineLXC
138- self.container = LibertineLXC(container_id, self.containers_config, service)
139+ self.container = LibertineLXC(container_id, self.containers_config, service, stdin)
140 elif container_type == "lxd":
141 from libertine.LxdContainer import LibertineLXD
142- self.container = LibertineLXD(container_id, self.containers_config, service)
143+ self.container = LibertineLXD(container_id, self.containers_config, service, stdin)
144 elif container_type == "chroot":
145 from libertine.ChrootContainer import LibertineChroot
146- self.container = LibertineChroot(container_id, self.containers_config, service)
147+ self.container = LibertineChroot(container_id, self.containers_config, service, stdin)
148 elif container_type == "mock":
149- self.container = LibertineMock(container_id, self.containers_config, service)
150+ self.container = LibertineMock(container_id, self.containers_config, service, stdin)
151 else:
152 raise RuntimeError(utils._("Unsupported container type '{container_type}'").format(container_type))
153
154@@ -438,14 +460,14 @@
155 """
156 return self.container.destroy_libertine_container(force)
157
158- def create_libertine_container(self, password=None, multiarch=False):
159+ def create_libertine_container(self, multiarch=False):
160 """
161 Creates the container.
162 """
163 self.container.architecture = HostInfo().get_host_architecture()
164 self.container.installed_release = self.containers_config.get_container_distro(self.container_id)
165
166- return self.container.create_libertine_container(password, multiarch)
167+ return self.container.create_libertine_container(multiarch)
168
169 def update_libertine_container(self, new_locale=None):
170 """
171@@ -589,3 +611,10 @@
172 return self.container.configure_remove_archive(archive)
173 except RuntimeError as e:
174 return handle_runtime_error(e)
175+
176+ def set_password(self, password):
177+ try:
178+ with ContainerRunning(self.container):
179+ return self.container.set_password(password)
180+ except RuntimeError as e:
181+ return handle_runtime_error(e)
182
183=== modified file 'python/libertine/LxcContainer.py'
184--- python/libertine/LxcContainer.py 2017-03-23 19:23:20 +0000
185+++ python/libertine/LxcContainer.py 2017-04-07 17:23:06 +0000
186@@ -157,8 +157,8 @@
187 A concrete container type implemented using an LXC container.
188 """
189
190- def __init__(self, container_id, config, service):
191- super().__init__(container_id, 'lxc', config, service)
192+ def __init__(self, container_id, config, service, stdin):
193+ super().__init__(container_id, 'lxc', config, service, stdin)
194 self.container = lxc_container(container_id)
195 self.host_info = HostInfo.HostInfo()
196 self._freeze_on_stop = config.get_freeze_on_stop(self.container_id)
197@@ -255,8 +255,10 @@
198 return lxc_stop(self.container, self._freeze_on_stop)
199
200 def run_in_container(self, command_string):
201- cmd_args = shlex.split(command_string)
202- return self.container.attach_wait(lxc.attach_run_command, cmd_args)
203+ popen_args = shlex.split("lxc-attach -P {root_path} -n {container_id} -- {command}"
204+ .format(root_path=utils.get_libertine_containers_dir_path(),
205+ container_id=self.container_id, command=command_string))
206+ return self._run_with_stdin(popen_args) or self.container.attach_wait(lxc.attach_run_command, shlex.split(command_string))
207
208 def update_packages(self, update_locale=False):
209 if self.timezone_needs_update():
210@@ -282,10 +284,7 @@
211 self.container.destroy()
212 return True
213
214- def create_libertine_container(self, password=None, multiarch=False):
215- if password is None:
216- return False
217-
218+ def create_libertine_container(self, multiarch=False):
219 username = os.environ['USER']
220 user_id = os.getuid()
221 group_id = os.getgid()
222@@ -336,8 +335,7 @@
223 self.update_locale()
224
225 self.run_in_container("userdel -r ubuntu")
226- self.run_in_container("useradd -u {} -p {} -G sudo {}".format(
227- str(user_id), crypt.crypt(password), str(username)))
228+ self.run_in_container("useradd -u {} -G sudo {}".format(str(user_id), str(username)))
229
230 if multiarch and self.architecture == 'amd64':
231 utils.get_logger().info(utils._("Adding i386 multiarch support..."))
232
233=== modified file 'python/libertine/LxdContainer.py'
234--- python/libertine/LxdContainer.py 2017-04-07 17:23:05 +0000
235+++ python/libertine/LxdContainer.py 2017-04-07 17:23:06 +0000
236@@ -387,8 +387,8 @@
237
238
239 class LibertineLXD(Libertine.BaseContainer):
240- def __init__(self, name, config, service):
241- super().__init__(name, 'lxd', config, service)
242+ def __init__(self, name, config, service, stdin):
243+ super().__init__(name, 'lxd', config, service, stdin)
244 self._host_info = HostInfo.HostInfo()
245 self._container = None
246 self._freeze_on_stop = config.get_freeze_on_stop(self.container_id)
247@@ -504,7 +504,8 @@
248 return _lxc_args(self.container_id, command, environ)
249
250 def run_in_container(self, command):
251- return subprocess.Popen(self._lxc_args(command, os.environ.copy())).wait()
252+ args = self._lxc_args(command, os.environ.copy())
253+ return self._run_with_stdin(args) or subprocess.Popen(args).wait()
254
255 def start_container(self, home=env_home_path()):
256 if not self._try_get_container():
257
258=== modified file 'python/libertine/service/download.py'
259--- python/libertine/service/download.py 2017-04-07 17:23:05 +0000
260+++ python/libertine/service/download.py 2017-04-07 17:23:06 +0000
261@@ -22,10 +22,11 @@
262
263
264 class Download(dbus.service.Object):
265- def __init__(self, connection, id):
266+ def __init__(self, connection, id, input_queue):
267 self._finished = multiprocessing.Event()
268 self._result = multiprocessing.SimpleQueue()
269 self._error = multiprocessing.SimpleQueue()
270+ self._input = input_queue
271 dbus.service.Object.__init__(self, conn=connection, object_path=(constants.DOWNLOAD_OBJECT % id))
272
273 @property
274@@ -53,6 +54,9 @@
275 def data(self, message):
276 self._result.put(message)
277
278+ def input(self, message):
279+ self._input.put(message.encode('utf-8'))
280+
281 # Signals to satisfy the download interface
282
283 @dbus.service.signal(constants.DOWNLOAD_INTERFACE, signature='o')
284
285=== modified file 'python/libertine/service/operations_monitor.py'
286--- python/libertine/service/operations_monitor.py 2017-04-07 17:23:05 +0000
287+++ python/libertine/service/operations_monitor.py 2017-04-07 17:23:06 +0000
288@@ -27,8 +27,8 @@
289 self._operations = []
290 dbus.service.Object.__init__(self, conn=connection, object_path=constants.OPERATIONS_MONITOR_OBJECT)
291
292- def new_operation(self):
293- self._operations.append(download.Download(self.connection, str(uuid.uuid4().fields[-1])))
294+ def new_operation(self, input_queue):
295+ self._operations.append(download.Download(self.connection, str(uuid.uuid4().fields[-1]), input_queue))
296 return self._operations[-1].id
297
298 def remove_from_connection(self, path):
299
300=== modified file 'python/libertine/service/task_dispatcher_base.py'
301--- python/libertine/service/task_dispatcher_base.py 2017-04-07 17:23:05 +0000
302+++ python/libertine/service/task_dispatcher_base.py 2017-04-07 17:23:06 +0000
303@@ -33,7 +33,7 @@
304 def _cleanup(self):
305 for task in [task for task in self._tasks if task.should_delete]:
306 utils.get_logger().debug("Cleaning up task '{}'".format(task.id))
307- task.thread.join()
308+ task.join()
309 self._monitor.remove_from_connection(task.id)
310 self._tasks.remove(task)
311
312
313=== modified file 'python/libertine/service/tasks/base_task.py'
314--- python/libertine/service/tasks/base_task.py 2017-04-07 17:23:05 +0000
315+++ python/libertine/service/tasks/base_task.py 2017-04-07 17:23:06 +0000
316@@ -33,8 +33,11 @@
317 self._lock = lock
318 self._container = container_id
319 self._config = config
320+ self._monitor = monitor
321+
322 self._finished_at = multiprocessing.SimpleQueue()
323- self._monitor = monitor
324+ self._stdin = multiprocessing.SimpleQueue()
325+ self._thread = None
326 self._operation_id = None
327 self._delete_at = None
328
329@@ -69,14 +72,17 @@
330
331 return False
332
333+ def join(self):
334+ self._thread.join()
335+
336 def _finish(self):
337 self._finished_at.put(time.time())
338
339 def start(self):
340- self._operation_id = self._monitor.new_operation()
341- self.thread = multiprocessing.Process(target=self.run)
342- self.thread.start()
343- return self.thread
344+ self._operation_id = self._monitor.new_operation(self._stdin)
345+ self._thread = multiprocessing.Process(target=self.run)
346+ self._thread.start()
347+ return self._thread
348
349 def watch_file(self, finished, path):
350 with open(path, 'rb') as thefile:
351@@ -99,6 +105,7 @@
352 with output_redirector.OutputRedirector(self._operation_id.split("/")[-1]) as redirector:
353 end_watch = multiprocessing.Event()
354 multiprocessing.Process(target=self.watch_file, args=(end_watch, redirector.path)).start()
355+
356 if self._lock is not None:
357 with self._lock:
358 self._refresh_database(False)
359
360=== modified file 'python/libertine/service/tasks/create_task.py'
361--- python/libertine/service/tasks/create_task.py 2017-04-07 17:23:05 +0000
362+++ python/libertine/service/tasks/create_task.py 2017-04-07 17:23:06 +0000
363@@ -32,11 +32,10 @@
364
365 def _run(self):
366 utils.get_logger().debug("Creating container '%s'" % self._container)
367-
368 try:
369 container = LibertineContainer(self._container, self._config, self._client)
370
371- if not container.create_libertine_container(password='', multiarch=self._multiarch):
372+ if not container.create_libertine_container(multiarch=self._multiarch):
373 self._config.delete_container(self._container)
374 self._error("Creating container '%s' failed" % self._container)
375 else:
376
377=== modified file 'python/libertine/service/tasks/install_task.py'
378--- python/libertine/service/tasks/install_task.py 2017-04-07 17:23:05 +0000
379+++ python/libertine/service/tasks/install_task.py 2017-04-07 17:23:06 +0000
380@@ -36,7 +36,7 @@
381
382 def _run(self):
383 utils.get_logger().debug("Installing package '%s'" % self._package)
384- container = LibertineContainer(self._container, self._config, self._client)
385+ container = LibertineContainer(self._container, self._config, self._client, self._stdin)
386 if container.install_package(self._package, update_cache=self._update_cache, no_dialog=True):
387 self._config.update_package_install_status(self._container, self._package_name, "installed")
388 utils.refresh_libertine_scope()
389
390=== modified file 'python/libertine/service/tasks/remove_task.py'
391--- python/libertine/service/tasks/remove_task.py 2017-04-07 17:23:05 +0000
392+++ python/libertine/service/tasks/remove_task.py 2017-04-07 17:23:06 +0000
393@@ -31,7 +31,7 @@
394
395 def _run(self):
396 utils.get_logger().debug("Removing package '%s'" % self._package)
397- container = LibertineContainer(self._container, self._config, self._client)
398+ container = LibertineContainer(self._container, self._config, self._client, self._stdin)
399 if container.remove_package(self._package, no_dialog=True):
400 self._config.delete_package(self._container, self._package)
401 utils.refresh_libertine_scope()
402
403=== modified file 'python/libertine/service/tasks/update_task.py'
404--- python/libertine/service/tasks/update_task.py 2017-04-07 17:23:05 +0000
405+++ python/libertine/service/tasks/update_task.py 2017-04-07 17:23:06 +0000
406@@ -32,7 +32,7 @@
407
408 def _run(self):
409 utils.get_logger().debug("Updating container '%s'" % self._container)
410- container = LibertineContainer(self._container, self._config, self._client)
411+ container = LibertineContainer(self._container, self._config, self._client, self._stdin)
412 self._config.update_container_install_status(self._container, "updating")
413
414 new_locale = self._get_updated_locale()
415
416=== modified file 'tests/unit/service/test_operations_monitor.py'
417--- tests/unit/service/test_operations_monitor.py 2017-03-07 20:45:30 +0000
418+++ tests/unit/service/test_operations_monitor.py 2017-04-07 17:23:06 +0000
419@@ -20,6 +20,7 @@
420 class TestOperationsMonitor(TestCase):
421 def setUp(self):
422 self._connection = unittest.mock.Mock()
423+ self._stdin = unittest.mock.Mock()
424
425 def test_new_operation_returns_some_id(self):
426 with unittest.mock.patch('dbus.service.Object'):
427@@ -27,7 +28,7 @@
428 monitor._connection = self._connection
429
430 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
431- self.assertIsNotNone(monitor.new_operation())
432+ self.assertIsNotNone(monitor.new_operation(self._stdin))
433
434 def test_remove_connection(self):
435 with unittest.mock.patch('dbus.service.Object'):
436@@ -35,7 +36,7 @@
437 monitor._connection = self._connection
438
439 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
440- monitor.remove_from_connection(monitor.new_operation())
441+ monitor.remove_from_connection(monitor.new_operation(self._stdin))
442 MockDownload.return_value.remove_from_connection.assert_called_once_with()
443
444 def test_returns_done_for_operation(self):
445@@ -45,10 +46,10 @@
446
447 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
448 MockDownload.return_value.done = True
449- self.assertTrue(monitor.done(monitor.new_operation()))
450+ self.assertTrue(monitor.done(monitor.new_operation(self._stdin)))
451
452 MockDownload.return_value.done = False
453- self.assertFalse(monitor.done(monitor.new_operation()))
454+ self.assertFalse(monitor.done(monitor.new_operation(self._stdin)))
455
456 # non-existent operation
457 self.assertFalse(monitor.done("123456"))
458@@ -60,10 +61,10 @@
459
460 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
461 MockDownload.return_value.done = True
462- self.assertFalse(monitor.running(monitor.new_operation()))
463+ self.assertFalse(monitor.running(monitor.new_operation(self._stdin)))
464
465 MockDownload.return_value.done = False
466- self.assertTrue(monitor.running(monitor.new_operation()))
467+ self.assertTrue(monitor.running(monitor.new_operation(self._stdin)))
468
469 # non-existent operation
470 self.assertFalse(monitor.running("123456"))
471@@ -75,7 +76,7 @@
472
473 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
474 MockDownload.return_value.result = "pokemongus"
475- self.assertEqual("pokemongus", monitor.result(monitor.new_operation()))
476+ self.assertEqual("pokemongus", monitor.result(monitor.new_operation(self._stdin)))
477
478 # non-existent operation
479 self.assertEqual("", monitor.result("123456"))
480@@ -87,7 +88,7 @@
481
482 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
483 MockDownload.return_value.last_error = "pokemongus"
484- self.assertEqual("pokemongus", monitor.last_error(monitor.new_operation()))
485+ self.assertEqual("pokemongus", monitor.last_error(monitor.new_operation(self._stdin)))
486
487 # non-existent operation
488 self.assertEqual("", monitor.last_error("123456"))
489@@ -99,7 +100,7 @@
490 monitor._locations = []
491
492 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
493- path = monitor.new_operation()
494+ path = monitor.new_operation(self._stdin)
495 monitor.finished(path)
496 MockDownload.return_value.finished.assert_called_once_with(path)
497
498@@ -115,7 +116,7 @@
499 monitor._locations = []
500
501 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
502- path = monitor.new_operation()
503+ path = monitor.new_operation(self._stdin)
504 monitor.error(path, "something messed up")
505 MockDownload.return_value.error.assert_called_once_with("something messed up")
506
507@@ -131,7 +132,7 @@
508 monitor._locations = []
509
510 with unittest.mock.patch('libertine.service.operations_monitor.download.Download') as MockDownload:
511- path = monitor.new_operation()
512+ path = monitor.new_operation(self._stdin)
513 monitor.data(path, "some of that gud data")
514 MockDownload.return_value.data.assert_called_once_with("some of that gud data")
515
516
517=== modified file 'tools/libertine-container-manager'
518--- tools/libertine-container-manager 2017-03-23 19:23:20 +0000
519+++ tools/libertine-container-manager 2017-04-07 17:23:06 +0000
520@@ -34,7 +34,6 @@
521 self.containers_config = ContainersConfig()
522 self.host_info = HostInfo()
523
524-
525 def _container(self, container_id):
526 try:
527 return LibertineContainer(container_id, self.containers_config)
528@@ -53,7 +52,25 @@
529 return host_locale
530
531 def create(self, args):
532+ if not args.type:
533+ container_type = self.host_info.select_container_type_by_kernel()
534+ else:
535+ if (args.type == 'lxc' and not self.host_info.has_lxc_support()) or \
536+ (args.type == 'lxd' and not self.host_info.has_lxd_support()):
537+ libertine.utils.get_logger().error(utils._("System kernel does not support {type} type containers. "
538+ "Please either use chroot or omit the -t option.").format(type=args.type))
539+ sys.exit(1)
540+ container_type = args.type
541+
542 password = None
543+ if container_type == "lxc" or container_type == "lxd":
544+ if args.password:
545+ password = args.password
546+ elif sys.stdin.isatty():
547+ print(utils._("Enter password for your user in the Libertine container or leave blank for no password:"))
548+ password = getpass.getpass()
549+ else:
550+ password = sys.stdin.readline().rstrip()
551
552 if args.distro and not self.host_info.is_distro_valid(args.distro, args.force):
553 utils.get_logger().error(utils._("Invalid distro {distro}").format(distro=args.distro))
554@@ -67,16 +84,6 @@
555 "form ([a-z0-9][a-z0-9+.-]+).").format(container_id=args.id))
556 sys.exit(1)
557
558- if not args.type:
559- container_type = self.host_info.select_container_type_by_kernel()
560- else:
561- if (args.type == 'lxc' and not self.host_info.has_lxc_support()) or \
562- (args.type == 'lxd' and not self.host_info.has_lxd_support()):
563- utils.get_logger().error(utils._("System kernel does not support {container_type} type containers. "
564- "Please either use chroot or omit the -t option.").format(container_type=args.type))
565- sys.exit(1)
566- container_type = args.type
567-
568 if not args.distro:
569 args.distro = self.host_info.get_host_distro_release()
570 elif container_type == "chroot":
571@@ -91,15 +98,6 @@
572 if not args.name:
573 args.name = "Ubuntu \'" + (self.host_info.get_distro_codename(args.distro) or args.distro) + "\'"
574
575- if container_type == "lxc" or container_type == "lxd":
576- if args.password:
577- password = args.password
578- elif sys.stdin.isatty():
579- print(utils._("Enter password for your user in the Libertine container or leave blank for no password:"))
580- password = getpass.getpass()
581- else:
582- password = sys.stdin.readline().rstrip()
583-
584 self.containers_config.add_new_container(args.id, args.name, container_type, args.distro)
585
586 multiarch = 'disabled'
587@@ -125,6 +123,8 @@
588 self.containers_config.delete_container(args.id)
589 sys.exit(1)
590
591+ container.set_password(password)
592+
593 self.containers_config.update_container_install_status(args.id, "ready")
594
595 utils.refresh_libertine_scope()

Subscribers

People subscribed via source and target branches