M .gitignore => .gitignore +3 -0
@@ 1,5 1,8 @@
*.iso
*.img
+*.pub
+*.sec
+builds/
metadata.json
temp/
linux-gen
A assets/04081_lagoonnebula_1920x1080-attrib.txt => assets/04081_lagoonnebula_1920x1080-attrib.txt +21 -0
@@ 0,0 1,21 @@
+https://interfacelift.com/wallpaper/details/4081/lagoon_nebula.html
+
+
+Lagoon Nebula
+By Dominic Kamp
+October 25th, 2016
+
+Taken from Gornergrad, a rocky ridge of the Pennine Alps, overlooking the
+Gorner Glacier south-east of Zermatt in Switzerland.
+
+I was like standing there and then like woah, all of a sudden there was this
+cloud reaching out and then it was like lit from below and I was like SNAP boom
+into my camera.
+
+Moon for lighting, Photoshop, Manfrotto tripod, gloves.
+
+Nikon D800, Nikon AF-S NIKKOR 14-24mm f/2.8G ED.
+
+Photo Settings: 19mm, f/2, 25 seconds, ISO 100.
+
+Map: 45.9833, 7.7847
A assets/04081_lagoonnebula_1920x1080.png => assets/04081_lagoonnebula_1920x1080.png +0 -0
A assets/lubuntu-calamares.desktop => assets/lubuntu-calamares.desktop +11 -0
@@ 0,0 1,11 @@
+[Desktop Entry]
+Type=Application
+Version=1.0
+Name=Install To Disk
+Exec=bash -c "export BROWSER='sudo -H -u lubuntu firefox'; sudo -E calamares"
+Comment=Calamares — System Installer
+Icon=calamares
+Terminal=false
+StartupNotify=true
+Categories=Qt;System;
+Keywords=installer;calamares;system;
A assets/splash.pcx => assets/splash.pcx +0 -0
A assets/splash.png => assets/splash.png +0 -0
M builder/build.go => builder/build.go +6 -1
@@ 26,6 26,7 @@ func build(sess *buildSession) error {
return errors.Wrap(err, "chmod filesystem manifest")
}
+ setProgress(sess, "Building: Creating filesystem manifest", 10)
{ // write filesystem.manifest
output, err := execc(sess.tempDir, "chroot", sess.chrootDir, "dpkg-query",
"-W", "--showformat='${Package} ${Version}\\n'")
@@ 59,6 60,7 @@ func build(sess *buildSession) error {
// TODO remove from the manifest (desktop) the calamares and casper
// packages
+ setProgress(sess, "Building: Making squashfs file", 11)
config.Logger.Debug("build: mksquashfs")
o, err := execc("", "mksquashfs",
sess.chrootDir, sess.extractDir+"/casper/filesystem.squashfs",
@@ 67,6 69,7 @@ func build(sess *buildSession) error {
return errors.Wrap(err, "mksquashfs "+string(o))
}
+ setProgress(sess, "Building: Calculating system size", 12)
{ // write filesystem.size
size, err := exec.Command("du", "-sx", "--block-size=1", sess.chrootDir).Output()
if err != nil {
@@ 95,6 98,7 @@ func build(sess *buildSession) error {
config.Logger.Debug("build: hashes")
var hashes strings.Builder
+ setProgress(sess, "Building: Calculating file hashes", 13)
err = filepath.Walk(sess.extractDir,
func(path string, info os.FileInfo, err error) error {
@@ 108,7 112,7 @@ func build(sess *buildSession) error {
return err
}
- hashes.WriteString(strings.Replace(string(hash), sess.extractDir, "", -1))
+ hashes.WriteString("." + strings.Replace(string(hash), sess.extractDir, "", -1))
}
return nil
})
@@ 130,6 134,7 @@ func build(sess *buildSession) error {
}
}
+ setProgress(sess, "Building: Creating .iso file", 14)
config.Logger.Debug("build: xorriso")
xorriso := exec.Command("xorriso", "-as", "mkisofs",
"-r", "-V", sess.cust.DistName+" "+sess.cust.DistVer+" amd64",
M builder/builder.go => builder/builder.go +25 -2
@@ 6,6 6,7 @@ import (
"io"
"os"
"os/exec"
+ "strconv"
"strings"
"git.sr.ht/~humaid/linux-gen/config"
@@ 51,6 52,19 @@ type SystemMetadata struct {
Timezones []string
}
+var maxProg int = 16
+
+func setProgress(sess *buildSession, status string, prog int) {
+ mkdir("./builds")
+ mkdir("./builds/" + sess.cust.AuthorID)
+ if maxProg == prog || maxProg == -1 {
+ writeToFile("./builds/"+sess.cust.AuthorID+"/prog", "Complete")
+ } else {
+ tot := int((float64(prog) / float64(maxProg)) * 100)
+ writeToFile("./builds/"+sess.cust.AuthorID+"/prog", status+" ("+strconv.Itoa(tot)+"%)")
+ }
+}
+
func GetMetadata() (SystemMetadata, error) {
var err error
@@ 202,6 216,7 @@ func Start(cust Customisation) (string, error) {
cust: cust,
}
+ setProgress(&sess, "Preparing...", 1)
if _, err := os.Stat(dir); err == nil {
cleanup(&sess)
}
@@ 218,6 233,7 @@ func Start(cust Customisation) (string, error) {
cleanup(&sess)
return "", err
}
+ setProgress(&sess, "Customising", 5)
config.Logger.Debug("start customise")
err = customise(&sess)
@@ 230,7 246,10 @@ func Start(cust Customisation) (string, error) {
cleanup(&sess)
return "", err
}
+ config.Logger.Debug("Will build after press enter")
+ fmt.Scanln()
+ setProgress(&sess, "Building", 9)
config.Logger.Debug("start build")
err = build(&sess)
if err != nil {
@@ 243,12 262,16 @@ func Start(cust Customisation) (string, error) {
return "", err
}
+ setProgress(&sess, "Finalising...", 15)
mkdir("./builds")
mkdir("./builds/" + cust.AuthorID)
os.Remove("./builds/final.iso")
_, err = exec.Command("cp", sess.tempDir+"/output.iso", "./builds/"+cust.AuthorID+"/final.iso").Output()
+ o, _ := execc("./builds/"+cust.AuthorID+"/final.iso", "sha256sum", "final.iso")
+ writeToFile("./builds/"+cust.AuthorID+"/sha256sum.txt", o)
cleanup(&sess)
+ setProgress(&sess, "Complete", 16)
return "", nil
}
@@ 274,8 297,8 @@ func cleanup(sess *buildSession) {
}
}
- //config.Logger.Debug("Will remove all when press enter")
- //fmt.Scanln()
+ config.Logger.Debug("Will remove all when press enter")
+ fmt.Scanln()
os.RemoveAll(sess.tempDir)
}
M builder/customise.go => builder/customise.go +15 -0
@@ 22,6 22,8 @@ func sedFile(file string, pattern string) error {
func customise(sess *buildSession) error {
var date = time.Now().Format(DATE)
+ setProgress(sess, "Customising: Applying Branding", 6)
+
sedFile(sess.extractDir+"/isolinux/txt.cfg", "s/Lubuntu/"+sess.cust.DistName+"/g")
sedFile(sess.extractDir+"/boot/grub/grub.cfg", "s/Lubuntu/"+sess.cust.DistName+"/g")
sedFile(sess.extractDir+"/boot/grub/loopback.cfg", "s/Lubuntu/"+sess.cust.DistName+"/g")
@@ 59,6 61,7 @@ UBUNTU_CODENAME=focal`)
"s/lubuntu\\.me/humaidq\\.ae/g")
// Install packages
+ setProgress(sess, "Customising: Creating build script", 7)
if err := buildCustomiseScript(sess); err != nil {
return errors.Wrap(err, "build customise script")
}
@@ 67,6 70,7 @@ UBUNTU_CODENAME=focal`)
os.Remove(sess.chrootDir + "/etc/resolv.conf")
os.Remove(sess.chrootDir + "/var/lib/dpkg/statoverride")
writeToFile(sess.chrootDir+"/etc/resolv.conf", "nameserver 8.8.8.8")
+ setProgress(sess, "Customising: Mouting partitions", 7)
// mount /dev
_, err := execc(sess.tempDir, "mount", "--bind", "/dev/", sess.chrootDir+"/dev")
@@ 74,10 78,19 @@ UBUNTU_CODENAME=focal`)
return errors.Wrap(err, "mount /dev for chroot")
}
+ setProgress(sess, "Customising: Installing packages and applying customisations", 8)
if _, err := execc(sess.tempDir, "chroot", sess.chrootDir, "/bin/bash", "/root/cust.sh"); err != nil {
return errors.Wrap(err, "chroot customise script")
}
+ // copy over pictures
+ wd, _ := os.Getwd()
+ execc(wd, "cp", "-f", "./assets/splash.pcx", sess.extractDir+"/isolinux/")
+ execc(wd, "cp", "-f", "./assets/splash.png", sess.extractDir+"/isolinux/")
+ execc(wd, "cp", "-f", "./assets/lubuntu-calamares.desktop", sess.chrootDir+"/usr/share/applications/lubuntu-calamares.desktop")
+ execc(wd, "chmod", "+x", sess.chrootDir+"/usr/share/applications/lubuntu-calamares.desktop")
+ execc(wd, "cp", "-f", "./assets/04081_lagoonnebula_1920x1080.png", sess.chrootDir+"/usr/share/lubuntu/wallpapers/lubuntu-default-wallpaper.png")
+
umount(sess.chrootDir + "/dev")
return nil
@@ 110,6 123,8 @@ apt update
sh.WriteString("apt autoremove --purge -y\n")
+ sh.WriteString(sess.cust.Script + "\n")
+
sh.WriteString(`umount /proc
umount /sys
umount /dev/pts
M => +4 -0
@@ 40,6 40,7 @@ func extract(sess *buildSession) error {
mkdir(sess.mountDir)
mkdir(sess.extractDir)
setProgress(sess, "Extracting: mounting ISO", 2)
config.Logger.Debug("extract: mount ISO")
// mount the ISO file
_, err = exec.Command("mount", "-o", "loop", config.Config.OrigISOFile,
@@ 50,6 51,7 @@ func extract(sess *buildSession) error {
config.Logger.Debug(sess.mountDir, sess.extractDir)
config.Logger.Debug("extract: rsync")
setProgress(sess, "Extracting: rsync", 3)
// copy contents to extract folder
o, err := execc("", "rsync", "--exclude=/casper/filesystem.squashfs",
@@ 59,12 61,14 @@ func extract(sess *buildSession) error {
//return errors.Wrap(err, "copy contents (rsync) "+o)
}
setProgress(sess, "Extracting: unsquashfs", 3)
config.Logger.Debug("extract: unsquashfs")
o, err = execc(sess.tempDir, "unsquashfs",
sess.mountDir+"/casper/filesystem.squashfs")
if err != nil {
return errors.Wrap(err, "unsquashfs: "+o)
}
setProgress(sess, "Extracting: unmounting and cleaning up", 4)
os.Rename(sess.tempDir+"/squashfs-root", sess.chrootDir)
A builds/web/prog => builds/web/prog +1 -0
@@ 0,0 1,1 @@
+Complete<
\ No newline at end of file
M cmd/start.go => cmd/start.go +1 -1
@@ 62,7 62,7 @@ func start(clx *cli.Context) (err error) {
m.Get("/pkgs/sel", routes.SelectPackageHandler)
m.Get("/build", routes.BuildHandler)
m.Post("/build", routes.BuildHandler)
- m.Get("/download/:name.iso", routes.DownloadHandler)
+ m.Get("/download/:name", routes.DownloadHandler)
log.Printf("Starting web server on port %s\n", config.Config.SitePort)
log.Fatal(http.ListenAndServe(fmt.Sprintf("0.0.0.0:%s", config.Config.SitePort), m))
A key.txt => key.txt +1 -0
@@ 0,0 1,1 @@
+ieje2ieWash8Yohd
M routes/home.go => routes/home.go +16 -1
@@ 39,7 39,16 @@ func DownloadHandler(ctx *macaron.Context, sess session.Store) {
sessData = s.(sessionData)
}
ctx.Data["sess"] = sessData
- ctx.ServeFile("./builds/web/final.iso")
+ name := ctx.Params("name")
+ switch name {
+ case "final.iso":
+ ctx.ServeFile("./builds/web/final.iso")
+ case "sha256sum.txt":
+ ctx.ServeFile("./builds/web/sha256sum.txt")
+ case "sha256sum.sig":
+ ctx.ServeFile("./builds/web/sha256sum.sig")
+ }
+ ctx.PlainText(400, []byte("invalid file"))
}
type packageAction int
@@ 378,6 387,12 @@ func BuildHandler(ctx *macaron.Context, sess session.Store) {
return
}
+ if a, err := ioutil.ReadFile("./builds/web/prog"); err == nil {
+ if string(a) != "Complete" {
+ ctx.Data["Progress"] = string(a)
+ }
+ }
+
if stat, err := os.Stat("./builds/web/final.iso"); err == nil && !stat.IsDir() {
ctx.Data["HasBuild"] = true
ctx.Data["BuildTime"] = stat.ModTime().Format("2 January 2006 3:04pm")
M templates/build.html => templates/build.html +12 -1
@@ 1,5 1,8 @@
{{ template "partials/header" .}}
{{ template "partials/configbar" . }}
+{{if .Progress}}
+<meta http-equiv="refresh" content="1">
+{{end}}
<h2>Build</h2>
<p>Once you have completed customising your system above, you may build your
system.</p>
@@ 7,7 10,11 @@ system.</p>
<p>Ready to build {{.sess.Name}} {{.sess.Version}}. Visit configuration page to
adjust version.</p>
<form method="post">
+ {{if .Progress}}
+ <p><b>Build in progress:</b> {{.Progress}}</p>
+ {{else}}
<p><button type="submit" class="btn">Build ISO</button></p>
+ {{end}}
</form>
<h3>Builds</h3>
@@ 25,7 32,11 @@ adjust version.</p>
<td>{{.sess.Name}} build</td>
<td>{{.BuildTime}}</td>
<td>{{.BuildSize}} GB</td>
- <td><a href="/download/final.iso" class="btn">Download</a></td>
+ <td>
+ <a href="/download/final.iso" class="btn">Download</a>
+ <a href="/download/sha256sum.txt" class="btn">Hash</a>
+ <a href="/download/sha256sum.sig" class="btn">Sig</a>
+ </td>
</tr>
{{else}}
<tr>
M => +1 -2
@@ 2,8 2,7 @@
</div>
<div class="footer">
<p><a rel="noopener noreferrer" href="/">CSLDG</a> is part of a research
project by Humaid AlQassimi at Heriot-Watt University. This is a
prototype.</p>
project by Humaid AlQassimi at Heriot-Watt University.</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/js/all.min.js" integrity="sha512-RXf+QSDCUQs5uwRKaDoXt55jygZZm2V++WUZduaU/Ui/9EGp3f/2KZVahFZBKGH0s774sd3HmrhUy+SgOFQLVQ==" crossorigin="anonymous"></script>
</body>