Add command to build images 66/466/10
authorYolanda Robla <yroblamo@redhat.com>
Wed, 13 Mar 2019 12:39:59 +0000 (13:39 +0100)
committerYolanda Robla <yroblamo@redhat.com>
Fri, 15 Mar 2019 12:29:22 +0000 (13:29 +0100)
Change-Id: I8a01b72c78555d4af899856637e1f49a940e36ad

Makefile
README.md
cmd/images.go [new file with mode: 0644]

index 8998dc9..46095c9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,7 @@ GONAME="kni-edge-installer"
 
 BUILDDIR = $(shell pwd)/build
 INSTALLER_GIT_REPO = github.com/openshift/installer
+RHCOS_VERSION = "maipo"
 
 ifndef INSTALLER_PATH
 override INSTALLER_PATH = https://github.com/openshift/installer/releases/download/v0.14.0/openshift-install-linux-amd64
@@ -25,19 +26,24 @@ build:
        @echo "Building kni-edge-installer with $(GOPATH) to ./bin"
        @GOPATH=$(GOPATH) GOBIN=$(GOBIN) go build -o bin/$(GONAME) $(GOFILES)
 
-deploy:
-       @echo "Launching cluster deployment bin/$(GONAME)"
-       @./bin/$(GONAME) generate --installer_path $(INSTALLER_PATH) --build_path $(BUILDDIR) --base_repository $(BASE_REPO) --base_path $(BASE_PATH) --secrets_repository $(CREDENTIALS) --site_repository $(SITE_REPO) --settings_path $(SETTINGS_PATH)
-
 clean:
        @echo "Destroying previous cluster"
        @./bin/$(GONAME) clean --build_path $(BUILDDIR)
 
+deploy:
+       @echo "Launching cluster deployment bin/$(GONAME)"
+       @./bin/$(GONAME) generate --installer_path $(INSTALLER_PATH) --build_path $(BUILDDIR) --base_repository $(BASE_REPO) --base_path $(BASE_PATH) --secrets_repository $(CREDENTIALS) --site_repository $(SITE_REPO) --settings_path $(SETTINGS_PATH) --master_memory_mb $(MASTER_MEMORY_MB)
+
+images:
+       @echo "Launching image generation"
+       @./bin/$(GONAME) images --build_path $(BUILDDIR) --version $(RHCOS_VERSION)
+
 help:
        @echo "Please use \`make <target>' where <target> is one of"
        @echo "  binary to generate a new openshift-install binary"
        @echo "  build to produce the installer binary"
        @echo "  clean to destroy a previously created cluster and remove build contents"
-       @echo "  deploy CREDENTIALS=<github_secret_repo> BASE_REPO=<github_manifests_repo> BASE_PATH=<subpath_on_manifests_repo> SITE_REPO=<github_site_repo> SETTINGS_PATH=<subpath_on_site_repo>
+       @echo "  deploy CREDENTIALS=<github_secret_repo> BASE_REPO=<github_manifests_repo> BASE_PATH=<subpath_on_manifests_repo> SITE_REPO=<github_site_repo> SETTINGS_PATH=<subpath_on_site_repo>"
+       @echo "  images to download baremetal images"
 
 .PHONY: build get install run watch start stop restart clean
index 98dd723..90a3a9f 100644 (file)
--- a/README.md
+++ b/README.md
@@ -163,3 +163,18 @@ can be modified with the desired values. After that this code can be executed to
 generate a new cluster based on the modified manifests:
 
     /path/to/openshift-install create cluster
