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) }
// PreCreateCheck checks that VBoxManage exists and works func (d *Driver) PreCreateCheck() error { // Check that VBoxManage exists and works version, err := d.vbmOut("--version") if err != nil { return err } // Check that VBoxManage is of a supported version if err = checkVBoxManageVersion(strings.TrimSpace(version)); err != nil { return err } if !d.NoVTXCheck && d.IsVTXDisabled() { return ErrMustEnableVTX } // Downloading boot2docker to cache should be done here to make sure // that a download failure will not leave a machine half created. b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.UpdateISOCache(d.Boot2DockerURL); err != nil { return err } // Check that Host-only interfaces are ok if _, err = listHostOnlyNetworks(d.VBoxManager); err != nil { return err } return nil }
// PreCreateCheck checks that the machine creation process can be started safely. func (d *Driver) PreCreateCheck() error { // Check that powershell was found if powershell == "" { return ErrPowerShellNotFound } // Check that hyperv is installed if err := hypervAvailable(); err != nil { return err } // Check that the user is an Administrator isAdmin, err := isAdministrator() if err != nil { return err } if !isAdmin { return ErrNotAdministrator } // Check that there is a virtual switch already configured if _, err := d.chooseVirtualSwitch(); err != nil { return err } // Downloading boot2docker to cache should be done here to make sure // that a download failure will not leave a machine half created. b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.UpdateISOCache(d.Boot2DockerURL); err != nil { return err } 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 } // 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 SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } if err := os.MkdirAll(d.ResolveStorePath("."), 0755); err != nil { return err } // Libvirt typically runs as a deprivileged service account and // needs the execute bit set for directories that contain disks for dir := d.ResolveStorePath("."); dir != "/"; dir = filepath.Dir(dir) { log.Debugf("Verifying executable bit set on %s", dir) info, err := os.Stat(dir) if err != nil { return err } mode := info.Mode() if mode&0001 != 1 { log.Debugf("Setting executable bit set on %s", dir) mode |= 0001 os.Chmod(dir, mode) } } log.Debugf("Creating VM data disk...") if err := d.generateDiskImage(d.DiskSize); err != nil { return err } log.Debugf("Defining VM...") tmpl, err := template.New("domain").Parse(domainXMLTemplate) if err != nil { return err } var xml bytes.Buffer err = tmpl.Execute(&xml, d) if err != nil { return err } vm, err := d.conn.DomainDefineXML(xml.String()) if err != nil { log.Warnf("Failed to create the VM: %s", err) return err } d.VM = &vm d.vmLoaded = true return d.Start() }
// PreCreateCheck allows for pre-create operations to make sure a driver is ready for creation func (d *Driver) PreCreateCheck() error { // Check platform type if runtime.GOOS != "darwin" { return fmt.Errorf("Driver \"parallels\" works only on OS X!") } // Check Parallels Desktop version ver, err := getParallelsVersion() if err != nil { return err } if ver < 10 { return fmt.Errorf("Driver \"parallels\" supports only Parallels Desktop 10 and higher. You use: Parallels Desktop %d.", ver) } if ver < 11 { log.Debugf("Found Parallels Desktop version: %d", ver) log.Infof("Driver \"parallels\" integration with Parallels Desktop 10 is maintained by open source community.") log.Infof("For Parallels supported configuration you should use it with Parallels Desktop 11 or later (Pro or Business edition).") return nil } // Check Parallels Desktop edition edit, err := getParallelsEdition() if err != nil { return err } log.Debugf("Found Parallels Desktop version: %d, edition: %s", ver, edit) switch edit { case "pro", "business": break default: return fmt.Errorf("Docker Machine can be used only with Parallels Desktop Pro or Business edition. You use: %s edition", edit) } // Check whether the host is connected to Shared network ok, err := isSharedConnected() if err != nil { return err } if !ok { return errSharedNotConnected } // Downloading boot2docker to cache should be done here to make sure // that a download failure will not leave a machine half created. b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.UpdateISOCache(d.Boot2DockerURL); err != nil { return err } return nil }
// PreCreateCheck checks that the machine creation process can be started safely. func (d *Driver) PreCreateCheck() error { // Downloading boot2docker to cache should be done here to make sure // that a download failure will not leave a machine half created. b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.UpdateISOCache(d.Boot2DockerURL); err != nil { return err } 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 SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } log.Infof("Creating VM...") virtualSwitch, err := d.chooseVirtualSwitch() if err != nil { return err } log.Infof("Using switch %q", virtualSwitch) diskImage, err := d.generateDiskImage() if err != nil { return err } if err := cmd("New-VM", d.MachineName, "-Path", fmt.Sprintf("'%s'", d.ResolveStorePath(".")), "-SwitchName", quote(virtualSwitch), "-MemoryStartupBytes", toMb(d.MemSize)); err != nil { return err } if d.CPU > 1 { if err := cmd("Set-VMProcessor", d.MachineName, "-Count", fmt.Sprintf("%d", d.CPU)); err != nil { return err } } if err := cmd("Set-VMDvdDrive", "-VMName", d.MachineName, "-Path", quote(d.ResolveStorePath("boot2docker.iso"))); err != nil { return err } if err := cmd("Add-VMHardDiskDrive", "-VMName", d.MachineName, "-Path", quote(diskImage)); err != nil { return err } log.Infof("Starting VM...") return d.Start() }
func (provisioner *Boot2DockerProvisioner) upgradeIso() error { // TODO: Ideally, we should not read from mcndirs directory at all. // The driver should be able to communicate how and where to place the // relevant files. b2dutils := mcnutils.NewB2dUtils(mcndirs.GetBaseDir()) // Check if the driver has specified a custom b2d url jsonDriver, err := json.Marshal(provisioner.GetDriver()) if err != nil { return err } var d struct { Boot2DockerURL string } json.Unmarshal(jsonDriver, &d) log.Info("Downloading latest boot2docker iso...") // Usually we call this implicitly, but call it here explicitly to get // the latest default boot2docker ISO. if d.Boot2DockerURL == "" { if err := b2dutils.DownloadLatestBoot2Docker(d.Boot2DockerURL); err != nil { return err } } log.Info("Stopping machine to do the upgrade...") if err := provisioner.Driver.Stop(); err != nil { return err } if err := mcnutils.WaitFor(drivers.MachineInState(provisioner.Driver, state.Stopped)); err != nil { return err } machineName := provisioner.GetDriver().GetMachineName() log.Infof("Upgrading machine %q...", machineName) // Either download the latest version of the b2d url that was explicitly // specified when creating the VM or copy the (updated) default ISO if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, machineName); err != nil { return err } log.Infof("Starting machine back up...") if err := provisioner.Driver.Start(); err != nil { return err } return mcnutils.WaitFor(drivers.MachineInState(provisioner.Driver, state.Running)) }
func (provisioner *RancherProvisioner) upgradeIso() error { // Largely copied from Boot2Docker provisioner, we should find a way to share this code log.Info("Stopping machine to do the upgrade...") if err := provisioner.Driver.Stop(); err != nil { return err } if err := mcnutils.WaitFor(drivers.MachineInState(provisioner.Driver, state.Stopped)); err != nil { return err } machineName := provisioner.GetDriver().GetMachineName() log.Infof("Upgrading machine %s...", machineName) // TODO: Ideally, we should not read from mcndirs directory at all. // The driver should be able to communicate how and where to place the // relevant files. b2dutils := mcnutils.NewB2dUtils(mcndirs.GetBaseDir()) url, err := provisioner.getLatestISOURL() if err != nil { return err } if err := b2dutils.DownloadISOFromURL(url); err != nil { return err } // Copy the latest version of boot2docker ISO to the machine's directory if err := b2dutils.CopyIsoToMachineDir("", machineName); err != nil { return err } log.Infof("Starting machine back up...") if err := provisioner.Driver.Start(); err != nil { return err } return mcnutils.WaitFor(drivers.MachineInState(provisioner.Driver, state.Running)) }
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 (provisioner *Boot2DockerProvisioner) upgradeIso() error { log.Info("Stopping machine to do the upgrade...") if err := provisioner.Driver.Stop(); err != nil { return err } if err := mcnutils.WaitFor(drivers.MachineInState(provisioner.Driver, state.Stopped)); err != nil { return err } machineName := provisioner.GetDriver().GetMachineName() log.Infof("Upgrading machine %s...", machineName) // TODO: Ideally, we should not read from mcndirs directory at all. // The driver should be able to communicate how and where to place the // relevant files. b2dutils := mcnutils.NewB2dUtils("", "", mcndirs.GetBaseDir()) // Usually we call this implicitly, but call it here explicitly to get // the latest boot2docker ISO. if err := b2dutils.DownloadLatestBoot2Docker(); err != nil { return err } // Copy the latest version of boot2docker ISO to the machine's directory if err := b2dutils.CopyIsoToMachineDir("", machineName); err != nil { return err } log.Infof("Starting machine back up...") if err := provisioner.Driver.Start(); err != nil { return err } return mcnutils.WaitFor(drivers.MachineInState(provisioner.Driver, state.Running)) }
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 VirtualBox VM...") // import b2d VM if requested if d.Boot2DockerImportVM != "" { name := d.Boot2DockerImportVM // make sure vm is stopped _ = d.vbm("controlvm", name, "poweroff") diskInfo, err := getVMDiskInfo(name, d.VBoxManager) if err != nil { return err } if _, err := os.Stat(diskInfo.Path); err != nil { return err } if err := d.vbm("clonehd", diskInfo.Path, d.diskPath()); err != nil { return err } log.Debugf("Importing VM settings...") vmInfo, err := getVMInfo(name, d.VBoxManager) if err != nil { return err } d.CPU = vmInfo.CPUs d.Memory = vmInfo.Memory log.Debugf("Importing SSH key...") keyPath := filepath.Join(mcnutils.GetHomeDir(), ".ssh", "id_boot2docker") if err := mcnutils.CopyFile(keyPath, d.GetSSHKeyPath()); err != nil { return err } } else { log.Infof("Creating SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } log.Debugf("Creating disk image...") if err := d.generateDiskImage(d.DiskSize); err != nil { return err } } if err := d.vbm("createvm", "--basefolder", d.ResolveStorePath("."), "--name", d.MachineName, "--register"); err != nil { return err } log.Debugf("VM CPUS: %d", d.CPU) log.Debugf("VM Memory: %d", d.Memory) cpus := d.CPU if cpus < 1 { cpus = int(runtime.NumCPU()) } if cpus > 32 { cpus = 32 } if err := d.vbm("modifyvm", d.MachineName, "--firmware", "bios", "--bioslogofadein", "off", "--bioslogofadeout", "off", "--bioslogodisplaytime", "0", "--biosbootmenu", "disabled", "--ostype", "Linux26_64", "--cpus", fmt.Sprintf("%d", cpus), "--memory", fmt.Sprintf("%d", d.Memory), "--acpi", "on", "--ioapic", "on", "--rtcuseutc", "on", "--natdnshostresolver1", "off", "--natdnsproxy1", "off", "--cpuhotplug", "off", "--pae", "on", "--hpet", "on", "--hwvirtex", "on", "--nestedpaging", "on", "--largepages", "on", "--vtxvpid", "on", "--accelerate3d", "off", "--boot1", "dvd"); err != nil { return err } if err := d.vbm("modifyvm", d.MachineName, "--nic1", "nat", "--nictype1", "82540EM", "--cableconnected1", "on"); err != nil { return err } if err := d.setupHostOnlyNetwork(d.MachineName); err != nil { return err } if err := d.vbm("storagectl", d.MachineName, "--name", "SATA", "--add", "sata", "--hostiocache", "on"); err != nil { return err } if err := d.vbm("storageattach", d.MachineName, "--storagectl", "SATA", "--port", "0", "--device", "0", "--type", "dvddrive", "--medium", d.ResolveStorePath("boot2docker.iso")); err != nil { return err } if err := d.vbm("storageattach", d.MachineName, "--storagectl", "SATA", "--port", "1", "--device", "0", "--type", "hdd", "--medium", d.diskPath()); err != nil { return err } // let VBoxService do nice magic automounting (when it's used) if err := d.vbm("guestproperty", "set", d.MachineName, "/VirtualBox/GuestAdd/SharedFolders/MountPrefix", "/"); err != nil { return err } if err := d.vbm("guestproperty", "set", d.MachineName, "/VirtualBox/GuestAdd/SharedFolders/MountDir", "/"); err != nil { return err } shareName, shareDir := getShareDriveAndName() if shareDir != "" && !d.NoShare { log.Debugf("setting up shareDir") if _, err := os.Stat(shareDir); err != nil && !os.IsNotExist(err) { return err } else if !os.IsNotExist(err) { if shareName == "" { // parts of the VBox internal code are buggy with share names that start with "/" shareName = strings.TrimLeft(shareDir, "/") // TODO do some basic Windows -> MSYS path conversion // ie, s!^([a-z]+):[/\\]+!\1/!; s!\\!/!g } // woo, shareDir exists! let's carry on! if err := d.vbm("sharedfolder", "add", d.MachineName, "--name", shareName, "--hostpath", shareDir, "--automount"); err != nil { return err } // enable symlinks if err := d.vbm("setextradata", d.MachineName, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/"+shareName, "1"); err != nil { return err } } } return d.Start() }
// Create has the following implementation: // 1. check whether the docker directory contains the boot2docker ISO // 2. generate an SSH keypair and bundle it in a tar. // 3. create a virtual machine with the boot2docker ISO mounted; // 4. reconfigure the virtual machine network and disk size; func (d *Driver) Create() error { b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Generating SSH Keypair...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } // Create context ctx, cancel := context.WithCancel(context.Background()) defer cancel() c, err := d.vsphereLogin(ctx) if err != nil { return err } defer c.Logout(ctx) // Create a new finder f := find.NewFinder(c.Client, true) dc, err := f.DatacenterOrDefault(ctx, d.Datacenter) if err != nil { return err } f.SetDatacenter(dc) dss, err := f.DatastoreOrDefault(ctx, d.Datastore) if err != nil { return err } net, err := f.NetworkOrDefault(ctx, d.Network) if err != nil { return err } hs, err := f.HostSystemOrDefault(ctx, d.HostSystem) if err != nil { return err } var rp *object.ResourcePool if d.Pool != "" { // Find specified Resource Pool rp, err = f.ResourcePool(ctx, d.Pool) if err != nil { return err } } else { // Pick default Resource Pool for Host System rp, err = hs.ResourcePool(ctx) if err != nil { return err } } spec := types.VirtualMachineConfigSpec{ Name: d.MachineName, GuestId: "otherLinux64Guest", Files: &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", dss.Name())}, NumCPUs: int32(d.CPU), MemoryMB: int64(d.Memory), } scsi, err := object.SCSIControllerTypes().CreateSCSIController("pvscsi") if err != nil { return err } spec.DeviceChange = append(spec.DeviceChange, &types.VirtualDeviceConfigSpec{ Operation: types.VirtualDeviceConfigSpecOperationAdd, Device: scsi, }) log.Infof("Creating VM...") folders, err := dc.Folders(ctx) task, err := folders.VmFolder.CreateVM(ctx, spec, rp, hs) if err != nil { return err } info, err := task.WaitForResult(ctx, nil) if err != nil { return err } log.Infof("Uploading Boot2docker ISO ...") dsurl, err := dss.URL(ctx, dc, fmt.Sprintf("%s/%s", d.MachineName, isoFilename)) if err != nil { return err } p := soap.DefaultUpload if err = c.Client.UploadFile(d.ISO, dsurl, &p); err != nil { return err } // Retrieve the new VM vm := object.NewVirtualMachine(c.Client, info.Result.(types.ManagedObjectReference)) devices, err := vm.Device(ctx) if err != nil { return err } var add []types.BaseVirtualDevice controller, err := devices.FindDiskController("scsi") if err != nil { return err } disk := devices.CreateDisk(controller, dss.Reference(), dss.Path(fmt.Sprintf("%s/%s.vmdk", d.MachineName, d.MachineName))) // Convert MB to KB disk.CapacityInKB = int64(d.DiskSize) * 1024 add = append(add, disk) ide, err := devices.FindIDEController("") if err != nil { return err } cdrom, err := devices.CreateCdrom(ide) if err != nil { return err } add = append(add, devices.InsertIso(cdrom, dss.Path(fmt.Sprintf("%s/%s", d.MachineName, isoFilename)))) backing, err := net.EthernetCardBackingInfo(ctx) if err != nil { return err } netdev, err := object.EthernetCardTypes().CreateEthernetCard("vmxnet3", backing) if err != nil { return err } log.Infof("Reconfiguring VM...") add = append(add, netdev) if vm.AddDevice(ctx, add...); err != nil { return err } if err := d.Start(); err != nil { return err } log.Infof("Provisioning certs and ssh keys...") // Generate a tar keys bundle if err := d.generateKeyBundle(); err != nil { return err } opman := guest.NewOperationsManager(c.Client, vm.Reference()) fileman, err := opman.FileManager(ctx) if err != nil { return err } src := d.ResolveStorePath("userdata.tar") s, err := os.Stat(src) if err != nil { return err } auth := AuthFlag{} flag := FileAttrFlag{} auth.auth.Username = B2DUser auth.auth.Password = B2DPass flag.SetPerms(0, 0, 660) url, err := fileman.InitiateFileTransferToGuest(ctx, auth.Auth(), "/home/docker/userdata.tar", flag.Attr(), s.Size(), true) if err != nil { return err } u, err := c.Client.ParseURL(url) if err != nil { return err } if err = c.Client.UploadFile(src, u, nil); err != nil { return err } procman, err := opman.ProcessManager(ctx) if err != nil { return err } var env []string guestspec := types.GuestProgramSpec{ ProgramPath: "/usr/bin/sudo", Arguments: "/bin/mv /home/docker/userdata.tar /var/lib/boot2docker/userdata.tar && /usr/bin/sudo tar xf /var/lib/boot2docker/userdata.tar -C /home/docker/ > /var/log/userdata.log 2>&1 && /usr/bin/sudo chown -R docker:staff /home/docker", WorkingDirectory: "", EnvVariables: env, } _, err = procman.StartProgram(ctx, auth.Auth(), &guestspec) if err != nil { return err } return nil }
// Create a host using the driver's config func (d *Driver) Create() error { var ( err error ) b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err = b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Creating SSH key...") sshKeyPath := d.GetSSHKeyPath() log.Debugf("SSH key: %s", sshKeyPath) if err = ssh.GenerateSSHKey(sshKeyPath); err != nil { return err } log.Infof("Creating Parallels Desktop VM...") ver, err := getParallelsVersion() if err != nil { return err } distribution := "boot2docker" if ver < 11 { distribution = "linux-2.6" } absStorePath, _ := filepath.Abs(d.ResolveStorePath(".")) if err = prlctl("create", d.MachineName, "--distribution", distribution, "--dst", absStorePath, "--no-hdd"); err != nil { return err } cpus := d.CPU if cpus < 1 { cpus = int(runtime.NumCPU()) } if cpus > 32 { cpus = 32 } if err = prlctl("set", d.MachineName, "--select-boot-device", "off", "--cpus", fmt.Sprintf("%d", cpus), "--memsize", fmt.Sprintf("%d", d.Memory), "--cpu-hotplug", "off", "--on-window-close", "keep-running", "--longer-battery-life", "on", "--3d-accelerate", "off", "--device-bootorder", "cdrom0"); err != nil { return err } absISOPath, _ := filepath.Abs(d.ResolveStorePath(isoFilename)) if err = prlctl("set", d.MachineName, "--device-set", "cdrom0", "--iface", "sata", "--position", "0", "--image", absISOPath, "--connect"); err != nil { return err } // Create a small plain disk. It will be converted and expanded later if err = prlctl("set", d.MachineName, "--device-add", "hdd", "--iface", "sata", "--position", "1", "--image", d.diskPath(), "--type", "plain", "--size", fmt.Sprintf("%d", minDiskSize)); err != nil { return err } if err = d.generateDiskImage(d.DiskSize); err != nil { return err } if ver >= 11 { // Enable headless mode if err = prlctl("set", d.MachineName, "--startup-view", "headless"); err != nil { return err } // Don't share any additional folders if err = prlctl("set", d.MachineName, "--shf-host-defined", "off"); err != nil { return err } // Enable time sync, don't touch timezone (this part is buggy) if err = prlctl("set", d.MachineName, "--time-sync", "on"); err != nil { return err } if err = prlctl("set", d.MachineName, "--disable-timezone-sync", "on"); err != nil { return err } } else { // Disable time sync feature because it has an issue with timezones. if err = prlctl("set", d.MachineName, "--time-sync", "off"); err != nil { return err } } // Configure Shared Folders if err = prlctl("set", d.MachineName, "--shf-host", "on", "--shared-cloud", "off", "--shared-profile", "off", "--smart-mount", "off"); err != nil { return err } if !d.NoShare { if err = prlctl("set", d.MachineName, "--shf-host-add", shareFolderName, "--path", shareFolderPath); err != nil { return err } } log.Infof("Starting Parallels Desktop VM...") // Don't use Start() since it expects to have a dhcp lease already if err = prlctl("start", d.MachineName); err != nil { return err } var ip string log.Infof("Waiting for VM to come online...") 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) conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, d.SSHPort), time.Duration(2*time.Second)) if err != nil { log.Debugf("SSH Daemon not responding yet: %s", err) time.Sleep(2 * time.Second) continue } conn.Close() break } } if ip == "" { return fmt.Errorf("Machine didn't return an IP after 120 seconds, aborting") } d.IPAddress = ip if err := d.Start(); err != nil { return err } return nil }
func (u *b2dUtilsUpdater) UpdateISOCache(storePath, isoURL string) error { return mcnutils.NewB2dUtils(storePath).UpdateISOCache(isoURL) }
func (u *b2dUtilsUpdater) CopyIsoToMachineDir(storePath, machineName, isoURL string) error { return mcnutils.NewB2dUtils(storePath).CopyIsoToMachineDir(isoURL, machineName) }
func (d *Driver) Create() error { var ( err error b2d_id uint b2d_image *goca.Image ) // Import Boot2Docker b2d_name := fmt.Sprintf("b2d-%s", d.MachineName) b2d_image, err = goca.NewImageFromName(b2d_name) if err != nil { b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath) if err = b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } b2d_template := goca.NewTemplateBuilder() b2d_template.AddValue("name", b2d_name) b2d_template.AddValue("path", d.ResolveStorePath("boot2docker.iso")) b2d_id, err = goca.CreateImage(b2d_template.String(), 1) // TODO: ds_id != 1 if err != nil { return err } b2d_image = goca.NewImage(b2d_id) b2d_state := "" for b2d_state != "READY" { err = b2d_image.Info() if err != nil { return err } b2d_state, err = b2d_image.StateString() if err != nil { return err } switch b2d_state { case "INIT", "LOCKED": time.Sleep(1 * time.Second) case "READY": default: log.Errorf("Unexpected image state %s", b2d_state) return errors.New("Unexpected image state") } } log.Infof("Boot2Docker image registered...") } else { b2d_id = b2d_image.Id } log.Infof("Creating SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath()) if err != nil { return err } // Create template template := goca.NewTemplateBuilder() template.AddValue("NAME", d.MachineName) template.AddValue("CPU", d.CPU) template.AddValue("MEMORY", d.Memory) if d.VCPU != "" { template.AddValue("VCPU", d.VCPU) } vector := template.NewVector("NIC") vector.AddValue("NETWORK", d.Network) vector = template.NewVector("DISK") vector.AddValue("IMAGE_ID", b2d_id) vector.AddValue("DEV_PREFIX", "sd") vector = template.NewVector("DISK") vector.AddValue("FORMAT", "raw") vector.AddValue("TYPE", "fs") vector.AddValue("SIZE", string(d.DiskSize)) vector.AddValue("DEV_PREFIX", "sd") vector = template.NewVector("CONTEXT") vector.AddValue("NETWORK", "YES") vector.AddValue("SSH_PUBLIC_KEY", string(pubKey)) vector = template.NewVector("GRAPHICS") vector.AddValue("LISTEN", "0.0.0.0") vector.AddValue("TYPE", "vnc") // Instantiate log.Infof("Starting VM...") _, err = goca.CreateVM(template.String(), false) if err != nil { return err } if d.IPAddress, err = d.GetIP(); err != nil { return err } if err := d.Start(); err != nil { return err } return nil }
func (d *Driver) Create() error { err := hypervAvailable() if err != nil { return err } d.setMachineNameIfNotSet() b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath) if err := b2dutils.CopyIsoToMachineDir(d.boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Creating SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } log.Infof("Creating VM...") virtualSwitch, err := d.chooseVirtualSwitch() if err != nil { return err } err = d.generateDiskImage() if err != nil { return err } command := []string{ "New-VM", "-Name", d.MachineName, "-Path", fmt.Sprintf("'%s'", d.ResolveStorePath(".")), "-MemoryStartupBytes", fmt.Sprintf("%dMB", d.MemSize)} _, err = execute(command) if err != nil { return err } command = []string{ "Set-VMDvdDrive", "-VMName", d.MachineName, "-Path", fmt.Sprintf("'%s'", d.ResolveStorePath("boot2docker.iso"))} _, err = execute(command) if err != nil { return err } command = []string{ "Add-VMHardDiskDrive", "-VMName", d.MachineName, "-Path", fmt.Sprintf("'%s'", d.diskImage)} _, err = execute(command) if err != nil { return err } command = []string{ "Connect-VMNetworkAdapter", "-VMName", d.MachineName, "-SwitchName", fmt.Sprintf("'%s'", virtualSwitch)} _, err = execute(command) if err != nil { return err } log.Infof("Starting VM...") if err := d.Start(); err != nil { return err } 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 }
func (d *Driver) Create() error { b2dutils := mcnutils.NewB2dUtils("", "", d.GlobalArtifactPath()) if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Creating SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } log.Infof("Creating VM...") if err := os.MkdirAll(d.LocalArtifactPath("."), 0755); err != nil { return err } log.Debugf("Extracting vmlinuz64 and initrd.img from %s...", isoFilename) if err := d.extractKernelImages(); err != nil { return err } log.Debugf("Writing boot2docker VM disk image...") if err := d.writeDiskImage(); err != nil { return err } log.Debugf("Creating Blank disk image...") if err := d.generateBlankDiskImage(d.DiskSize); err != nil { // TODO return err } log.Debugf("Generate UUID...") d.UUID = uuidgen() log.Debugf(d.UUID) // TODO log.Debugf("Create UUID file...") if err := d.createUUIDFile(); err != nil { return err } log.Debugf("Running xhyve VM...") if err := d.Start(); err != nil { return err } // TODO Maybe get MAC address here from host asignment var ip string var err error log.Infof("Waiting for VM to come online...") 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 return nil }
func (d *Driver) Create() error { b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath) if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } // download cloud-init config drive if d.ConfigDriveURL != "" { log.Infof("Downloading %s from %s", isoConfigDrive, d.ConfigDriveURL) if err := b2dutils.DownloadISO(d.ResolveStorePath("."), isoConfigDrive, d.ConfigDriveURL); err != nil { return err } } log.Infof("Creating SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } log.Infof("Creating VM...") if err := os.MkdirAll(d.ResolveStorePath("."), 0755); err != nil { return err } if _, err := os.Stat(d.vmxPath()); err == nil { return ErrMachineExist } // Generate vmx config file from template vmxt := template.Must(template.New("vmx").Parse(vmx)) vmxfile, err := os.Create(d.vmxPath()) if err != nil { return err } vmxt.Execute(vmxfile, d) // Generate vmdk file diskImg := d.ResolveStorePath(fmt.Sprintf("%s.vmdk", d.MachineName)) if _, err := os.Stat(diskImg); err != nil { if !os.IsNotExist(err) { return err } if err := vdiskmanager(diskImg, d.DiskSize); err != nil { return err } } log.Infof("Starting %s...", d.MachineName) vmrun("start", d.vmxPath(), "nogui") var ip string log.Infof("Waiting for VM to come online...") 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) conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, 22), time.Duration(2*time.Second)) if err != nil { log.Debugf("SSH Daemon not responding yet: %s", err) time.Sleep(2 * time.Second) continue } conn.Close() 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 // Do not execute the rest of boot2docker specific configuration // The uplaod of the public ssh key uses a ssh connection, // this works without installed vmware client tools if d.ConfigDriveURL != "" { var keyfh *os.File var keycontent []byte log.Infof("Copy public SSH key to %s [%s]", d.MachineName, d.IPAddress) // create .ssh folder in users home if err := executeSSHCommand(fmt.Sprintf("mkdir -p /home/%s/.ssh", d.SSHUser), d); err != nil { return err } // read generated public ssh key if keyfh, err = os.Open(d.publicSSHKeyPath()); err != nil { return err } defer keyfh.Close() if keycontent, err = ioutil.ReadAll(keyfh); err != nil { return err } // add public ssh key to authorized_keys if err := executeSSHCommand(fmt.Sprintf("echo '%s' > /home/%s/.ssh/authorized_keys", string(keycontent), d.SSHUser), d); err != nil { return err } // make it secure if err := executeSSHCommand(fmt.Sprintf("chmod 600 /home/%s/.ssh/authorized_keys", d.SSHUser), d); err != nil { return err } log.Debugf("Leaving create sequence early, configdrive found") return nil } // Generate a tar keys bundle if err := d.generateKeyBundle(); err != nil { return err } // Test if /var/lib/boot2docker exists vmrun("-gu", B2DUser, "-gp", B2DPass, "directoryExistsInGuest", d.vmxPath(), "/var/lib/boot2docker") // Copy SSH keys bundle vmrun("-gu", B2DUser, "-gp", B2DPass, "CopyFileFromHostToGuest", d.vmxPath(), d.ResolveStorePath("userdata.tar"), "/home/docker/userdata.tar") // Expand tar file. vmrun("-gu", B2DUser, "-gp", B2DPass, "runScriptInGuest", d.vmxPath(), "/bin/sh", "sudo /bin/mv /home/docker/userdata.tar /var/lib/boot2docker/userdata.tar && sudo tar xf /var/lib/boot2docker/userdata.tar -C /home/docker/ > /var/log/userdata.log 2>&1 && sudo chown -R docker:staff /home/docker") // Enable Shared Folders vmrun("-gu", B2DUser, "-gp", B2DPass, "enableSharedFolders", d.vmxPath()) var shareName, shareDir string // TODO configurable at some point switch runtime.GOOS { case "darwin": shareName = "Users" shareDir = "/Users" // TODO "linux" and "windows" } if shareDir != "" { if _, err := os.Stat(shareDir); err != nil && !os.IsNotExist(err) { return err } else if !os.IsNotExist(err) { // add shared folder, create mountpoint and mount it. vmrun("-gu", B2DUser, "-gp", B2DPass, "addSharedFolder", d.vmxPath(), shareName, shareDir) command := "[ ! -d " + shareDir + " ]&& sudo mkdir " + shareDir + "; [ -f /usr/local/bin/vmhgfs-fuse ]&& sudo /usr/local/bin/vmhgfs-fuse -o allow_other .host:/" + shareName + " " + shareDir + " || sudo mount -t vmhgfs .host:/" + shareName + " " + shareDir vmrun("-gu", B2DUser, "-gp", B2DPass, "runScriptInGuest", d.vmxPath(), "/bin/sh", command) } } return nil }
// Create a host using the driver's config func (d *Driver) Create() error { var ( err error ) b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Creating SSH key...") sshKeyPath := d.GetSSHKeyPath() log.Debugf("SSH key: %s", sshKeyPath) if err := ssh.GenerateSSHKey(sshKeyPath); err != nil { return err } log.Infof("Creating Parallels Desktop VM...") if err := prlctl("create", d.MachineName, "--distribution", "boot2docker", "--dst", d.ResolveStorePath("."), "--no-hdd"); err != nil { return err } cpus := d.CPU if cpus < 1 { cpus = int(runtime.NumCPU()) } if cpus > 32 { cpus = 32 } if err := prlctl("set", d.MachineName, "--select-boot-device", "off", "--cpus", fmt.Sprintf("%d", cpus), "--memsize", fmt.Sprintf("%d", d.Memory), "--cpu-hotplug", "off", "--nested-virt", "on", "--pmu-virt", "on", "--on-window-close", "keep-running", "--longer-battery-life", "on", "--3d-accelerate", "off", "--device-bootorder", "cdrom0"); err != nil { return err } if err := prlctl("set", d.MachineName, "--device-set", "cdrom0", "--iface", "sata", "--position", "0", "--image", d.ResolveStorePath(isoFilename)); err != nil { return err } // Create a small plain disk. It will be converted and expanded later if err := prlctl("set", d.MachineName, "--device-add", "hdd", "--iface", "sata", "--position", "1", "--image", d.diskPath(), "--type", "plain", "--size", fmt.Sprintf("%d", minDiskSize)); err != nil { return err } if err := d.generateDiskImage(d.DiskSize); err != nil { return err } // Disable Time Sync feature because it has an issue with timezones. // TODO: Turn it back as soon as Time Sync is fixed in Parallels Tools if err := prlctl("set", d.MachineName, "--time-sync", "off"); err != nil { return err } // Enable headless mode if err := prlctl("set", d.MachineName, "--startup-view", "headless"); err != nil { return err } // Configure Shared Folders if err := prlctl("set", d.MachineName, "--shf-host", "on", "--shf-host-defined", "off", "--shared-cloud", "off", "--shared-profile", "off", "--smart-mount", "off"); err != nil { return err } if !d.NoShare { if err := prlctl("set", d.MachineName, "--shf-host-add", shareFolderName, "--path", shareFolderPath); err != nil { return err } } log.Infof("Starting Parallels Desktop VM...") // Don't use Start() since it expects to have a dhcp lease already if err := prlctl("start", d.MachineName); err != nil { return err } var ip string log.Infof("Waiting for VM to come online...") 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") } d.IPAddress = ip if err := d.Start(); err != nil { return err } return nil }
// Create has the following implementation: // 1. check whether the docker directory contains the boot2docker ISO // 2. generate an SSH keypair and bundle it in a tar. // 3. create a virtual machine with the boot2docker ISO mounted; // 4. reconfigure the virtual machine network and disk size; func (d *Driver) Create() error { b2dutils := mcnutils.NewB2dUtils(d.StorePath) if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil { return err } log.Infof("Generating SSH Keypair...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } vcConn := NewVcConn(d) log.Infof("Uploading Boot2docker ISO ...") if err := vcConn.DatastoreMkdir(d.MachineName); err != nil { return err } if _, err := os.Stat(d.ISO); os.IsNotExist(err) { log.Errorf("Unable to find boot2docker ISO at %s", d.ISO) return errors.NewIncompleteVsphereConfigError(d.ISO) } if err := vcConn.DatastoreUpload(d.ISO, d.MachineName); err != nil { return err } isoPath := fmt.Sprintf("%s/%s", d.MachineName, isoFilename) if err := vcConn.VMCreate(isoPath); err != nil { return err } log.Infof("Configuring the virtual machine %s... ", d.MachineName) if err := vcConn.VMDiskCreate(); err != nil { return err } if err := vcConn.VMAttachNetwork(); err != nil { return err } if err := d.Start(); err != nil { return err } // Generate a tar keys bundle if err := d.generateKeyBundle(); err != nil { return err } // Copy SSH keys bundle if err := vcConn.GuestUpload(B2DUser, B2DPass, d.ResolveStorePath("userdata.tar"), "/home/docker/userdata.tar"); err != nil { return err } // Expand tar file. if err := vcConn.GuestStart(B2DUser, B2DPass, "/usr/bin/sudo", "/bin/mv /home/docker/userdata.tar /var/lib/boot2docker/userdata.tar && /usr/bin/sudo tar xf /var/lib/boot2docker/userdata.tar -C /home/docker/ > /var/log/userdata.log 2>&1 && /usr/bin/sudo chown -R docker:staff /home/docker"); err != nil { return err } 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 SSH key...") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); 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("Make a boot2docker userdata.tar key bundle...") if err := d.generateKeyBundle(); err != nil { return err } // Fix file permission root to current user. // In order to avoid require sudo of vmnet.framework, Execute the root owner(and root uid) // "docker-machine-xhyve" and "goxhyve" binary in golang. log.Infof("Fix file permission...") os.Chown(d.ResolveStorePath("."), 501, 20) //TODO Parse current user uid and gid files, _ := ioutil.ReadDir(d.ResolveStorePath(".")) for _, f := range files { log.Debugf(d.ResolveStorePath(f.Name())) os.Chown(d.ResolveStorePath(f.Name()), 501, 20) } log.Infof("Creating blank ext4 filesystem disk image...") if err := d.generateBlankDiskImage(d.DiskSize); err != nil { return err } os.Chown(d.ResolveStorePath(d.MachineName+".img"), 501, 20) log.Debugf("Created disk size: %dMB", d.DiskSize) log.Infof("Generate UUID...") d.UUID = uuidgen() //TODO Native golang instead execute "uuidgen" log.Debugf("uuidgen generated UUID: %s", d.UUID) log.Infof("Convert UUID to MAC address...") //Trim "0" string re := regexp.MustCompile(`[0]`) mac, _ := vmnet.GetMACAddressByUUID(d.UUID) d.MacAddr = re.ReplaceAllString(mac, "") log.Debugf("uuid2mac output MAC address: %s", d.MacAddr) log.Infof("Starting %s...", d.MachineName) if err := d.Start(); err != nil { return err } var ip string var err error log.Infof("Waiting for VM to come online...") log.Debugf("d.MacAddr", d.MacAddr) 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 return nil }
func (d *Driver) Create() error { var err error d.setMachineNameIfNotSet() // Download boot2docker ISO from Internet var isoURL string b2dutils := mcnutils.NewB2dUtils(d.StorePath) if d.Boot2DockerURL != "" { isoURL = d.Boot2DockerURL } else { isoURL, err = b2dutils.GetLatestBoot2DockerReleaseURL("") if err != nil { log.Errorf("Unable to check for the latest release: %s", err) return err } } log.Infof("Downloading %s from %s...", isoFilename, isoURL) if err := b2dutils.DownloadISO(d.StorePath, isoFilename, isoURL); err != nil { return err } log.Infof("Logging into XenServer %s...", d.Server) c, err := d.GetXenAPIClient() if err != nil { return err } // Generate SSH Keys log.Infof("Creating SSH key...") if err := ssh.GenerateSSHKey(d.sshKeyPath()); err != nil { return err } log.Infof("Creating ISO VDI...") // Get the SR var sr *xsclient.SR if d.SR == "" { sr, err = c.GetDefaultSR() } else { sr, err = c.GetUniqueSRByNameLabel(d.SR) } if err != nil { return err } isoFileInfo, err := os.Stat(d.ISO) if err != nil { return err } // Create the VDI isoVdi, err := sr.CreateVdi(isoFilename, isoFileInfo.Size()) if err != nil { log.Errorf("Unable to create ISO VDI '%s': %v", isoFilename, err) return err } // Import the VDI if err = d.importVdi(isoVdi, d.ISO, time.Duration(d.UploadTimeout)*time.Second); err != nil { return err } isoVdiUuid, err := isoVdi.GetUuid() if err != nil { return err } log.Infof("Creating Disk VDI...") err = d.generateDiskImage() if err != nil { return err } // Create the VDI diskVdi, err := sr.CreateVdi("bootdocker disk", int64(d.DiskSize)*1024*1024) if err != nil { log.Errorf("Unable to create ISO VDI '%s': %v", "bootdocker disk", err) return err } if err = d.importVdi(diskVdi, d.TAR, time.Duration(d.UploadTimeout)*time.Second); err != nil { return err } diskVdiUuid, err := diskVdi.GetUuid() if err != nil { return err } log.Infof("Creating VM...") vm0, err := c.GetUniqueVMByNameLabel(osTemplateLabelName) if err != nil { return err } // Clone VM from VM template vm, err := vm0.Clone(fmt.Sprintf("__gui__%s", d.MachineName)) if err != nil { return err } vmMacSeed, err := pseudoUuid() if err != nil { return err } hostname, err := os.Hostname() if err != nil { log.Errorf("Unable get local hostname") } otherConfig := map[string]string{ "base_template_name": osTemplateLabelName, "install-methods": "cdrom,nfs,http,ftp", "linux_template": "true", "mac_seed": vmMacSeed, "docker-machine-creator": hostname, } err = vm.SetOtherConfig(otherConfig) if err != nil { return err } log.Infof("Provision VM...") err = vm.Provision() if err != nil { return err } // Set machine name err = vm.SetNameLabel(d.MachineName) if err != nil { return err } // Set vCPU number err = vm.SetVCPUsMax(d.CPU) if err != nil { return err } err = vm.SetVCPUsAtStartup(d.CPU) if err != nil { return err } platform_params := map[string]string{ "acpi": "1", "apic": "true", "cores-per-socket": "1", "device_id": "0001", "nx": "true", "pae": "true", "vga": "std", "videoram": "8", "viridian": "false", } err = vm.SetPlatform(platform_params) if err != nil { return err } // Set machine memory size err = vm.SetStaticMemoryRange(uint64(d.Memory)*1024*1024, uint64(d.Memory)*1024*1024) if err != nil { return err } log.Infof("Add ISO VDI to VM...") diskVdi, err = c.GetVdiByUuid(isoVdiUuid) if err != nil { return err } err = vm.ConnectVdi(diskVdi, xsclient.Disk, "0") if err != nil { return err } log.Infof("Add Disk VDI to VM...") diskVdi, err = c.GetVdiByUuid(diskVdiUuid) if err != nil { return err } err = vm.ConnectVdi(diskVdi, xsclient.Disk, "1") if err != nil { return err } log.Infof("Add Network to VM...") var networks []*xsclient.Network if d.Network == "" { networks1, err := c.GetNetworks() if err != nil { return err } for _, network := range networks1 { otherConfig, err := network.GetOtherConfig() if err != nil { return err } isInternal, ok := otherConfig["is_host_internal_management_network"] if ok && isInternal == "true" { continue } automaitc, ok := otherConfig["automatic"] if ok && automaitc == "false" { continue } networks = append(networks, network) } } else { network, err := c.GetUniqueNetworkByNameLabel(d.Network) if err != nil { return err } networks = append(networks, network) } if len(networks) == 0 { return fmt.Errorf("Unable get available networks for %v", d.MachineName) } vifDevices, err := vm.GetAllowedVIFDevices() if err != nil { return err } if len(vifDevices) < len(networks) { log.Warnf("VM(%s) networks number is limited to %d.", d.MachineName, len(vifDevices)) networks = networks[:len(vifDevices)] } for i, network := range networks { _, err = vm.ConnectNetwork(network, vifDevices[i]) if err != nil { return err } } log.Infof("Starting VM...") if d.Host == "" { if err = vm.Start(false, false); err != nil { return err } } else { host, err := c.GetUniqueHostByNameLabel(d.Host) if err != nil { return err } if err = vm.StartOn(host, false, false); err != nil { return err } } if err := d.wait(time.Duration(d.WaitTimeout) * time.Second); err != nil { return err } log.Infof("VM Created.") return nil }