func (b *B2dUtils) CopyIsoToMachineDir(isoURL, machineName string) error { // TODO: This is a bit off-color. machineDir := filepath.Join(b.artifactPath, "machines", machineName) machineIsoPath := filepath.Join(machineDir, 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(machineDir, b.isoFilename, isoURL); err != nil { return err } } return nil }
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 }
// 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) }
// 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) }
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 (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) 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) 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 (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 (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 := mcnutils.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 (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 }
// 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) generateDiskImage() error { // Create a small fixed vhd, put the tar in, // convert to dynamic, then resize d.diskImage = d.LocalArtifactPath("disk.vhd") fixed := d.LocalArtifactPath("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() 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) 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 }
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) b2dutils := mcnutils.NewB2dUtils("", "", provisioner.Driver.GlobalArtifactPath()) 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 (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: Replace this with asking for where the local artifact path is. b2dutils := mcnutils.NewB2dUtils("", "", provisioner.Driver.GlobalArtifactPath()) // 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 { log.Infof("Importing SSH key...") if err := mcnutils.CopyFile(d.SSHKey, d.GetSSHKeyPath()); err != nil { return fmt.Errorf("unable to copy ssh key: %s", err) } if err := os.Chmod(d.GetSSHKeyPath(), 0600); err != nil { return err } log.Debugf("IP: %s", d.IPAddress) return nil }
func (d *Driver) waitForStart() { log.Infof("Waiting for host to become available") for { s, err := d.GetState() if err != nil { log.Debugf("Failed to GetState - %+v", err) continue } if s == state.Running { break } else { log.Debugf("Still waiting - state is %s...", s) } time.Sleep(2 * time.Second) } }
func (d *Driver) chooseVirtualSwitch() (string, error) { if d.vSwitch != "" { return d.vSwitch, nil } command := []string{ "@(Get-VMSwitch).Name"} stdout, err := execute(command) if err != nil { return "", err } switches := parseStdout(stdout) if len(switches) > 0 { log.Infof("Using switch %s", switches[0]) return switches[0], nil } return "", fmt.Errorf("no vswitch found") }
func (d *Driver) Remove() error { s, err := d.GetState() if err != nil { if err == ErrMachineNotExist { log.Infof("machine does not exist, assuming it has been removed already") return nil } return err } if s == state.Running { if err := d.Stop(); err != nil { return err } } // vbox will not release it's lock immediately after the stop time.Sleep(1 * time.Second) return vbm("unregistervm", "--delete", d.MachineName) }
func (c *ComputeUtil) createFirewallRule() error { log.Infof("Creating firewall rule.") allowed := []*raw.FirewallAllowed{ { IPProtocol: "tcp", Ports: []string{ port, }, }, } if c.SwarmMaster { u, err := url.Parse(c.SwarmHost) if err != nil { return fmt.Errorf("error authorizing port for swarm: %s", err) } parts := strings.Split(u.Host, ":") swarmPort := parts[1] allowed = append(allowed, &raw.FirewallAllowed{ IPProtocol: "tcp", Ports: []string{ swarmPort, }, }) } rule := &raw.Firewall{ Allowed: allowed, SourceRanges: []string{ "0.0.0.0/0", }, TargetTags: []string{ firewallTargetTag, }, Name: firewallRule, } op, err := c.service.Firewalls.Insert(c.project, rule).Do() if err != nil { return err } return c.waitForGlobalOp(op.Name) }
func (d *Driver) Kill() error { if err := d.setUserSubscription(); err != nil { return err } if vmState, err := d.GetState(); err != nil { return err } else if vmState == state.Stopped { log.Infof("Host is already stopped") return nil } log.Debugf("killing %s", d.MachineName) if err := vmClient.ShutdownRole(d.MachineName, d.MachineName, d.MachineName); err != nil { return err } d.IPAddress = "" return nil }
func (d *Driver) Start() error { if err := d.setUserSubscription(); err != nil { return err } if vmState, err := d.GetState(); err != nil { return err } else if vmState == state.Running || vmState == state.Starting { log.Infof("Host is already running or starting") return nil } log.Debugf("starting %s", d.MachineName) if err := vmClient.StartRole(d.MachineName, d.MachineName, d.MachineName); err != nil { return err } var err error d.IPAddress, err = d.GetIP() return err }
func tokenFromWeb(config *oauth.Config) *oauth.Token { randState := fmt.Sprintf("st%d", time.Now().UnixNano()) config.RedirectURL = RedirectURI authURL := config.AuthCodeURL(randState) log.Info("Opening auth URL in browser.") log.Info(authURL) log.Info("If the URL doesn't open please open it manually and copy the code here.") openURL(authURL) code := getCodeFromStdin() log.Infof("Got code: %s", code) t := &oauth.Transport{ Config: config, Transport: http.DefaultTransport, } _, err := t.Exchange(code) if err != nil { log.Fatalf("Token exchange error: %v", err) } return t.Token }
func (d *Driver) Create() error { err := hypervAvailable() if err != nil { return err } d.setMachineNameIfNotSet() var isoURL string 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...") 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.LocalArtifactPath(".")), "-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.LocalArtifactPath("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 }