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

Proposed by Larry Price on 2017-04-03
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 on 2017-04-07
Libertine Developers 2017-04-03 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.
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 on 2017-04-07

merge

466. By Larry Price on 2017-04-07

chmod

Unmerged revisions

466. By Larry Price on 2017-04-07

chmod

465. By Larry Price on 2017-04-07

merge

464. By Larry Price on 2017-04-03

fixing up merge and tests

463. By Larry Price on 2017-04-03

merge

462. By Larry Price on 2017-03-31

create with password separate

461. By Larry Price on 2017-03-31

chroot and lxc

460. By Larry Price on 2017-03-30

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

459. By Larry Price on 2017-03-20

minor changes

458. By Larry Price on 2017-03-20

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

457. By Larry Price on 2017-03-20

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