diff -Nru goget-ubuntu-touch-0.4+15.04.20141121/debian/changelog goget-ubuntu-touch-0.4+15.04.20141125/debian/changelog --- goget-ubuntu-touch-0.4+15.04.20141121/debian/changelog 2014-11-25 23:54:12.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/debian/changelog 2014-11-25 23:54:13.000000000 +0000 @@ -1,3 +1,14 @@ +goget-ubuntu-touch (0.4+15.04.20141125-0ubuntu1) vivid; urgency=low + + [ Sergio Schvezov ] + * ubuntu-emulator: allow setting a default password for the phablet + user when creating (LP: #1390476) + * ubuntu-emulator: fixing password setup for phablet user when setting + up an armhf instance (LP: #1393398) + * ubuntu-device-flash: dual images for core + + -- Ubuntu daily release Tue, 25 Nov 2014 23:51:15 +0000 + goget-ubuntu-touch (0.4+15.04.20141121-0ubuntu1) vivid; urgency=low [ Sergio Schvezov ] diff -Nru goget-ubuntu-touch-0.4+15.04.20141121/debian/control goget-ubuntu-touch-0.4+15.04.20141125/debian/control --- goget-ubuntu-touch-0.4+15.04.20141121/debian/control 2014-11-25 23:54:12.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/debian/control 2014-11-25 23:54:13.000000000 +0000 @@ -43,6 +43,7 @@ ${misc:Depends}, ${shlibs:Depends}, Recommends: android-tools-adb, + qemu-user-static, Built-Using: ${misc:Built-Using} Description: Create and run emulator images of Ubuntu Touch Create and destroy Ubuntu Touch instances and run them with the emulator diff -Nru goget-ubuntu-touch-0.4+15.04.20141121/diskimage/customization.go goget-ubuntu-touch-0.4+15.04.20141125/diskimage/customization.go --- goget-ubuntu-touch-0.4+15.04.20141121/diskimage/customization.go 2014-11-21 11:32:37.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/diskimage/customization.go 2014-11-25 23:50:53.000000000 +0000 @@ -20,11 +20,9 @@ // with this program. If not, see . import ( - "errors" "fmt" "io/ioutil" "os" - "os/exec" "path/filepath" ) @@ -85,14 +83,3 @@ writeFlag := filepath.Join(img.Mountpoint, ".adb_onlock") return ioutil.WriteFile(writeFlag, []byte(""), 0644) } - -//SetPassword is an ugly hack to set the password -func (img DiskImage) SetPassword(user, password string) error { - // Run something that would look like this - // PATH=$path chroot "$SYSTEM_MOUNTPOINT" /bin/sh -c "echo -n "$user:$password" | chpasswd" - chrootCmd := fmt.Sprintf("echo -n '%s:%s' | chpasswd", user, password) - if out, err := exec.Command("chroot", img.Mountpoint, "/bin/sh", "-c", chrootCmd).CombinedOutput(); err != nil { - return errors.New(string(out)) - } - return nil -} diff -Nru goget-ubuntu-touch-0.4+15.04.20141121/diskimage/image.go goget-ubuntu-touch-0.4+15.04.20141125/diskimage/image.go --- goget-ubuntu-touch-0.4+15.04.20141121/diskimage/image.go 2014-11-21 11:32:37.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/diskimage/image.go 2014-11-25 23:51:02.000000000 +0000 @@ -37,13 +37,15 @@ type directory string const ( - systemDataLabel imageLabel = "system-data" - userDataLabel imageLabel = "user-data" + systemDataLabel imageLabel = "system-data" + systemDataLabel2 imageLabel = "system-data-2" + userDataLabel imageLabel = "user-data" ) const ( - systemDataDir directory = "system" - userDataDir directory = "user-data" + systemDataDir directory = "system" + systemDataDir2 directory = "system-2" + userDataDir directory = "user-data" ) type partition struct { @@ -128,16 +130,19 @@ } //System returns the system path -func (img *DiskImage) System() (string, error) { +func (img *DiskImage) System() ([]string, error) { if img.parts == nil { - return "", errors.New("img is not setup with partitions") + return nil, errors.New("img is not setup with partitions") } if img.Mountpoint == "" { - return "", errors.New("img not mounted") + return nil, errors.New("img not mounted") } - return filepath.Join(img.Mountpoint, string(systemDataDir)), nil + return []string{ + filepath.Join(img.Mountpoint, string(systemDataDir)), + filepath.Join(img.Mountpoint, string(systemDataDir2)), + }, nil } //Mount the DiskImage @@ -245,7 +250,7 @@ } //Partition creates a partitioned image from an img -func (img *DiskImage) Partition() error { +func (img *DiskImage) Partition(dual bool) error { if err := sysutils.CreateEmptyFile(img.path, img.size); err != nil { return err } @@ -257,17 +262,22 @@ } stdin.Write([]byte("mklabel msdos\n")) - stdin.Write([]byte("mkpart primary ext4 2048s 4G\n")) - stdin.Write([]byte("mkpart primary ext4 4G -1s\n")) + stdin.Write([]byte("mkpart primary ext4 2048s 3905535s\n")) + if dual { + stdin.Write([]byte("mkpart primary ext4 3905536s 7809023s\n")) + stdin.Write([]byte("mkpart primary ext4 7809024s -1s\n")) + } else { + stdin.Write([]byte("mkpart primary ext4 3905536s -1s\n")) + } stdin.Write([]byte("set 1 boot on\n")) - stdin.Write([]byte("print\n")) + stdin.Write([]byte("unit s print\n")) stdin.Write([]byte("quit\n")) return partedCmd.Run() } //MapPartitions creates loop devices for the partitions -func (img *DiskImage) MapPartitions() error { +func (img *DiskImage) MapPartitions(dual bool) error { kpartxCmd := exec.Command("kpartx", "-avs", img.path) stdout, err := kpartxCmd.StdoutPipe() if err != nil { @@ -278,10 +288,11 @@ return err } - loops := make([]string, 0, 2) + loops := make([]string, 0, 3) scanner := bufio.NewScanner(stdout) for scanner.Scan() { fields := strings.Fields(scanner.Text()) + if len(fields) > 2 { loops = append(loops, fields[2]) } else { @@ -292,13 +303,26 @@ return err } - if len(loops) != 2 { + expectedLoops := 2 + if dual { + expectedLoops = 3 + } + + if len(loops) != expectedLoops { return errors.New("more partitions then expected while creating loop mapping") } - img.parts = []partition{ - partition{label: systemDataLabel, dir: systemDataDir, loop: loops[0]}, - partition{label: userDataLabel, dir: userDataDir, loop: loops[1]}, + if dual { + img.parts = []partition{ + partition{label: systemDataLabel, dir: systemDataDir, loop: loops[0]}, + partition{label: systemDataLabel2, dir: systemDataDir2, loop: loops[1]}, + partition{label: userDataLabel, dir: userDataDir, loop: loops[2]}, + } + } else { + img.parts = []partition{ + partition{label: systemDataLabel, dir: systemDataDir, loop: loops[0]}, + partition{label: userDataLabel, dir: userDataDir, loop: loops[1]}, + } } if err := kpartxCmd.Wait(); err != nil { diff -Nru goget-ubuntu-touch-0.4+15.04.20141121/ubuntu-device-flash/core.go goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-device-flash/core.go --- goget-ubuntu-touch-0.4+15.04.20141121/ubuntu-device-flash/core.go 2014-11-21 11:32:47.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-device-flash/core.go 2014-11-25 23:51:02.000000000 +0000 @@ -53,6 +53,7 @@ Output string `long:"output" short:"o" description:"Name of the image file to create" required:"true"` Size int64 `long:"size" short:"s" description:"Size of image file to create in GB (min 6)" default:"20"` DeveloperMode bool `long:"developer-mode" description:"Finds the latest public key in your ~/.ssh and sets it up"` + Dual bool `long:"dual-images" description:"Sets up two images to upgrade with providing rollback support"` } var coreCmd CoreCmd @@ -127,7 +128,7 @@ }() img := diskimage.New(coreCmd.Output, "", coreCmd.Size) - if err := img.Partition(); err != nil { + if err := img.Partition(coreCmd.Dual); err != nil { return err } defer func() { @@ -176,7 +177,7 @@ } func (coreCmd *CoreCmd) partition(img *diskimage.DiskImage) error { - if err := img.MapPartitions(); err != nil { + if err := img.MapPartitions(coreCmd.Dual); err != nil { return fmt.Errorf("issue while mapping partitions: %s", err) } defer img.UnMapPartitions() @@ -185,7 +186,7 @@ } func (coreCmd *CoreCmd) setup(img *diskimage.DiskImage, filePathChan <-chan string) error { - if err := img.MapPartitions(); err != nil { + if err := img.MapPartitions(coreCmd.Dual); err != nil { return err } defer img.UnMapPartitions() @@ -201,24 +202,25 @@ } } - systemPath, err := img.System() + systemPaths, err := img.System() if err != nil { return err } - if err := coreCmd.setupBootloader(systemPath); err != nil { - return err - } - - if err := coreCmd.setupKeyboardLayout(systemPath); err != nil { - return err - } - userPath, err := img.User() if err != nil { return err } + if coreCmd.Dual { + src := fmt.Sprintf("%s/system/.", img.Mountpoint) + dst := fmt.Sprintf("%s/system-2", img.Mountpoint) + cmd := exec.Command("cp", "-r", "--preserve=all", src, dst) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("failed to replicate image contents: %s", out) + } + } + for _, dir := range []string{"system-data", "cache"} { dirPath := filepath.Join(userPath, dir) if err := os.Mkdir(dirPath, 0755); err != nil { @@ -226,8 +228,18 @@ } } - if err := coreCmd.setupCloudInit(systemPath, filepath.Join(userPath, "system-data")); err != nil { - return err + for i := range systemPaths { + if err := coreCmd.setupBootloader(systemPaths[i]); err != nil { + return err + } + + if err := coreCmd.setupKeyboardLayout(systemPaths[i]); err != nil { + return err + } + + if err := coreCmd.setupCloudInit(systemPaths[i], filepath.Join(userPath, "system-data")); err != nil { + return err + } } return nil diff -Nru goget-ubuntu-touch-0.4+15.04.20141121/ubuntu-emulator/create.go goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-emulator/create.go --- goget-ubuntu-touch-0.4+15.04.20141121/ubuntu-emulator/create.go 2014-11-21 11:32:37.000000000 +0000 +++ goget-ubuntu-touch-0.4+15.04.20141125/ubuntu-emulator/create.go 2014-11-25 23:50:53.000000000 +0000 @@ -23,6 +23,7 @@ "errors" "fmt" "os" + "os/exec" "path/filepath" "runtime" "syscall" @@ -39,6 +40,7 @@ RawDisk bool `long:"use-raw-disk" description:"Use raw disks instead of qcow2"` SDCard bool `long:"with-sdcard" description:"Create an external vfat sdcard"` Arch string `long:"arch" description:"Device architecture to use (i386 or armhf)"` + Password string `long:"password" description:"This sets up the default password for the phablet user" default:"0000"` } var createCmd CreateCmd @@ -49,6 +51,11 @@ defaultArch = "i386" ) +const ( + binQemuArmStatic = "/usr/bin/qemu-arm-static" + pkgQemuUserStatic = "qemu-user-static" +) + func init() { createCmd.Arch = defaultArch createCmd.Channel = defaultChannel @@ -66,6 +73,10 @@ } instanceName := args[0] + if err := createCmd.verifyDependencies(); err != nil { + return err + } + var device string if d, ok := devices[createCmd.Arch]; ok { device = d["name"] @@ -118,7 +129,7 @@ sdcardImage := diskimage.New(filepath.Join(dataDir, "sdcard.img"), "USERDATA", 4) systemImage := diskimage.NewExisting(filepath.Join(dataDir, "system.img")) - if err := createSystem(ubuntuImage, sdcardImage, files); err != nil { + if err := createCmd.createSystem(ubuntuImage, sdcardImage, files); err != nil { return err } @@ -179,7 +190,18 @@ return systemImage.ExtractFile("build.prop", filepath.Join(dataDir, "system")) } -func createSystem(ubuntuImage, sdcardImage *diskimage.DiskImage, files []string) (err error) { +func (createCmd *CreateCmd) verifyDependencies() error { + switch createCmd.Arch { + case "armhf": + if _, err := os.Stat(binQemuArmStatic); err != nil { + return fmt.Errorf("missing dependency %s (apt install %s)", binQemuArmStatic, pkgQemuUserStatic) + } + } + + return nil +} + +func (createCmd *CreateCmd) createSystem(ubuntuImage, sdcardImage *diskimage.DiskImage, files []string) (err error) { for _, img := range []*diskimage.DiskImage{ubuntuImage, sdcardImage} { if err := img.CreateExt4(); err != nil { return err @@ -205,13 +227,15 @@ } return err } - fmt.Println("Setting up a default password for phablet to: '0000'") - if err := ubuntuImage.SetPassword("phablet", "0000"); err != nil { + + fmt.Printf("Setting up a default password for phablet to: '%s'\n", createCmd.Password) + if err := createCmd.setPassword(ubuntuImage.Mountpoint); err != nil { if err := ubuntuImage.Unmount(); err != nil { fmt.Println("Unmount error :", err) } return err } + if err := ubuntuImage.Unmount(); err != nil { return err } @@ -230,6 +254,25 @@ } return nil } + +// setPassword is an ugly hack to set the password +func (createCmd *CreateCmd) setPassword(chroot string) error { + if createCmd.Arch == "armhf" { + dst := filepath.Join(chroot, binQemuArmStatic) + if out, err := exec.Command("cp", binQemuArmStatic, dst).CombinedOutput(); err != nil { + return fmt.Errorf("issues while setting up password: %s", out) + } + defer os.Remove(dst) + } + + // Run something that would look like this + // PATH=$path chroot "$SYSTEM_MOUNTPOINT" /bin/sh -c "echo -n "$user:$password" | chpasswd" + chrootCmd := fmt.Sprintf("echo -n '%s:%s' | chpasswd", "phablet", createCmd.Password) + if out, err := exec.Command("chroot", chroot, "/bin/sh", "-c", chrootCmd).CombinedOutput(); err != nil { + return errors.New(string(out)) + } + return nil +} func download(image ubuntuimage.Image) (files []string, err error) { cacheDir := ubuntuimage.GetCacheDir()