+
+## How to create images (WIP)
+
+For the installer to work on baremetal, it needs a different type of images: installer image (kernel, ramdisk), and the deployment image (raw). To generate the images please execute:
+
+    make images
+
+<<<<<<< HEAD
+=======
+By default it will generate RHCOS Maipo images. But ootpa can be generated by:
+
+    make images RHCOS_VERSION=ootpa
+
+>>>>>>> 10f8945... Add command to build images
+And this will leave the needed images inside your build directory. Those can be used later for a baremetal deploy.
diff --git a/cmd/images.go b/cmd/images.go
new file mode 100644 (file)
index 0000000..f042e66
--- /dev/null
@@ -0,0 +1,175 @@
+// Copyright © 2019 Red Hat <yroblamo@redhat.com>
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cmd
+
+import (
+       "bytes"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "log"
+       "os"
+       "os/exec"
+
+       "github.com/spf13/cobra"
+)
+
+// UmountDirectory will umount the ISO directory
+func UmountDirectory(mountPath string) {
+       cmd := exec.Command("sudo", "umount", mountPath)
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               log.Fatal(fmt.Sprintf("Error umounting directory: %s - %s", err, string(out)))
+               os.Exit(1)
+       }
+
+       // remove mount directory
+       os.RemoveAll(mountPath)
+}
+
+// ExtractIsoFiles will extract vmlinuz and initramfs from a given ISO
+func ExtractIsoFiles(isoPath string, buildPath string) {
+       // once there, mount it
+       mountPath := fmt.Sprintf("%s/iso_mount", buildPath)
+       os.RemoveAll(mountPath)
+       os.MkdirAll(mountPath, 0775)
+
+       // mount iso into that directory
+       log.Println("Extracting image content")
+       cmd := exec.Command("sudo", "mount", "-o", "loop", isoPath, mountPath)
+       cmd.Dir = buildPath
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               log.Fatal(fmt.Sprintf("Error creating manifests: %s - %s", err, string(out)))
+               os.Exit(1)
+       }
+
+       // copy the images to the build directory
+       cmd = exec.Command("cp", fmt.Sprintf("%s/vmlinuz", mountPath), buildPath)
+       cmd.Dir = buildPath
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               log.Fatal(fmt.Sprintf("Error copying vmlinuz: %s - %s", err, string(out)))
+               UmountDirectory(mountPath)
+               os.Exit(1)
+       }
+
+       cmd = exec.Command("cp", fmt.Sprintf("%s/initramfs.img", mountPath), buildPath)
+       cmd.Dir = buildPath
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               log.Fatal(fmt.Sprintf("Error copying initramfs: %s - %s", err, string(out)))
+               UmountDirectory(mountPath)
+               os.Exit(1)
+       }
+       os.Chmod(fmt.Sprintf("%s/initramfs.img", buildPath), 0664)
+       UmountDirectory(mountPath)
+
+       log.Println("Installer images are under: build/vmlinuz, build/initramfs.img")
+
+}
+
+// GenerateInstallerImages will extract vmlinuz/ramdisk from modified FCOS iso
+func GenerateInstallerImages(buildPath string) {
+       // Generate build directory for cosa
+       cosaPath := fmt.Sprintf("%s/cosa_build", buildPath)
+       os.RemoveAll(cosaPath)
+       os.MkdirAll(cosaPath, 0775)
+
+       // generate installer file
+       cosaBuildContent := `
+#! /bin/bash
+# init the build and proceed
+cd /srv
+coreos-assembler init https://github.com/yrobla/fedora-coreos-config --force
+
+coreos-assembler build
+coreos-assembler buildextend-installer 
+`
+       builderPath := fmt.Sprintf("%s/cosa_build_image.sh", cosaPath)
+       f, err := os.Create(builderPath)
+       if err != nil {
+               log.Fatal(fmt.Sprintf("Error creating installer script: %s", err))
+               os.Exit(1)
+       }
+       _, err = f.WriteString(cosaBuildContent)
+       f.Sync()
+       f.Close()
+       os.Chmod(builderPath, 0775)
+
+       log.Println("Installing coreos-assembler and running generation script")
+       cmd := exec.Command("podman", "run", "--rm", "--net=host", "-ti", "--privileged", "--userns=host", "-v", fmt.Sprintf("%s:/srv", cosaPath),
+               "--workdir", "/srv", "quay.io/coreos-assembler/coreos-assembler:latest", "shell", "/srv/cosa_build_image.sh")
+       cmd.Dir = buildPath
+
+       var stdBuffer bytes.Buffer
+       mw := io.MultiWriter(os.Stdout, &stdBuffer)
+       cmd.Stdout = mw
+       cmd.Stderr = mw
+
+       err = cmd.Run()
+       if err != nil {
+               log.Fatal(fmt.Sprintf("Error installing coreos-assembler: %s - %s", err, stdBuffer.String()))
+               os.Exit(1)
+       }
+       log.Println(stdBuffer.String())
+
+       // once the iso has been generated, extract vmlinuz/initramfs.img
+       isoPath := fmt.Sprintf("%s/builds/latest/fedora-coreos-29.iso", cosaPath)
+       if _, err := os.Stat(isoPath); os.IsNotExist(err) {
+               // path/to/whatever does not exist
+               log.Fatal("Final ISO image does not exist")
+               os.Exit(1)
+       }
+
+       ExtractIsoFiles(isoPath, buildPath)
+
+}
+
+// imagesCmd represents the images command
+var imagesCmd = &cobra.Command{
+       Use:              "images",
+       Short:            "Command to build the installer and deployment images (to be used on baremetal)",
+       Long:             ``,
+       TraverseChildren: true,
+       Run: func(cmd *cobra.Command, args []string) {
+               // Check if build path exists, create if not
+               buildPath, _ := cmd.Flags().GetString("build_path")
+               if len(buildPath) == 0 {
+                       // will generate a temporary directory
+                       buildPath, _ = ioutil.TempDir("/tmp", "kni")
+               } else {
+                       // remove if exists, recreate
+                       os.RemoveAll(buildPath)
+                       os.MkdirAll(buildPath, 0775)
+               }
+
+               // check version
+               version, _ := cmd.Flags().GetString("version")
+               if len(version) == 0 || (version != "maipo" && version != "ootpa") {
+                       log.Fatal("Version needs to be maipo or ootpa")
+                       os.Exit(1)
+               }
+
+               GenerateInstallerImages(buildPath)
+       },
+}
+
+func init() {
+       rootCmd.AddCommand(imagesCmd)
+
+       imagesCmd.Flags().StringP("build_path", "", "", "Directory to use as build path. If that not exists, the installer will generate a default directory")
+       imagesCmd.Flags().StringP("version", "", "", "Version of the images being generated (maipo, ootpa)")
+}