func (d *Driver) Create() error { b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Creating VM...") if err := os.MkdirAll(d.ResolveStorePath("."), 0755); err != nil { return err } log.Infof("Extracting vmlinuz64 and initrd.img from %s...", isoFilename) if err := d.extractKernelImages(); err != nil { return err } log.Infof("Generating %dMB disk image...", d.DiskSize) if err := d.generateDiskImage(d.DiskSize); err != nil { return err } // Fix file permission root to current user for vmnet.framework log.Infof("Fix file permission...") os.Chown(d.ResolveStorePath("."), syscall.Getuid(), syscall.Getegid()) files, _ := ioutil.ReadDir(d.ResolveStorePath(".")) for _, f := range files { log.Debugf(d.ResolveStorePath(f.Name())) os.Chown(d.ResolveStorePath(f.Name()), syscall.Getuid(), syscall.Getegid()) } log.Infof("Generate UUID...") d.UUID = uuidgen() log.Debugf("Generated UUID: %s", d.UUID) log.Infof("Convert UUID to MAC address...") rawUUID, err := d.getMACAdress() if err != nil { return err } d.MacAddr = trimMacAddress(rawUUID) log.Debugf("Converted MAC address: %s", d.MacAddr) log.Infof("Starting %s...", d.MachineName) if err := d.Start(); err != nil { return err } // Setup NFS sharing if d.NFSShare { log.Infof("NFS share folder must be root. Please insert root password.") err = d.setupNFSShare() if err != nil { log.Errorf("NFS setup failed: %s", err.Error()) } } return nil }
func (d *Driver) CopyIsoToMachineDir(isoURL, machineName string) error { b2d := b2d.NewB2dUtils(d.StorePath) mcnutils := mcnutils.NewB2dUtils(d.StorePath) if err := d.UpdateISOCache(isoURL); err != nil { return err } isoPath := filepath.Join(b2d.ImgCachePath, isoFilename) if isoStat, err := os.Stat(isoPath); err == nil { if int(isoStat.Sys().(*syscall.Stat_t).Uid) == 0 { log.Debugf("Fix %s file permission...", isoStat.Name()) os.Chown(isoPath, syscall.Getuid(), syscall.Getegid()) } } // TODO: This is a bit off-color. machineDir := filepath.Join(d.StorePath, "machines", machineName) machineIsoPath := filepath.Join(machineDir, isoFilename) // By default just copy the existing "cached" iso to the machine's directory... defaultISO := filepath.Join(b2d.ImgCachePath, defaultISOFilename) if isoURL == "" { log.Infof("Copying %s to %s...", defaultISO, machineIsoPath) return CopyFile(defaultISO, machineIsoPath) } // if ISO is specified, check if it matches a github releases url or fallback to a direct download downloadURL, err := b2d.GetReleaseURL(isoURL) if err != nil { return err } return mcnutils.DownloadISO(machineDir, b2d.Filename(), downloadURL) }
func (d *Driver) UpdateISOCache(isoURL string) error { b2d := b2d.NewB2dUtils(d.StorePath) mcnutils := mcnutils.NewB2dUtils(d.StorePath) // recreate the cache dir if it has been manually deleted if _, err := os.Stat(b2d.ImgCachePath); os.IsNotExist(err) { log.Infof("Image cache directory does not exist, creating it at %s...", b2d.ImgCachePath) if err := os.Mkdir(b2d.ImgCachePath, 0700); err != nil { return err } } // Check owner of storage cache directory cacheStat, _ := os.Stat(b2d.ImgCachePath) if int(cacheStat.Sys().(*syscall.Stat_t).Uid) == 0 { log.Debugf("Fix %s directory permission...", cacheStat.Name()) os.Chown(b2d.ImgCachePath, syscall.Getuid(), syscall.Getegid()) } if isoURL != "" { // Non-default B2D are not cached return nil } exists := b2d.Exists() if !exists { log.Info("No default Boot2Docker ISO found locally, downloading the latest release...") return mcnutils.DownloadLatestBoot2Docker("") } latest := b2d.IsLatest() if !latest { log.Info("Default Boot2Docker ISO is out-of-date, downloading the latest release...") return mcnutils.DownloadLatestBoot2Docker("") } return nil }
func isRoot() bool { return syscall.Getuid() == 0 || syscall.Geteuid() == 0 || syscall.Getgid() == 0 || syscall.Getegid() == 0 }
// Getegid returns the numeric effective group id of the caller. func Getegid() int { return syscall.Getegid() }
// RunInContainer will execute a set of commands within a running Docker container func (d *ImageManager) RunInContainer(opts RunInContainerOpts) (exitCode int, container *dockerclient.Container, err error) { // Get current user info to map to container // os/user.Current() isn't supported when cross-compiling hence this code currentUID := syscall.Geteuid() currentGID := syscall.Getegid() var actualCmd, containerCmd []string if opts.KeepContainer { // Sleep effectively forever so if something goes wrong we can // docker exec -it bash into the container, investigate, and // manually kill the container. Most of the time the compile step // will succeed and the container will be killed and removed. containerCmd = []string{"sleep", "365d"} actualCmd = opts.Cmd } else { containerCmd = opts.Cmd // actualCmd not used } env := []string{ fmt.Sprintf("HOST_USERID=%d", currentUID), fmt.Sprintf("HOST_USERGID=%d", currentGID), } for _, name := range []string{"http_proxy", "https_proxy"} { var proxyURL *url.URL var err error if val, ok := os.LookupEnv(name); ok { env = append(env, fmt.Sprintf("%s=%s", name, val)) if proxyURL, err = url.Parse(val); err != nil { proxyURL = nil } } name = strings.ToUpper(name) if val, ok := os.LookupEnv(name); ok { env = append(env, fmt.Sprintf("%s=%s", name, val)) if proxyURL == nil { // Follow curl, lower case env vars have precedence if proxyURL, err = url.Parse(val); err != nil { proxyURL = nil } } } } cco := dockerclient.CreateContainerOptions{ Config: &dockerclient.Config{ Tty: false, AttachStdin: false, AttachStdout: true, AttachStderr: true, Hostname: "compiler", Domainname: "fissile", Cmd: containerCmd, WorkingDir: "/", Image: opts.ImageName, Env: env, }, HostConfig: &dockerclient.HostConfig{ Privileged: false, Binds: []string{}, ReadonlyRootfs: false, }, Name: opts.ContainerName, } for name, dirverOpts := range opts.Volumes { name = fmt.Sprintf("volume_%s_%s", opts.ContainerName, name) _, err := d.client.CreateVolume(dockerclient.CreateVolumeOptions{ Name: name, DriverOpts: dirverOpts, }) if err != nil { return -1, nil, err } } for src, dest := range opts.Mounts { if _, ok := opts.Volumes[src]; ok { // Attempt to mount a volume; use the generated name src = fmt.Sprintf("volume_%s_%s", opts.ContainerName, src) } mountString := fmt.Sprintf("%s:%s", src, dest) if dest == ContainerInPath { mountString += ":ro" } cco.HostConfig.Binds = append(cco.HostConfig.Binds, mountString) } container, err = d.client.CreateContainer(cco) if err != nil { return -1, nil, err } attached := make(chan struct{}) attachCloseWaiter, attachErr := d.client.AttachToContainerNonBlocking(dockerclient.AttachToContainerOptions{ Container: container.ID, InputStream: nil, OutputStream: opts.StdoutWriter, ErrorStream: opts.StderrWriter, Stdin: false, Stdout: opts.StdoutWriter != nil, Stderr: opts.StderrWriter != nil, Stream: true, RawTerminal: false, Success: attached, }) if attachErr != nil { return -1, container, fmt.Errorf("Error running in container: %s. Error attaching to container: %s", container.ID, attachErr.Error()) } attached <- <-attached err = d.client.StartContainer(container.ID, container.HostConfig) if err != nil { return -1, container, err } closeFiles := func() { if stdoutCloser, ok := opts.StdoutWriter.(io.Closer); ok { stdoutCloser.Close() } if stderrCloser, ok := opts.StderrWriter.(io.Closer); ok { stderrCloser.Close() } } if !opts.KeepContainer { exitCode, err = d.client.WaitContainer(container.ID) attachCloseWaiter.Wait() closeFiles() if err != nil { exitCode = -1 } return exitCode, container, nil } // KeepContainer mode: // Run the cmd with 'docker exec ...' so we can keep the container around. // Note that this time we'll need to stop it if it doesn't fail cmdArgs := append([]string{"exec", "-i", container.ID}, actualCmd...) // Couldn't get this to work with dockerclient.Exec, so do it this way execCmd := exec.Command("docker", cmdArgs...) execCmd.Stdout = opts.StdoutWriter execCmd.Stderr = opts.StderrWriter err = execCmd.Run() // No need to wait on execCmd or on attachCloseWaiter if err == nil { exitCode = 0 } else { exitCode = -1 } closeFiles() return exitCode, container, err }
func (d *Driver) Create() error { if err := d.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Creating VM...") if err := os.MkdirAll(d.ResolveStorePath("."), 0755); err != nil { return err } if err := d.extractKernelImages(); err != nil { return err } log.Infof("Generating %dMB disk image...", d.DiskSize) if d.Qcow2 { if err := d.generateQcow2Image(d.DiskSize); err != nil { return err } } else { if err := d.generateSparseBundleDiskImage(d.DiskSize); err != nil { return err } } // Fix file permission root to current user for vmnet.framework log.Infof("Fix file permission...") os.Chown(d.ResolveStorePath("."), syscall.Getuid(), syscall.Getegid()) files, _ := ioutil.ReadDir(d.ResolveStorePath(".")) for _, f := range files { log.Debugf(d.ResolveStorePath(f.Name())) os.Chown(d.ResolveStorePath(f.Name()), syscall.Getuid(), syscall.Getegid()) } if d.UUID == "" { log.Infof("Generate UUID...") d.UUID = uuidgen() log.Debugf("Generated UUID: %s", d.UUID) } else { log.Infof("Using Supplied UUID: %s", d.UUID) } log.Infof("Convert UUID to MAC address...") rawUUID, err := d.getMACAdress() if err != nil { return fmt.Errorf("Could not convert the UUID to MAC address: %s", err.Error()) } d.MacAddr = trimMacAddress(rawUUID) log.Debugf("Converted MAC address: %s", d.MacAddr) log.Infof("Starting %s...", d.MachineName) if err := d.Start(); err != nil { return err } if d.Virtio9p { err = d.setupVirt9pShare() if err != nil { log.Errorf("virtio-9p setup failed: %s", err.Error()) } } // Setup NFS sharing if d.NFSShare { log.Infof("NFS share folder must be root. Please insert root password.") err = d.setupNFSShare() if err != nil { log.Errorf("NFS setup failed: %s", err.Error()) } } return nil }
func (d *Driver) Create() error { b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Creating VM...") if err := os.MkdirAll(d.ResolveStorePath("."), 0755); err != nil { return err } log.Infof("Extracting vmlinuz64 and initrd.img from %s...", isoFilename) if err := d.extractKernelImages(); err != nil { return err } log.Infof("Generating %dMB disk image...", d.DiskSize) if err := d.generateDiskImage(d.DiskSize); err != nil { return err } // Fix file permission root to current user for vmnet.framework log.Infof("Fix file permission...") os.Chown(d.ResolveStorePath("."), syscall.Getuid(), syscall.Getegid()) files, _ := ioutil.ReadDir(d.ResolveStorePath(".")) for _, f := range files { log.Debugf(d.ResolveStorePath(f.Name())) os.Chown(d.ResolveStorePath(f.Name()), syscall.Getuid(), syscall.Getegid()) } log.Infof("Generate UUID...") d.UUID = uuidgen() log.Debugf("Generated UUID: %s", d.UUID) log.Infof("Convert UUID to MAC address...") rawUUID, err := d.getMACAdress() if err != nil { return err } d.MacAddr = trimMacAddress(rawUUID) log.Debugf("Converted MAC address: %s", d.MacAddr) log.Infof("Starting %s...", d.MachineName) if err := d.Start(); err != nil { return err } log.Infof("Waiting for VM to come online...") var ip string for i := 1; i <= 60; i++ { ip, err = d.getIPfromDHCPLease() if err != nil { log.Debugf("Not there yet %d/%d, error: %s", i, 60, err) time.Sleep(2 * time.Second) continue } if ip != "" { log.Debugf("Got an ip: %s", ip) break } } if ip == "" { return fmt.Errorf("Machine didn't return an IP after 120 seconds, aborting") } // We got an IP, let's copy ssh keys over d.IPAddress = ip // Setup NFS sharing if d.NFSShare { err = d.setupNFSShare() if err != nil { log.Errorf("NFS setup failed: %s", err.Error()) } } return nil }