Merge lp:~townsend/unity8-preview-lxc/fix-setup into lp:unity8-preview-lxc

Proposed by Christopher Townsend
Status: Merged
Approved by: Stephen M. Webb
Approved revision: 80
Merged at revision: 77
Proposed branch: lp:~townsend/unity8-preview-lxc/fix-setup
Merge into: lp:unity8-preview-lxc
Diff against target: 518 lines (+114/-238)
9 files modified
bin/unity8-lxc-compositor (+15/-0)
bin/unity8-lxc-session (+4/-6)
bin/unity8-lxc-setup (+56/-209)
data/unity8-autodev (+12/-0)
data/unity8-lxc.conf (+20/-0)
debian/control (+1/-1)
debian/install (+1/-0)
debian/unity8-lxc.postinst (+0/-4)
docs/unity8-lxc-setup.1 (+5/-18)
To merge this branch: bzr merge lp:~townsend/unity8-preview-lxc/fix-setup
Reviewer Review Type Date Requested Status
Stephen M. Webb (community) Approve
Review via email: mp+275348@code.launchpad.net

Commit message

Rework the creation of the unity8-lxc container since the Ubuntu Desktop Next ISO has been deprecated.
Many fixes for working with the systemd based containers.

To post a comment you must log in.
Revision history for this message
Stephen M. Webb (bregma) wrote :

