Merge ~xueshengyao/pc-enablement/+git/oem-scripts:master into ~oem-solutions-engineers/pc-enablement/+git/oem-scripts:master

Proposed by Shengyao Xue
Status: Merged
Merged at revision: a8558fa198690dc2b059e269086ba9c012295092
Proposed branch: ~xueshengyao/pc-enablement/+git/oem-scripts:master
Merge into: ~oem-solutions-engineers/pc-enablement/+git/oem-scripts:master
Diff against target: 373 lines (+331/-0)
5 files modified
autoISO.go (+321/-0)
debian/changelog (+6/-0)
debian/control (+1/-0)
debian/install (+1/-0)
debian/rules (+2/-0)
Reviewer Review Type Date Requested Status
jeremyszu Pending
Shih-Yuan Lee Pending
Review via email: mp+407436@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/autoISO.go b/autoISO.go
0new file mode 1006440new file mode 100644
index 0000000..3f7eb72
--- /dev/null
+++ b/autoISO.go
@@ -0,0 +1,321 @@
1// make a auto install OEM ISO from a base OEM ISO image.
2// Usage: autoISO /path/to/oem-xxx.iso
3// Copyright (C) 2021 Canonical Ltd.
4// Author: Shengyao Xue <shengyao.xue@canonical.com>
5//
6// This program is free software; you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program; if not, write to the Free Software
18// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20package main
21
22import (
23 "bytes"
24 "flag"
25 "fmt"
26 "io/ioutil"
27 "os"
28 "os/exec"
29 "os/user"
30 "path/filepath"
31)
32
33func check(e error) {
34 if e != nil {
35 panic(e)
36 }
37}
38
39func fileExists(path string) bool {
40 _, err := os.Stat(path)
41 return err == nil
42}
43
44func main() {
45 if !fileExists("/usr/bin/mksquashfs") {
46 fmt.Println("Please install squashfs-tools package first.")
47 os.Exit(-1)
48 }
49 if !fileExists("/usr/bin/genisoimage") {
50 fmt.Println("Please install genisoimage package first.")
51 os.Exit(-1)
52 }
53
54 extractOnly := flag.Bool("x", false, "extract the base ISO image only.")
55 keepFolder := flag.Bool("k", false, "keep the temporary folder after the new image created.")
56 sanityTest := flag.Bool("s", false, "add first boot sanity test.")
57 flag.Parse()
58
59 currentUser, err := user.Current()
60 check(err)
61 if currentUser.Username != "root" {
62 fmt.Printf("This program requires superuser privileges, please run it as root.\n")
63 os.Exit(-1)
64 }
65 var baseiso string
66 if flag.NArg() == 1 {
67 baseiso = filepath.Clean(flag.Arg(0))
68 } else {
69 fmt.Printf("Usage: autoISO [option] /path/to/oem-xxx.iso\n")
70 fmt.Printf(" -h: help for options.\n")
71 os.Exit(0)
72 }
73
74 parentDir, err := os.Getwd()
75 check(err)
76 fmt.Printf("autoISO started, the artifacts will be created in current working directory: %v\n", parentDir)
77 fmt.Printf("This might take several minutes. Please wait...\n")
78 //autoISODir, err := os.MkdirTemp(parentDir, "autoISO-*")
79 autoISODir, err := ioutil.TempDir(parentDir, "autoISO-*")
80 check(err)
81 check(os.Chdir(autoISODir))
82 check(os.Mkdir("iso", 0775))
83 check(os.Mkdir("squash", 0775))
84 cmd := exec.Command("mount", baseiso, "iso")
85 cmd.Dir = autoISODir
86 check(cmd.Run())
87 cmd = exec.Command("mount", "iso/casper/filesystem.squashfs", "squash")
88 check(cmd.Run())
89 cmd = exec.Command("cp", "-a", "iso", "isorw")
90 check(cmd.Run())
91 cmd = exec.Command("cp", "-a", "squash", "squashrw")
92 check(cmd.Run())
93 cmd = exec.Command("umount", "squash")
94 check(cmd.Run())
95 cmd = exec.Command("umount", "iso")
96 check(cmd.Run())
97 if *extractOnly {
98 fmt.Printf("autoISO extracted only.\n")
99 } else {
100 // oem-config
101 check(os.Mkdir("squashrw/usr/lib/oem-config/pre-install", 0775))
102 preseed := `#!/bin/bash
103cat <<EOF | sudo debconf-communicate ubiquity
104SET passwd/user-fullname u
105FSET passwd/user-fullname seen true
106SET passwd/username u
107FSET passwd/username seen true
108SET passwd/user-password u
109FSET passwd/user-password seen true
110SET passwd/user-password-again u
111FSET passwd/user-password-again seen true
112SET passwd/auto-login true
113FSET passwd/auto-login seen true
114SET time/zone Asia/Shanghai
115FSET time/zone seen true
116EOF
117
118cat <<EOF | sudo debconf-communicate keyboard-configuration
119SET keyboard-configuration/xkb-keymap us
120FSET keyboard-configuration/xkb-keymap seen true
121SET keyboard-configuration/layoutcode us
122FSET keyboard-configuration/layoutcode seen true
123SET keyboard-configuration/layout English (US)
124FSET keyboard-configuration/layout seen true
125SET keyboard-configuration/variant English (US)
126FSET keyboard-configuration/variant seen true
127EOF
128`
129 //check(ioutil.WriteFile("squashrw/usr/lib/oem-config/pre-install/oobe-preseed", []byte(preseed), 0775))
130 check(ioutil.WriteFile("squashrw/usr/lib/oem-config/pre-install/oobe-preseed", []byte(preseed), 0775))
131 grub := "GRUB_CMDLINE_LINUX=$(echo $GRUB_CMDLINE_LINUX automatic-oem-config)\n"
132 check(ioutil.WriteFile("squashrw/etc/default/grub.d/automatic-oem-config.cfg", []byte(grub), 0664))
133
134 // sanity test
135 if *sanityTest {
136 oemDevFirstBoot := `#!/bin/bash
137
138set -x
139
140while true ; do
141 sleep 10
142 ping -c 3 8.8.8.8 && break # ideally wired network works, use it.
143 sleep 10
144 if [ -e /etc/oem-config-hack/connect-wifi ]; then
145 bash /etc/oem-config-hack/connect-wifi
146 else
147 echo Wired network not working and wifi not available, Quit!
148 bash
149 exit
150 fi
151done
152
153if ! dpkg-query -W prepare-checkbox-sanity; then
154 sudo add-apt-repository -y ppa:checkbox-dev/ppa
155 sudo apt install -y prepare-checkbox-sanity
156 sudo reboot
157 exit
158fi
159
160if [ -e ~/.config/autostart/oem-dev-firstboot.desktop ]; then
161 rm ~/.config/autostart/oem-dev-firstboot.desktop
162fi
163
164checkbox-run-plan pc-sanity-smoke-test --checkbox-conf /home/u/.config/checkbox.conf -b
165
166sleep 3
167
168gio open ~/.local/share/checkbox-ng/submission_*.html
169
170bash
171`
172 check(ioutil.WriteFile("squashrw/usr/bin/oem-dev-firstboot", []byte(oemDevFirstBoot), 0775))
173 oemDevFirstBootAutoStart := `#!/bin/bash
174set -x
175mkdir -p "/home/$1/.config/autostart/"
176cat > /home/$1/.config/autostart/oem-dev-firstboot.desktop << EOF
177[Desktop Entry]
178Version=1.0
179Encoding=UTF-8
180Name=Local Sanity
181Type=Application
182Terminal=true
183Exec=/usr/bin/oem-dev-firstboot
184Categories=System;Settings
185EOF
186cat > /home/$1/.config/checkbox.conf <<EOF
187[environment]
188ROUTERS = multiple
189OPEN_N_SSID = ubuntu-cert-n-open
190OPEN_BG_SSID = ubuntu-cert-bg-open
191OPEN_AC_SSID = ubuntu-cert-ac-open
192OPEN_AX_SSID = ubuntu-cert-ax-open
193WPA_N_SSID = ubuntu-cert-n-wpa
194WPA_BG_SSID = ubuntu-cert-bg-wpa
195WPA_AC_SSID = ubuntu-cert-ac-wpa
196WPA_AX_SSID = ubuntu-cert-ax-wpa
197WPA_N_PSK = insecure
198WPA_BG_PSK = insecure
199WPA_AC_PSK = insecure
200WPA_AX_PSK = insecure
201SERVER_IPERF = 192.168.1.99
202TEST_TARGET_IPERF = 192.168.1.99
203BTDEVADDR = 34:13:E8:9A:52:12
204
205# Transfer server
206TRANSFER_SERVER = cdimage.ubuntu.com
207EOF
208touch "/home/$1/.config/gnome-initial-setup-done"
209chown -R "$1.$1" "/home/u/.config"
210`
211 check(ioutil.WriteFile("squashrw/usr/bin/oem-dev-firstboot-autostart", []byte(oemDevFirstBootAutoStart), 0775))
212 oemDevFirstBootPostInstall := `#!/bin/bash
213set -x
214/usr/bin/oem-dev-firstboot-autostart u
215`
216 check(ioutil.WriteFile("squashrw/usr/lib/oem-config/post-install/oem-dev-firstboot", []byte(oemDevFirstBootPostInstall), 0775))
217 }
218 // ubiquity
219 ubiquity, err := ioutil.ReadFile("squashrw/usr/lib/ubiquity/bin/ubiquity")
220 check(err)
221 ubiquity = bytes.Replace(ubiquity, []byte("def run_oem_hooks():\n \"\"\"Run hook scripts from /usr/lib/oem-config/post-install.\"\"\"\n hookdir = '/usr/lib/oem-config/post-install'\n"), []byte("def run_oem_hooks(hookdir):\n \"\"\"Run hook scripts from hookdir.\"\"\""), -1)
222 ubiquity = bytes.Replace(ubiquity, []byte("if oem_config:\n run_oem_hooks()"), []byte("if oem_config:\n run_oem_hooks('/usr/lib/oem-config/post-install')"), -1)
223 ubiquity = bytes.Replace(ubiquity, []byte("if args"), []byte("if oem_config:\n run_oem_hooks('/usr/lib/oem-config/pre-install')\n\n if args"), -1)
224 check(ioutil.WriteFile("squashrw/usr/lib/ubiquity/bin/ubiquity", ubiquity, 0755))
225
226 // recovery
227 recovery, err := ioutil.ReadFile("squashrw/usr/lib/ubiquity/plugins/ubuntu-recovery.py")
228 check(err)
229 // check if this change already landed to ubuntu-recovery package (version >= 0.4.9~20.04ouagadougou22)
230 if !bytes.Contains(recovery, []byte("'UBIQUITY_AUTOMATIC' in os.environ")) {
231 recovery = bytes.Replace(recovery, []byte("os.path.exists(\"/cdrom/.oem/bypass_create_media\")"), []byte("os.path.exists(\"/cdrom/.oem/bypass_create_media\") or ('UBIQUITY_AUTOMATIC' in os.environ)"), -1)
232 check(ioutil.WriteFile("squashrw/usr/lib/ubiquity/plugins/ubuntu-recovery.py", recovery, 0755))
233 }
234
235 // bootstrap
236 bootstrap, err := ioutil.ReadFile("squashrw/usr/lib/ubiquity/plugins/ubuntu-bootstrap.py")
237 check(err)
238 bootstrap = bytes.Replace(bootstrap, []byte("gi.require_version('UDisks', '2.0')\n"), []byte("gi.require_version('UDisks', '2.0')\nfrom gi.repository import GLib\n"), -1)
239 bootstrap = bytes.Replace(bootstrap, []byte("self.interactive_recovery.set_sensitive(False)\n self.automated_recovery.set_sensitive(False)"), []byte("self.interactive_recovery.set_sensitive(False)\n self.automated_recovery.set_sensitive(False)\n if value == \"dev\" and stage == 1:\n self.automated_recovery.set_active(True)\n self.controller.allow_go_forward(True)\n GLib.timeout_add(5000, self.controller.go_forward)\n"), -1)
240 bootstrap = bytes.Replace(bootstrap, []byte("elif rec_type == 'hdd' or rec_type == 'dev':"), []byte("elif rec_type == 'hdd' or (rec_type == 'dev' and self.stage == 2):"), -1)
241 bootstrap = bytes.Replace(bootstrap, []byte("or rec_type == 'hdd' or rec_type == 'dev':"), []byte("or rec_type == 'hdd' or (rec_type == 'dev' and self.stage == 2):"), -1)
242 bootstrap = bytes.Replace(bootstrap, []byte("rpconf.rec_type == \"factory\""), []byte("(rpconf.rec_type == \"factory\" or rpconf.rec_type == \"dev\")"), -1)
243 check(ioutil.WriteFile("squashrw/usr/lib/ubiquity/plugins/ubuntu-bootstrap.py", bootstrap, 0755))
244
245 // user ubuntu, reservation for MAAS, cloud init etc.
246 uUbuntu := `#!/bin/bash
247adduser --disabled-password --gecos "" ubuntu
248adduser ubuntu sudo
249`
250 check(ioutil.WriteFile("squashrw/usr/lib/oem-config/post-install/u-ubuntu", []byte(uUbuntu), 0775))
251
252 // gconf-modification
253 gconfModification := `#!/bin/bash
254cat <<EOF >> /usr/share/glib-2.0/schemas/certification.gschema.override
255[org.gnome.settings-daemon.plugins.power]
256idle-dim=false
257#sleep-display-ac=0
258sleep-inactive-ac-timeout=0
259sleep-inactive-battery-timeout=0
260[org.gnome.desktop.session]
261idle-delay=0
262[org.gnome.desktop.screensaver]
263ubuntu-lock-on-suspend=false
264lock-enabled=false
265idle-activation-enabled=false
266EOF
267
268glib-compile-schemas /usr/share/glib-2.0/schemas
269`
270 check(ioutil.WriteFile("squashrw/usr/lib/oem-config/post-install/gconf-modification", []byte(gconfModification), 0775))
271
272 // disable unattended update of APT
273 oemDisableUattn := `#!/usr/bin/python3
274import softwareproperties
275from softwareproperties import SoftwareProperties
276import os
277
278# given
279# euid,eguid 1000,1000
280# ruid,rguid 0, 0
281# we need to seteuid to 0 so we have permission.
282os.seteuid(0)
283os.setegid(0)
284
285s = SoftwareProperties.SoftwareProperties()
286s.set_update_automation_level(softwareproperties.UPDATE_MANUAL)
287
288print("OK")
289`
290 check(ioutil.WriteFile("squashrw/usr/lib/oem-config/post-install/oem-disable-uattn", []byte(oemDisableUattn), 0775))
291
292 // sudoers
293 sudoers := "%sudo ALL=(ALL:ALL) NOPASSWD: ALL\n"
294 check(ioutil.WriteFile("squashrw/etc/sudoers.d/oem-config-hack-nopwd", []byte(sudoers), 0664))
295
296 // make new squashfs
297 cmd = exec.Command("mksquashfs", "squashrw", "isorw/casper/filesystem.squashfs", "-noappend")
298 check(cmd.Run())
299
300 // projectCfg
301 projectCfg, err := ioutil.ReadFile("isorw/preseed/project.cfg")
302 check(err)
303 // change recovery_type to dev
304 projectCfg = bytes.Replace(projectCfg, []byte("# Hide"), []byte("ubiquity ubuntu-recovery/recovery_type string dev\n\n# Hide"), -1)
305 // change poweroff to reboot
306 projectCfg = bytes.Replace(projectCfg, []byte("ubiquity/reboot boolean false"), []byte("ubiquity/reboot boolean true"), -1)
307 projectCfg = bytes.Replace(projectCfg, []byte("ubiquity/poweroff boolean true"), []byte("ubiquity/poweroff boolean false"), -1)
308 check(ioutil.WriteFile("isorw/preseed/project.cfg", projectCfg, 0755))
309
310 // make new ISO
311 cmd = exec.Command("genisoimage", "-J", "-l", "-cache-inodes", "-allow-multidot", "-r", "-input-charset", "utf-8", "-eltorito-alt-boot", "-efi-boot", "boot/grub/efi.img", "-no-emul-boot", "-o", parentDir+"/"+filepath.Base(baseiso)+"."+filepath.Base(autoISODir)+".iso", "isorw")
312 check(cmd.Run())
313
314 if !*keepFolder {
315 check(os.RemoveAll(autoISODir))
316 fmt.Printf("autoISO done.\n")
317 } else {
318 fmt.Printf("autoISO done. Temporary folder %v keeped.\n", autoISODir)
319 }
320 }
321}
diff --git a/debian/changelog b/debian/changelog
index 38037d5..049e0a6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
1oem-scripts (1.9) focal; urgency=medium
2
3 * Add autoISO.go to oem-scripts.
4
5 -- Shengyao Xue <shengyao.xue@canonical.com> Fri, 20 Aug 2021 16:04:49 +0800
6
1oem-scripts (1.8) focal; urgency=medium7oem-scripts (1.8) focal; urgency=medium
28
3 * debian/tests/mir-bug,9 * debian/tests/mir-bug,
diff --git a/debian/control b/debian/control
index 7ef7aa5..2427bba 100644
--- a/debian/control
+++ b/debian/control
@@ -6,6 +6,7 @@ Build-Depends:
6 debhelper (>=11),6 debhelper (>=11),
7 dh-python,7 dh-python,
8 flake8,8 flake8,
9 golang-go,
9 python3-all,10 python3-all,
10 python3-debian,11 python3-debian,
11 python3-launchpadlib,12 python3-launchpadlib,
diff --git a/debian/install b/debian/install
12new file mode 10064413new file mode 100644
index 0000000..b1f5851
--- /dev/null
+++ b/debian/install
@@ -0,0 +1 @@
1autoISO /usr/sbin/
diff --git a/debian/rules b/debian/rules
index 98284ec..02ab8ad 100755
--- a/debian/rules
+++ b/debian/rules
@@ -3,6 +3,8 @@
33
4%:4%:
5 dh $@ --with python3 --buildsystem=pybuild5 dh $@ --with python3 --buildsystem=pybuild
6 go build autoISO.go
7 strip autoISO
68
7override_dh_auto_test:9override_dh_auto_test:
8 ./tests/test_black10 ./tests/test_black

Subscribers

People subscribed via source and target branches