github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/containers/compilers/osv/java-compiler/osv_boot_creator.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "github.com/sirupsen/logrus" 7 "io/ioutil" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "strings" 12 "time" 13 ) 14 15 //expect project directory at /project_directory; mount w/ -v FOLDER:/project_directory 16 //output dir will be /project_directory 17 //output files to whatever is mounted to /project_directory 18 const ( 19 project_directory = "/project_directory" 20 ) 21 22 var buildImageTimeout = time.Minute * 10 23 24 func main() { 25 useEc2Bootstrap := flag.Bool("ec2", false, "indicates whether to compile using the wrapper for ec2") 26 mainFile := flag.String("main_file", "", "name of jar or war file (not path)") 27 buildCmd := flag.String("buildCmd", "", "optional build command to build project (if not a jar)") 28 runtimeArgs := flag.String("runtime", "", "args to pass to java runtime") 29 args := flag.String("args", "", "arguments to kernel") 30 flag.Parse() 31 32 if *buildCmd != "" { 33 logrus.WithField("cmd", *buildCmd).Info("running user specified build command") 34 buildArgs := strings.Split(*buildCmd, " ") 35 var params []string 36 if len(buildArgs) > 1 { 37 params = buildArgs[1:] 38 } 39 build := exec.Command(buildArgs[0], params...) 40 build.Dir = project_directory 41 build.Stdout = os.Stdout 42 build.Stderr = os.Stderr 43 printCommand(build) 44 if err := build.Run(); err != nil { 45 logrus.WithError(err).Error("failed running build command") 46 os.Exit(-1) 47 } 48 } 49 50 artifactFile := filepath.Join(project_directory, *mainFile) 51 if _, err := os.Stat(artifactFile); err != nil { 52 logrus.WithError(err).Error("failed to stat " + filepath.Join(project_directory, *mainFile) + "; is main_file set correctly?") 53 logrus.Info("listing project files for debug purposes:") 54 listProjectFiles := exec.Command("find", project_directory) 55 listProjectFiles.Stdout = os.Stdout 56 listProjectFiles.Stderr = os.Stderr 57 listProjectFiles.Run() 58 os.Exit(-1) 59 } 60 argsStr := "" 61 if *useEc2Bootstrap { 62 argsStr += "-bootstrapType=ec2 " 63 } else { 64 argsStr += "-bootstrapType=udp " 65 } 66 if *args != "" { 67 argsStr += fmt.Sprintf("-appArgs=%s ", strings.Join(strings.Split(*args, " "), ",,")) 68 } 69 70 if strings.HasSuffix(*mainFile, ".war") { 71 logrus.Infof(".war file detected. Using Apache Tomcat to deploy") 72 argsStr += "-tomcat " 73 tomcatCapstanFileContents := fmt.Sprintf(` 74 base: unik-tomcat 75 76 cmdline: /java.so %s -cp /usr/tomcat/bin/bootstrap.jar:usr/tomcat/bin/tomcat-juli.jar -jar /program.jar %s 77 78 # 79 # List of files that are included in the generated image. 80 # 81 files: 82 /usr/tomcat/webapps/%s: %s`, 83 *runtimeArgs, 84 argsStr, 85 filepath.Base(artifactFile), artifactFile) 86 logrus.Info("writing capstanfile\n", tomcatCapstanFileContents) 87 if err := ioutil.WriteFile(filepath.Join(project_directory, "Capstanfile"), []byte(tomcatCapstanFileContents), 0644); err != nil { 88 logrus.WithError(err).Error("failed writing capstanfile") 89 os.Exit(-1) 90 } 91 } else if strings.HasSuffix(*mainFile, ".jar") { 92 logrus.Infof("building Java unikernel from .jar file") 93 argsStr += fmt.Sprintf("-jarName=/%s", *mainFile) 94 jarRunnerCapstanFileContents := fmt.Sprintf(` 95 base: unik-jar-runner 96 97 cmdline: /java.so %s -cp /%s -jar /program.jar %s 98 99 rootfs: %s`, 100 *runtimeArgs, 101 *mainFile, 102 argsStr, 103 project_directory) 104 logrus.Info("writing capstanfile\n", jarRunnerCapstanFileContents) 105 if err := ioutil.WriteFile(filepath.Join(project_directory, "Capstanfile"), []byte(jarRunnerCapstanFileContents), 0644); err != nil { 106 logrus.WithError(err).Error("failed writing capstanfile") 107 os.Exit(-1) 108 } 109 } else { 110 logrus.Errorf("%s is not of type .war or .jar, exiting!", *mainFile) 111 os.Exit(-1) 112 } 113 114 go func() { 115 fmt.Println("capstain building") 116 117 capstanCmd := exec.Command("capstan", "run", "-p", "qemu") 118 capstanCmd.Dir = project_directory 119 capstanCmd.Stdout = os.Stdout 120 capstanCmd.Stderr = os.Stderr 121 printCommand(capstanCmd) 122 if err := capstanCmd.Run(); err != nil { 123 logrus.WithError(err).Error("capstan build failed") 124 os.Exit(-1) 125 } 126 }() 127 capstanImage := filepath.Join(os.Getenv("HOME"), ".capstan", "instances", "qemu", "project_directory", "disk.qcow2") 128 129 select { 130 case <-fileReady(capstanImage): 131 fmt.Printf("image ready at %s\n", capstanImage) 132 break 133 case <-time.After(buildImageTimeout): 134 logrus.Error("timed out waiting for capstan to finish building") 135 os.Exit(-1) 136 } 137 138 fmt.Println("qemu-img converting (compatibility") 139 convertToCompatibleCmd := exec.Command("qemu-img", "convert", 140 "-f", "qcow2", 141 "-O", "qcow2", 142 "-o", "compat=0.10", 143 capstanImage, 144 project_directory+"/boot.qcow2") 145 printCommand(convertToCompatibleCmd) 146 if out, err := convertToCompatibleCmd.CombinedOutput(); err != nil { 147 logrus.WithError(err).Error(string(out)) 148 os.Exit(-1) 149 } 150 151 fmt.Println("file created at " + project_directory + "/boot.qcow2") 152 } 153 154 func fileReady(filename string) <-chan struct{} { 155 closeChan := make(chan struct{}) 156 fmt.Printf("waiting for file to become ready...\n") 157 go func() { 158 count := 0 159 for { 160 if _, err := os.Stat(filename); err == nil { 161 close(closeChan) 162 return 163 } 164 //count every 5 sec 165 if count%5 == 0 { 166 fmt.Printf("waiting for file...%vs\n", count) 167 } 168 time.Sleep(time.Second * 1) 169 count++ 170 } 171 }() 172 return closeChan 173 } 174 175 func printCommand(cmd *exec.Cmd) { 176 fmt.Printf("running command from dir %s: %v\n", cmd.Dir, cmd.Args) 177 }