func (d *Driver) Create() error { spec := d.buildHostSpec() log.Infof("Creating SSH key...") key, err := d.createSSHKey() if err != nil { return err } log.Infof("SSH key %s (%d) created in SoftLayer", key.Label, key.Id) d.SSHKeyID = key.Id spec.SshKeys = []*SshKey{key} id, err := d.getClient().VirtualGuest().Create(spec) if err != nil { return fmt.Errorf("Error creating host: %q", err) } d.Id = id d.getIp() d.waitForStart() d.waitForSetupTransactions() return nil }
func ClientOK(endpoint string, test func() bool) error { backoff := util.Backoff{} defer backoff.Close() var err error retry := false for ok := range backoff.Start() { if !ok { err = fmt.Errorf("Timeout waiting for Docker at %s", endpoint) break } if test() { break } retry = true log.Infof("Waiting for Docker at %s", endpoint) } if err != nil { return err } if retry { log.Infof("Connected to Docker at %s", endpoint) } return nil }
func (d *Driver) Create() error { log.Infof("Creating SSH key...") key, err := d.createSSHKey() if err != nil { return err } d.SSHKeyID = key.ID var sshKey *godo.DropletCreateSSHKey sshKey = &godo.DropletCreateSSHKey{ID: d.SSHKeyID} log.Infof("Creating Digital Ocean droplet...") client := d.getClient() createRequest := &godo.DropletCreateRequest{ Image: godo.DropletCreateImage{Slug: "digitalocean-image"}, Name: d.MachineName, Region: d.Region, Size: d.Size, IPv6: d.IPv6, PrivateNetworking: d.PrivateNetworking, Backups: d.Backups, SSHKeys: []godo.DropletCreateSSHKey{*sshKey}, } newDroplet, _, err := client.Droplets.Create(createRequest) if err != nil { return err } d.DropletID = newDroplet.ID droplets, _, err := client.Droplets.List(nil) if err != nil { return err } for _, n := range droplets { for _, network := range n.Networks.V4 { if network.Type == "public" { d.IPAddress = network.IPAddress } } if d.IPAddress != "" { break } time.Sleep(1 * time.Second) } log.Debugf("Created droplet ID %d, IP address %s", newDroplet.ID, d.IPAddress) return nil }
func (b *B2dUtils) CopyIsoToMachineDir(isoURL, machineName string) error { machinesDir := GetMachineDir() machineIsoPath := filepath.Join(machinesDir, machineName, b.isoFilename) // just in case the cache dir has been manually deleted, // check for it and recreate it if it's gone if _, err := os.Stat(b.imgCachePath); os.IsNotExist(err) { log.Infof("Image cache does not exist, creating it at %s...", b.imgCachePath) if err := os.Mkdir(b.imgCachePath, 0700); err != nil { return err } } // By default just copy the existing "cached" iso to // the machine's directory... if isoURL == "" { if err := b.copyDefaultIsoToMachine(machineIsoPath); err != nil { return err } } else { // But if ISO is specified go get it directly log.Infof("Downloading %s from %s...", b.isoFilename, isoURL) if err := b.DownloadISO(filepath.Join(machinesDir, machineName), b.isoFilename, isoURL); err != nil { return err } } return nil }
// deleteInstance deletes the instance, leaving the persistent disk. func (c *ComputeUtil) deleteInstance() error { log.Infof("Deleting instance.") op, err := c.service.Instances.Delete(c.project, c.zone, c.instanceName).Do() if err != nil { return err } log.Infof("Waiting for instance to delete.") return c.waitForRegionalOp(op.Name) }
// deleteDisk deletes the persistent disk. func (c *ComputeUtil) deleteDisk() error { log.Infof("Deleting disk.") op, err := c.service.Disks.Delete(c.project, c.zone, c.diskName()).Do() if err != nil { return err } log.Infof("Waiting for disk to delete.") return c.waitForRegionalOp(op.Name) }
func (d *Driver) Create() error { log.Infof("Creating SSH key...") key, err := d.createSSHKey() if err != nil { return err } d.SSHKeyID = key.ID log.Infof("Creating Digital Ocean droplet...") client := d.getClient() createRequest := &godo.DropletCreateRequest{ Image: d.Image, Name: d.MachineName, Region: d.Region, Size: d.Size, IPv6: d.IPv6, PrivateNetworking: d.PrivateNetworking, Backups: d.Backups, SSHKeys: []interface{}{d.SSHKeyID}, } newDroplet, _, err := client.Droplets.Create(createRequest) if err != nil { return err } d.DropletID = newDroplet.Droplet.ID for { newDroplet, _, err = client.Droplets.Get(d.DropletID) if err != nil { return err } for _, network := range newDroplet.Droplet.Networks.V4 { if network.Type == "public" { d.IPAddress = network.IPAddress } } if d.IPAddress != "" { break } time.Sleep(1 * time.Second) } log.Debugf("Created droplet ID %d, IP address %s", newDroplet.Droplet.ID, d.IPAddress) return nil }
func (d *Driver) Restart() error { p, err := govcloudair.NewClient() if err != nil { return err } log.Infof("Connecting to vCloud Air...") // Authenticate to vCloud Air v, err := p.Authenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) if err != nil { return err } vapp, err := v.FindVAppByID(d.VAppID) if err != nil { return err } status, err := vapp.GetStatus() if err != nil { return err } if status == "POWERED_ON" { // If it's powered on, restart the machine log.Infof("Restarting %s...", d.MachineName) task, err := vapp.Reset() if err != nil { return err } if err = task.WaitTaskCompletion(); err != nil { return err } } else { // If it's not powered on, start it. log.Infof("Docker host %s is powered off, powering it back on...", d.MachineName) task, err := vapp.PowerOn() if err != nil { return err } if err = task.WaitTaskCompletion(); err != nil { return err } } if err = p.Disconnect(); err != nil { return err } d.IPAddress, err = d.GetIP() return err }
func saveToken(storePath string, token *oauth.Token) { tokenPath := path.Join(storePath, "gce_token") log.Infof("Saving token in %v", tokenPath) f, err := os.Create(tokenPath) if err != nil { log.Infof("Warning: failed to cache oauth token: %v", err) return } defer f.Close() gob.NewEncoder(f).Encode(token) }
func setupCertificates(caCertPath, caKeyPath, clientCertPath, clientKeyPath string) error { org := utils.GetUsername() bits := 2048 if _, err := os.Stat(utils.GetMachineCertDir()); err != nil { if os.IsNotExist(err) { if err := os.MkdirAll(utils.GetMachineCertDir(), 0700); err != nil { log.Fatalf("Error creating machine config dir: %s", err) } } else { log.Fatal(err) } } if _, err := os.Stat(caCertPath); os.IsNotExist(err) { log.Infof("Creating CA: %s", caCertPath) // check if the key path exists; if so, error if _, err := os.Stat(caKeyPath); err == nil { log.Fatalf("The CA key already exists. Please remove it or specify a different key/cert.") } if err := utils.GenerateCACertificate(caCertPath, caKeyPath, org, bits); err != nil { log.Infof("Error generating CA certificate: %s", err) } } if _, err := os.Stat(clientCertPath); os.IsNotExist(err) { log.Infof("Creating client certificate: %s", clientCertPath) if _, err := os.Stat(utils.GetMachineCertDir()); err != nil { if os.IsNotExist(err) { if err := os.Mkdir(utils.GetMachineCertDir(), 0700); err != nil { log.Fatalf("Error creating machine client cert dir: %s", err) } } else { log.Fatal(err) } } // check if the key path exists; if so, error if _, err := os.Stat(clientKeyPath); err == nil { log.Fatalf("The client key already exists. Please remove it or specify a different key/cert.") } if err := utils.GenerateCert([]string{""}, clientCertPath, clientKeyPath, caCertPath, caKeyPath, org, bits); err != nil { log.Fatalf("Error generating client certificate: %s", err) } } return nil }
func (d *Driver) Start() error { machineState, err := d.GetState() if err != nil { return err } switch machineState { case state.Running: log.Infof("VM %s has already been started", d.MachineName) return nil case state.Stopped: // TODO add transactional or error handling in the following steps vcConn := NewVcConn(d) err := vcConn.VMPowerOn() if err != nil { return err } // this step waits for the vm to start and fetch its ip address; // this guarantees that the opem-vmtools has started working... _, err = vcConn.VMFetchIP() if err != nil { return err } d.IPAddress, err = d.GetIP() return err } return errors.NewInvalidStateError(d.MachineName) }
func (conn VcConn) DatastoreMkdir(dirName string) error { _, err := conn.DatastoreLs(dirName) if err == nil { return nil } log.Infof("Creating directory %s on datastore %s of vCenter %s... ", dirName, conn.driver.Datastore, conn.driver.IP) args := []string{"datastore.mkdir"} args = conn.AppendConnectionString(args) args = append(args, fmt.Sprintf("--ds=%s", conn.driver.Datastore)) args = append(args, fmt.Sprintf("--dc=%s", conn.driver.Datacenter)) args = append(args, dirName) _, stderr, err := govcOutErr(args...) if stderr != "" { return errors.NewDatastoreError(conn.driver.Datastore, "mkdir", stderr) } if err != nil { return err } return nil }
func (conn VcConn) VMCreate(isoPath string) error { log.Infof("Creating virtual machine %s of vCenter %s... ", conn.driver.MachineName, conn.driver.IP) args := []string{"vm.create"} args = conn.AppendConnectionString(args) args = append(args, fmt.Sprintf("--net=%s", conn.driver.Network)) args = append(args, fmt.Sprintf("--dc=%s", conn.driver.Datacenter)) args = append(args, fmt.Sprintf("--ds=%s", conn.driver.Datastore)) args = append(args, fmt.Sprintf("--iso=%s", isoPath)) memory := strconv.Itoa(conn.driver.Memory) args = append(args, fmt.Sprintf("--m=%s", memory)) cpu := strconv.Itoa(conn.driver.CPU) args = append(args, fmt.Sprintf("--c=%s", cpu)) args = append(args, "--disk.controller=pvscsi") args = append(args, "--net.adapter=vmxnet3") args = append(args, "--on=false") if conn.driver.Pool != "" { args = append(args, fmt.Sprintf("--pool=%s", conn.driver.Pool)) } if conn.driver.HostIP != "" { args = append(args, fmt.Sprintf("--host.ip=%s", conn.driver.HostIP)) } args = append(args, conn.driver.MachineName) _, stderr, err := govcOutErr(args...) if stderr == "" && err == nil { return nil } return errors.NewVMError("create", conn.driver.MachineName, stderr) }
func (d *Driver) Start() error { log.Infof("Starting %s...", d.MachineName) vmrun("start", d.vmxPath(), "nogui") // Do not execute the rest of boot2docker specific configuration, exit here if d.ConfigDriveURL != "" { log.Debugf("Leaving start sequence early, configdrive found") return nil } log.Debugf("Mounting Shared Folders...") 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) { // create mountpoint and mount shared folder vmrun("-gu", B2DUser, "-gp", B2DPass, "runScriptInGuest", d.vmxPath(), "/bin/sh", "sudo mkdir "+shareDir+" && sudo mount -t vmhgfs .host:/"+shareName+" "+shareDir) } } return nil }
func (d *Driver) waitForSetupTransactions() { log.Infof("Waiting for host setup transactions to complete") // sometimes we'll hit a case where there's no active transaction, but if // we check again in a few seconds, it moves to the next transaction. We // don't want to get false-positives, so we check a few times in a row to make sure! noActiveCount, maxNoActiveCount := 0, 3 for { t, err := d.GetActiveTransaction() if err != nil { noActiveCount = 0 log.Debugf("Failed to GetActiveTransaction - %+v", err) continue } if t == "" { if noActiveCount == maxNoActiveCount { break } noActiveCount++ } else { noActiveCount = 0 log.Debugf("Still waiting - active transaction is %s...", t) } time.Sleep(2 * time.Second) } }
func (d *Driver) getIp() (string, error) { log.Infof("Getting Host IP") for { var ( ip string err error ) if d.deviceConfig.PrivateNet { ip, err = d.getClient().VirtualGuest().GetPrivateIp(d.Id) } else { ip, err = d.getClient().VirtualGuest().GetPublicIp(d.Id) } if err != nil { time.Sleep(2 * time.Second) continue } // not a perfect regex, but should be just fine for our needs exp := regexp.MustCompile(`\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}`) if exp.MatchString(ip) { d.IPAddress = ip return ip, nil } time.Sleep(2 * time.Second) } }
func (d *Driver) Start() error { s, err := d.GetState() if err != nil { return err } if s == state.Stopped { // check network to re-create if needed if err := d.setupHostOnlyNetwork(d.MachineName); err != nil { return fmt.Errorf("Error setting up host only network on machine start: %s", err) } } switch s { case state.Stopped, state.Saved: d.SSHPort, err = setPortForwarding(d.MachineName, 1, "ssh", "tcp", 22, d.SSHPort) if err != nil { return err } if err := vbm("startvm", d.MachineName, "--type", "headless"); err != nil { return err } log.Infof("Starting VM...") case state.Paused: if err := vbm("controlvm", d.MachineName, "resume", "--type", "headless"); err != nil { return err } log.Infof("Resuming VM ...") default: log.Infof("VM not in restartable state") } // Wait for SSH over NAT to be available before returning to user if err := drivers.WaitForSSH(d); err != nil { return err } // Bail if we don't get an IP from DHCP after a given number of seconds. if err := utils.WaitForSpecific(d.hostOnlyIpAvailable, 5, 4*time.Second); err != nil { return err } d.IPAddress, err = d.GetIP() return err }
func (provisioner *RancherProvisioner) upgrade() error { switch provisioner.Driver.DriverName() { case "virtualbox": return provisioner.upgradeIso() default: log.Infof("Running upgrade") if _, err := provisioner.SSHCommand("sudo rancherctl os upgrade -f --no-reboot"); err != nil { return err } log.Infof("Upgrade succeeded, rebooting") // ignore errors here because the SSH connection will close provisioner.SSHCommand("sudo reboot") return nil } }
func (b *B2dUtils) DownloadISOFromURL(latestReleaseUrl string) error { log.Infof("Downloading %s to %s...", latestReleaseUrl, b.commonIsoPath) if err := b.DownloadISO(b.imgCachePath, b.isoFilename, latestReleaseUrl); err != nil { return err } return nil }
func cmdRegenerateCerts(c *cli.Context) { force := c.Bool("force") if force || confirmInput("Regenerate TLS machine certs? Warning: this is irreversible.") { log.Infof("Regenerating TLS certificates") if err := runActionWithContext("configureAuth", c); err != nil { log.Fatal(err) } } }
func (d *Driver) Remove() error { client := d.getClient() if resp, err := client.Keys.DeleteByID(d.SSHKeyID); err != nil { if resp.StatusCode == 404 { log.Infof("Digital Ocean SSH key doesn't exist, assuming it is already deleted") } else { return err } } if resp, err := client.Droplets.Delete(d.DropletID); err != nil { if resp.StatusCode == 404 { log.Infof("Digital Ocean droplet doesn't exist, assuming it is already deleted") } else { return err } } return nil }
func (d *Driver) Stop() error { p, err := govcloudair.NewClient() if err != nil { return err } log.Infof("Connecting to vCloud Air...") // Authenticate to vCloud Air v, err := p.Authenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) if err != nil { return err } vapp, err := v.FindVAppByID(d.VAppID) if err != nil { return err } status, err := vapp.GetStatus() if err != nil { return err } if status == "POWERED_ON" { log.Infof("Shutting down %s...", d.MachineName) task, err := vapp.Shutdown() if err != nil { return err } if err = task.WaitTaskCompletion(); err != nil { return err } } if err = p.Disconnect(); err != nil { return err } d.IPAddress = "" return nil }
func (d *Driver) waitTask(task *xsclient.Task, timeout time.Duration) error { timeout_at := time.Now().Add(timeout) for { status, err := task.GetStatus() if err != nil { return fmt.Errorf("Failed to get task status: %s", err.Error()) } if status == xsclient.Success { log.Infof("Upload VDI task(%s) completed", task.Ref) break } switch status { case xsclient.Pending: progress, err := task.GetProgress() if err != nil { return fmt.Errorf("Failed to get progress: %s", err.Error()) } log.Debugf("Upload %.0f%% complete", progress*100) log.Infof("Uploading...") case xsclient.Failure: errorInfo, err := task.GetErrorInfo() if err != nil { errorInfo = []string{fmt.Sprintf("furthermore, failed to get error info: %s", err.Error())} } return fmt.Errorf("Task failed: %s", errorInfo) case xsclient.Cancelling, xsclient.Cancelled: return fmt.Errorf("Task Cancelled") default: return fmt.Errorf("Unknown task status %v", status) } if time.Now().After(timeout_at) { return fmt.Errorf("Upload VDI task(%s) timed out", task.Ref) } time.Sleep(5 * time.Second) } return nil }
// Create creates a GCE VM instance acting as a docker host. func (d *Driver) Create() error { c, err := newComputeUtil(d) if err != nil { return err } log.Infof("Creating host...") // Check if the instance already exists. There will be an error if the instance // doesn't exist, so just check instance for nil. if instance, _ := c.instance(); instance != nil { return fmt.Errorf("Instance %v already exists.", d.MachineName) } log.Infof("Generating SSH Key") if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { return err } return c.createInstance(d) }
func (d *Driver) Start() error { log.Infof("Starting %s...", d.MachineName) vmrun("start", d.vmxPath(), "nogui") log.Debugf("Mounting Shared Folders...") if err := d.setupSharedDirs(); err != nil { return err } return nil }
func (d *Driver) wait() error { log.Infof("Waiting for host to start...") for { ip, _ := d.GetIP() if ip != "" { break } time.Sleep(1 * time.Second) } return nil }
func (d *Driver) generateDiskImage() error { // Create a small fixed vhd, put the tar in, // convert to dynamic, then resize d.diskImage = d.ResolveStorePath("disk.vhd") fixed := d.ResolveStorePath("fixed.vhd") log.Infof("Creating VHD") command := []string{ "New-VHD", "-Path", fmt.Sprintf("'%s'", fixed), "-SizeBytes", "10MB", "-Fixed"} _, err := execute(command) if err != nil { return err } tarBuf, err := d.generateTar() if err != nil { return err } file, err := os.OpenFile(fixed, os.O_WRONLY, 0644) if err != nil { return err } defer file.Close() file.Seek(0, os.SEEK_SET) _, err = file.Write(tarBuf.Bytes()) if err != nil { return err } file.Close() command = []string{ "Convert-VHD", "-Path", fmt.Sprintf("'%s'", fixed), "-DestinationPath", fmt.Sprintf("'%s'", d.diskImage), "-VHDType", "Dynamic"} _, err = execute(command) if err != nil { return err } command = []string{ "Resize-VHD", "-Path", fmt.Sprintf("'%s'", d.diskImage), "-SizeBytes", fmt.Sprintf("%dMB", d.diskSize)} _, err = execute(command) if err != nil { return err } return err }
func (d *Driver) wait(timeout time.Duration) (err error) { log.Infof("Waiting for VM to start...") ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() out := make(chan error, 1) go func(ctx context.Context, out chan<- error) { var ip string for { ip, _ = d.GetIP() if ip != "" { break } if t, ok := ctx.Deadline(); ok && time.Now().After(t) { out <- fmt.Errorf("Wait GetIP timed out") return } time.Sleep(1 * time.Second) } port, err := d.GetSSHPort() if err != nil { out <- err return } addr := fmt.Sprintf("%s:%d", ip, port) log.Infof("Got VM address(%v), Now waiting for SSH", addr) out <- ssh.WaitForTCP(addr) }(ctx, out) select { case err := <-out: return err case <-ctx.Done(): return fmt.Errorf("Wait for VM to start timed out: %v", ctx.Err()) } return nil }
func (d *Driver) Remove() error { s, _ := d.GetState() if s == state.Running { if err := d.Kill(); err != nil { return fmt.Errorf("Error stopping VM before deletion") } } log.Infof("Deleting %s...", d.MachineName) vmrun("deleteVM", d.vmxPath(), "nogui") return nil }
func (d *Driver) Remove() error { log.Infof("Canceling SoftLayer instance %d...", d.Id) var err error for i := 0; i < 5; i++ { if err = d.getClient().VirtualGuest().Cancel(d.Id); err != nil { time.Sleep(2 * time.Second) continue } break } if err != nil { return err } log.Infof("Removing SSH Key %d...", d.SSHKeyID) if err = d.getClient().SshKey().Delete(d.SSHKeyID); err != nil { return err } return nil }