Other than problems mentioned on IRC (looking for the Xenial image but the image has not yet been created as the archives are not open when I tested this) and the long delay on startup, this works well and is cleaner than the original.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/unity8-lxc-compositor'
2--- bin/unity8-lxc-compositor 2015-06-17 12:43:39 +0000
3+++ bin/unity8-lxc-compositor 2015-10-22 16:22:57 +0000
4@@ -38,6 +38,21 @@
5 lxc-wait -t 0 -s RUNNING -n $CONTAINER_NAME || lxc-start -n $CONTAINER_NAME -d && \
6 lxc-wait -t 5 -s RUNNING -n $CONTAINER_NAME
7
8+# Wait for systemd to be (almost) up and running before proceeding
9+(cat << EOF
10+i=0
11+echo \$i
12+while [ \$i -lt "20" ]; do
13+ pgrep agetty
14+ if [ \$? -eq "0" ]; then
15+ break
16+ fi
17+ i=\$[\$i+1]
18+ sleep 1
19+done
20+EOF
21+) | lxc-attach -n $CONTAINER_NAME -- bash
22+
23 lxc-attach -n $CONTAINER_NAME -- /usr/sbin/unity-system-compositor.sleep $* &
24
25 PARENT_PID=$!
26
27=== modified file 'bin/unity8-lxc-session'
28--- bin/unity8-lxc-session 2015-06-17 12:43:39 +0000
29+++ bin/unity8-lxc-session 2015-10-22 16:22:57 +0000
30@@ -47,13 +47,11 @@
31 cgm movepid \$cgroup $SUDO_USER \$\$
32 done
33
34-rm -Rf /run/systemd
35-cp -R /var/lib/host-systemd /run/systemd
36+cp -R /var/lib/host-systemd/users /run/systemd/
37+cp -R /var/lib/host-systemd/seats /run/systemd/
38+cp -R /var/lib/host-systemd/sessions /run/systemd/
39
40-if [ ! -L /dev/shm ] && [ -e /dev/shm ]; then
41- rmdir /dev/shm 2>/dev/null || mv /dev/shm /dev/shm.bak
42- ln -s /run/shm /dev/shm
43-fi
44+cp -R /var/lib/host-udev /run/udev/
45
46 sudo -u $SUDO_USER -E /usr/bin/lightdm-unity8-session
47 EOF
48
49=== modified file 'bin/unity8-lxc-setup'
50--- bin/unity8-lxc-setup 2015-06-29 14:55:53 +0000
51+++ bin/unity8-lxc-setup 2015-10-22 16:22:57 +0000
52@@ -30,8 +30,6 @@
53 from distro_info import UbuntuDistroInfo, DistroDataOutdated
54
55 CONTAINER_NAME = "unity8-lxc"
56-ISO_URL = "http://cdimage.ubuntu.com/ubuntu-desktop-next/daily-live/" \
57- "current/RELEASE-desktop-ARCH.iso.zsync"
58 SKIP_JOB = ["bluetooth", "lightdm", "plymouth", "plymouth-upstart-bridge",
59 "plymouth-shutdown", "ubiquity"]
60
61@@ -39,18 +37,9 @@
62 # Argument parsing
63 parser = argparse.ArgumentParser(description="Unity8 inside LXC")
64 parser.add_argument(
65- "--rebuild-all", action="store_true",
66- help=("Wipe and replace the container rootfs and configuration."))
67-parser.add_argument(
68- "--rebuild-config", action="store_true",
69- help=("Wipe and regenerate the container configuration."))
70-parser.add_argument(
71- "--rebuild-rootfs", action="store_true",
72+ "--rebuild", action="store_true",
73 help=("Wipe and replace the container rootfs."))
74 parser.add_argument(
75- "--redownload", action="store_true",
76- help=("Re-download the ISO image instead of using the local version."))
77-parser.add_argument(
78 "--test", type=int, metavar="SECONDS", default=None,
79 help=("Test mode, argument is time in seconds for the session."))
80 parser.add_argument(
81@@ -68,17 +57,10 @@
82 container = lxc.Container(CONTAINER_NAME)
83 container_path = "%s/%s" % (lxc.default_config_path, CONTAINER_NAME)
84 rootfs_path = "%s/rootfs" % container_path
85-iso_filename = "%s/ubuntu-next.iso" % container_path
86-iso_path = "%s/iso" % container_path
87-squashfs_path = "%s/squashfs" % container_path
88
89 (distro, version, codename) = platform.linux_distribution()
90
91-if not os.path.exists(iso_filename):
92- args.redownload = True
93-
94 # Actions
95-generate_config = True
96 generate_rootfs = True
97
98 def start_container(wait_for_network=True):
99@@ -100,102 +82,22 @@
100
101 # Deal with existing containers
102 if container.defined:
103- generate_config = False
104 generate_rootfs = False
105
106 if not args.test and container.running:
107 print("Stopping the existing container.")
108 container.stop()
109
110- if args.rebuild_all:
111- args.rebuild_config = True
112- args.rebuild_rootfs = True
113-
114- if args.rebuild_config:
115- generate_config = True
116- container.clear_config()
117-
118- if args.rebuild_rootfs:
119+ if args.rebuild:
120+ print("Deleting current unity8-lxc container...")
121 generate_rootfs = True
122- if os.path.exists(rootfs_path):
123- shutil.rmtree(rootfs_path)
124+ container.destroy()
125+ del container
126+ container = lxc.Container(CONTAINER_NAME)
127
128-if not generate_config and not generate_rootfs and not args.test and not args.update_lxc:
129+if not generate_rootfs and not args.test and not args.update_lxc:
130 parser.error("The container already exists.")
131
132-
133-if generate_config:
134- # Setup the container config
135- ## Load the default LXC config keys
136- container.load_config("/usr/share/lxc/config/ubuntu.common.conf")
137-
138- ## Setup the network ##
139- container.append_config_item("lxc.network.type", "veth")
140- container.append_config_item("lxc.network.link", "lxcbr0")
141- container.append_config_item("lxc.network.hwaddr", "00:16:3e:xx:xx:xx")
142-
143- ## Architecture
144- container.set_config_item("lxc.arch", "x86_64")
145-
146- ## Rootfs path
147- container.set_config_item("lxc.rootfs", rootfs_path)
148-
149- ## Hostname
150- container.set_config_item("lxc.utsname", CONTAINER_NAME)
151-
152- ## Devices
153- ### /dev/tty*
154- container.append_config_item("lxc.cgroup.devices.allow", "c 4:* rwm")
155-
156- ### /dev/input/*
157- container.append_config_item("lxc.cgroup.devices.allow", "c 13:* rwm")
158- container.append_config_item("lxc.mount.entry",
159- "/dev/input dev/input none bind,create=dir")
160-
161- ### /dev/dri/*
162- container.append_config_item("lxc.cgroup.devices.allow", "c 226:* rwm")
163- container.append_config_item("lxc.mount.entry",
164- "/dev/dri dev/dri none bind,create=dir")
165-
166- ### /dev/snd/*
167- container.append_config_item("lxc.cgroup.devices.allow", "c 116:* rwm")
168- container.append_config_item("lxc.mount.entry",
169- "/dev/snd dev/snd none bind,create=dir")
170-
171- ## Enable cgmanager access
172- container.set_config_item("lxc.mount.auto", "cgroup:mixed proc:mixed sys:mixed")
173-
174- ## Allow nested containers
175- container.set_config_item("lxc.aa_profile", "lxc-container-default-with-nesting")
176-
177- ## Disable the lxc autodev
178- container.append_config_item("lxc.autodev", "0")
179-
180- # Setup the /home bind-mount
181- container.append_config_item("lxc.mount.entry", "/home home none bind")
182-
183- # Setup the /etc/shadow bind-mount
184- container.append_config_item("lxc.mount.entry",
185- "/etc/shadow etc/shadow none bind")
186-
187- # Setup the local time and timezone
188- container.append_config_item("lxc.mount.entry",
189- "/etc/localtime etc/localtime none bind")
190- container.append_config_item("lxc.mount.entry",
191- "/etc/timezone etc/timezone none bind")
192-
193- # Setup up /run/udev
194- container.append_config_item("lxc.mount.entry",
195- "/run/udev var/lib/host-udev none bind,ro,create=dir")
196-
197- # Setup /run/systemd
198- container.append_config_item("lxc.mount.entry",
199- "/run/systemd var/lib/host-systemd none bind,ro,create=dir")
200-
201- ## Dump it all to disk
202- container.save_config()
203-
204-
205 if generate_rootfs:
206 # Setup the container rootfs
207
208@@ -213,44 +115,11 @@
209 except DistroDataOutdated:
210 current_release = UbuntuDistroInfo().stable()
211
212- ## Download the ISO image
213- if args.redownload:
214- iso_url = ISO_URL.replace("ARCH", architecture)
215- iso_url = iso_url.replace("RELEASE", current_release)
216-
217- ### Use zsync to fetch the ISO
218- cmd = "cd %s && zsync -i %s -o %s %s" % (container_path, iso_filename, iso_filename, iso_url)
219- os.system(cmd)
220-
221- ### Remove the ISO backup since it's not needed
222- if os.path.exists(iso_filename+".zs-old"):
223- os.remove(iso_filename+".zs-old")
224-
225- if not os.path.exists(iso_filename):
226- parser.error("No Unity 8 Desktop Next ISO exists!")
227-
228- ## Mount the ISO
229- if not os.path.exists(iso_path):
230- os.mkdir(iso_path)
231- subprocess.call(["mount", "-o", "loop,ro", iso_filename, iso_path])
232-
233- if not os.path.exists(squashfs_path):
234- os.mkdir(squashfs_path)
235- subprocess.call(["mount", "-o", "loop,ro",
236- os.path.join(iso_path, "casper", "filesystem.squashfs"),
237- squashfs_path])
238-
239- ## Unpack the ISO
240- print("Unpacking the ISO image...")
241- subprocess.call(["rsync", "-aA", "--hard-links", "--numeric-ids",
242- "%s/" % squashfs_path, "%s/" % rootfs_path])
243-
244- ## Unmount the ISO
245- subprocess.call(["umount", squashfs_path])
246- os.rmdir(squashfs_path)
247-
248- subprocess.call(["umount", iso_path])
249- os.rmdir(iso_path)
250+ print("Creating the new unity8-lxc container...")
251+ container.create("download", 0,
252+ {"dist": "ubuntu",
253+ "release": current_release,
254+ "arch": architecture})
255
256 ## Configure
257 print("Configuring the Unity8 LXC...")
258@@ -262,7 +131,7 @@
259 ### Generate /etc/hosts
260 with open(os.path.join(rootfs_path, "etc", "hosts"), "w+") as fd:
261 fd.write("""127.0.0.1 localhost
262-127.0.1.1 unity8-mir
263+127.0.1.1 unity8-lxc
264
265 # The following lines are desirable for IPv6 capable hosts
266 ::1 localhost ip6-localhost ip6-loopback
267@@ -270,76 +139,54 @@
268 ff02::2 ip6-allrouters
269 """)
270
271- ### Disable some upstart jobs
272+ # Generate the package install policy override
273+ with open(os.path.join(rootfs_path, 'usr', 'sbin', 'policy-rc.d'), 'w+') as fd:
274+ fd.write("""#!/bin/sh
275+while true; do
276+case \"$1\" in
277+ -*) shift ;;
278+ makedev) exit 0;;
279+ *) exit 101;;
280+esac
281+done
282+""")
283+ fd.close()
284+
285+ os.chmod(os.path.join(rootfs_path, 'usr', 'sbin', 'policy-rc.d'), 0o755)
286+
287+ start_container()
288+
289+ # Remove the default ubuntu user in the container
290+ container.attach_wait(lxc.attach_run_command,
291+ ["userdel", "-r", "ubuntu"])
292+
293+ # Copy the ubuntu-desktop-next metapackage to the rootfs
294+ lxc_archive = os.path.join(rootfs_path, 'tmp', 'ubuntu-desktop-next.deb')
295+ glob_name = "ubuntu-desktop-next_*_%s.deb" % architecture
296+ metapackage = glob.glob(os.path.join('/', 'usr', 'share', 'unity8-lxc', glob_name))
297+ shutil.copy(metapackage[0], lxc_archive)
298+
299+ container.attach_wait(lxc.attach_run_command,
300+ ["apt-get", "update"])
301+
302+ container.attach_wait(lxc.attach_run_command,
303+ ["dpkg", "-i", os.path.join('/', 'tmp', 'ubuntu-desktop-next.deb')])
304+ container.attach_wait(lxc.attach_run_command,
305+ ["apt-get", "install", "-f", "-y"])
306+
307+ container.attach_wait(lxc.attach_run_command,
308+ ["systemctl", "disable", "lightdm.service"])
309+ container.stop()
310+
311+ # Disable some upstart jobs
312 for job in glob.glob("%s/etc/init/*.conf" % rootfs_path):
313 if os.path.basename(job).rsplit(".conf", 1)[0] in SKIP_JOB:
314 with open("%s.override" % job.rsplit(".conf", 1)[0], "w+") as fd:
315 fd.write("manual")
316
317- ### Create any missing devices
318- for i in range(64):
319- tty_path = os.path.join(rootfs_path, "dev", "tty%s" % i)
320- if not os.path.exists(tty_path):
321- os.mknod(tty_path, 0o620 | stat.S_IFCHR, device=os.makedev(4, i))
322- os.chown(tty_path, 0, 5)
323-
324- ### Generate /run/udev
325- with open(os.path.join(rootfs_path, "etc", "init", "udev-db.conf"), "w+") as fd:
326- fd.write("""start on starting udev
327-pre-start script
328- rm -Rf /run/udev
329- cp -R /var/lib/host-udev /run/udev
330-end script
331-""")
332-
333- ### Switch back to upstart instead of systemd
334- with open(os.path.join(rootfs_path, "etc", "X11", "default-display-manager"), "w+") as fd:
335- fd.write("")
336-
337- os.chdir(container_path)
338-
339- files = glob.glob("%s/upstart-sysv_*.deb" % container_path)
340-
341- upstart_file = ""
342-
343- if files:
344- upstart_file = files[0]
345-
346- if args.redownload or not os.path.exists(upstart_file):
347- if os.path.exists(upstart_file):
348- os.remove(upstart_file)
349-
350- rmadison_cmd = "rmadison -s %s upstart-sysv | cut -d '|' -f 2 | tr -d '[[:space:]]'" % current_release
351- upstart_sysv_ver = subprocess.getoutput(rmadison_cmd)
352- upstart_file = "upstart-sysv_%s_%s.deb" % (upstart_sysv_ver, architecture)
353-
354- dget_url = "http://archive.ubuntu.com/ubuntu/pool/main/u/upstart/%s" % upstart_file
355- subprocess.call(["dget", dget_url])
356-
357- if args.rebuild_rootfs:
358- rootfs_archive_path = os.path.join(rootfs_path, "var", "cache", "apt", "archives")
359- shutil.copy(upstart_file, rootfs_archive_path)
360-
361- start_container(False)
362-
363- print("Generating locale...")
364- r = os.popen("locale", "r").read().split("\n")
365- locale = ["locale-gen"]
366-
367- for i in r:
368- if i == "":
369- break
370- i = i.split('=')[1].replace("\"", "")
371- if not i in locale and i != "":
372- locale.append(i)
373-
374- container.attach_wait(lxc.attach_run_command, locale)
375-
376- print("Switching to upstart...")
377- container.attach_wait(lxc.attach_run_command,
378- ["apt-get", "install", "upstart-sysv", "-y", "--no-download", "--ignore-missing"])
379-
380- container.stop()
381+ with open(os.path.join(container_path, 'config'), 'a') as fd:
382+ fd.write("lxc.include = " + os.path.join('/', 'usr', 'share', 'unity8-lxc', 'unity8-lxc.conf'))
383+ fd.close()
384
385 if args.test:
386 # Start a test session
387
388=== added directory 'data'
389=== added file 'data/ubuntu-desktop-next_1.249_amd64.deb'
390Binary files data/ubuntu-desktop-next_1.249_amd64.deb 1970-01-01 00:00:00 +0000 and data/ubuntu-desktop-next_1.249_amd64.deb 2015-10-22 16:22:57 +0000 differ
391=== added file 'data/ubuntu-desktop-next_1.249_i386.deb'
392Binary files data/ubuntu-desktop-next_1.249_i386.deb 1970-01-01 00:00:00 +0000 and data/ubuntu-desktop-next_1.249_i386.deb 2015-10-22 16:22:57 +0000 differ
393=== added file 'data/unity8-autodev'
394--- data/unity8-autodev 1970-01-01 00:00:00 +0000
395+++ data/unity8-autodev 2015-10-22 16:22:57 +0000
396@@ -0,0 +1,12 @@
397+#!/usr/bin/python3
398+
399+import os
400+import stat
401+
402+rootfs_path = os.environ['LXC_ROOTFS_MOUNT']
403+
404+for i in range(64):
405+ tty_path = os.path.join(rootfs_path, "dev", "tty%s" % i)
406+ if not os.path.exists(tty_path):
407+ os.mknod(tty_path, 0o620 | stat.S_IFCHR, device=os.makedev(4, i))
408+ os.chown(tty_path, 0, 5)
409
410=== added file 'data/unity8-lxc.conf'
411--- data/unity8-lxc.conf 1970-01-01 00:00:00 +0000
412+++ data/unity8-lxc.conf 2015-10-22 16:22:57 +0000
413@@ -0,0 +1,20 @@
414+lxc.cgroup.devices.allow = c 4:* rwm
415+lxc.cgroup.devices.allow = c 13:* rwm
416+lxc.mount.entry = /dev/input dev/input none bind,create=dir
417+lxc.cgroup.devices.allow = c 226:* rwm
418+lxc.mount.entry = /dev/dri dev/dri none bind,create=dir
419+lxc.cgroup.devices.allow = c 116:* rwm
420+lxc.mount.entry = /dev/snd dev/snd none bind,create=dir
421+lxc.cgroup.devices.allow = c 189:* rwm
422+lxc.mount.entry = /dev/bus dev/bus none bind,create=dir
423+lxc.aa_profile = lxc-container-default-with-nesting
424+lxc.mount.entry = /home home none bind
425+lxc.mount.entry = /etc/shadow etc/shadow none bind
426+lxc.mount.entry = /etc/localtime etc/localtime none bind
427+lxc.mount.entry = /etc/timezone etc/timezone none bind
428+lxc.mount.entry = tmpfs run tmpfs rw,nodev,noexec,nosuid,size=104857600
429+lxc.mount.entry = none run/user tmpfs rw,nodev,noexec,nosuid,size=104857600,mode=0755,create=dir
430+lxc.mount.entry = /run/udev var/lib/host-udev none bind,ro,create=dir
431+lxc.mount.entry = /run/systemd var/lib/host-systemd none bind,ro,create=dir
432+lxc.mount.entry = /usr/lib/locale usr/lib/locale none bind
433+lxc.hook.autodev = /usr/share/unity8-lxc/unity8-autodev
434
435=== modified file 'debian/control'
436--- debian/control 2015-06-17 12:43:39 +0000
437+++ debian/control 2015-10-22 16:22:57 +0000
438@@ -8,7 +8,7 @@
439
440 Package: unity8-lxc
441 Architecture: all
442-Depends: python3, python3-lxc, sudo, python3-distro-info, zsync, devscripts, ${misc:Depends}
443+Depends: python3, python3-lxc, sudo, python3-distro-info, ${misc:Depends}
444 Description: Unity8 LXC integration
445 This package contains the scripts required to setup and run a Unity8
446 desktop inside an LXC container.
447
448=== modified file 'debian/install'
449--- debian/install 2014-09-30 18:09:11 +0000
450+++ debian/install 2015-10-22 16:22:57 +0000
451@@ -2,3 +2,4 @@
452 bin/* usr/bin/
453 xsessions/* usr/share/xsessions/
454 unity-greeter/* usr/share/unity-greeter/
455+data/* usr/share/unity8-lxc/
456
457=== modified file 'debian/unity8-lxc.postinst'
458--- debian/unity8-lxc.postinst 2014-11-20 19:49:17 +0000
459+++ debian/unity8-lxc.postinst 2015-10-22 16:22:57 +0000
460@@ -4,10 +4,6 @@
461
462 CONTAINER_NAME="unity8-lxc"
463
464-if [ -e /var/lib/lxc/$CONTAINER_NAME/config ]; then
465- unity8-lxc-setup --rebuild-config
466-fi
467-
468 if [ ! -d /var/lib/lxc/$CONTAINER_NAME ]; then
469 echo "**** Please run 'sudo unity8-lxc-setup' to setup the Unity8 LXC ****"
470 fi
471
472=== modified file 'docs/unity8-lxc-setup.1'
473--- docs/unity8-lxc-setup.1 2014-08-26 17:44:12 +0000
474+++ docs/unity8-lxc-setup.1 2015-10-22 16:22:57 +0000
475@@ -1,4 +1,4 @@
476-.TH unity8-lxc-setup 1 2014-08-26 "unity8-lxc-setup"
477+.TH unity8-lxc-setup 1 2015-10-22 "unity8-lxc-setup"
478 .SH NAME
479 unity8-lxc-setup \- administers the LXC for the Unity 8 desktop session
480
481@@ -23,26 +23,13 @@
482 .TP
483
484 .TP
485-.B --rebuild-all
486-Wipe and replace the container rootfs and configuration.
487-.TP
488-
489-.TP
490-.B --rebuild-config
491-Wipe and regenerate the container configuration.
492-.TP
493-
494-.TP
495-.B --rebuild-root
496+
497+.TP
498+.B --rebuild
499 Wipe and replace the container rootfs.
500 .TP
501
502 .TP
503-.B --redownload
504-Re-download the Unity 8 desktop preview ISO image instead of using the local version.
505-.TP
506-
507-.TP
508 .B --test SECONDS
509 Test mode, argument is time in seconds for the session.
510 .TP
511@@ -60,6 +47,6 @@
512 Written by Stéphane Graber and Christopher Townsend.
513
514 .SH COPYRIGHT
515-Copyright 2014 Canonical Ltd. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
516+Copyright 2014-2015 Canonical Ltd. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
517 .P
518 This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

Subscribers

People subscribed via source and target branches