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 }
// execute command over SSH with user / password authentication func executeSSHCommand(command string, d *Driver) error { log.Debugf("Execute executeSSHCommand: %s", command) config := &cryptossh.ClientConfig{ User: d.SSHUser, Auth: []cryptossh.AuthMethod{ cryptossh.Password(d.SSHPassword), }, } client, err := cryptossh.Dial("tcp", fmt.Sprintf("%s:%d", d.IPAddress, d.SSHPort), config) if err != nil { log.Debugf("Failed to dial:", err) return err } session, err := client.NewSession() if err != nil { log.Debugf("Failed to create session: " + err.Error()) return err } defer session.Close() var b bytes.Buffer session.Stdout = &b if err := session.Run(command); err != nil { log.Debugf("Failed to run: " + err.Error()) return err } log.Debugf("Stdout from executeSSHCommand: %s", b.String()) return nil }
func (d *Driver) GetIP() (string, error) { s, err := d.GetState() if err != nil { return "", err } if s != state.Running { return "", drivers.ErrHostIsNotRunning } c, err := NewClient("http://localhost:" + strconv.Itoa(d.APIPort)) if err != nil { return "", err } var ip string for i := 1; i <= 60; i++ { vmip, err := c.GetVMIPAddress(d.MachineName) if err != nil && vmip.Code != 200 { log.Debugf("Not there yet %d/%d, error code: %d, message %s", i, 60, vmip.Code, err) time.Sleep(2 * time.Second) continue } ip = vmip.Message log.Debugf("Got an ip: %s", ip) break } if ip == "" { return "", fmt.Errorf("machine didn't return an IP after 120 seconds, aborting") } return ip, nil }
func sshAvailableFunc(d Driver) func() bool { return func() bool { log.Debug("Getting to WaitForSSH function...") hostname, err := d.GetSSHHostname() if err != nil { log.Debugf("Error getting IP address waiting for SSH: %s", err) return false } port, err := d.GetSSHPort() if err != nil { log.Debugf("Error getting SSH port: %s", err) return false } if err := ssh.WaitForTCP(fmt.Sprintf("%s:%d", hostname, port)); err != nil { log.Debugf("Error waiting for TCP waiting for SSH: %s", err) return false } if _, err := RunSSHCommandFromDriver(d, "exit 0"); err != nil { log.Debugf("Error getting ssh command 'exit 0' : %s", err) return false } return true } }
func (d *Driver) mountSharedFolder(shareDir, shareName string) error { // create mountpoint and mount shared folder addr, err := d.GetSSHHostname() if err != nil { return err } port, err := d.GetSSHPort() if err != nil { return err } auth := &ssh.Auth{ Keys: []string{d.GetSSHKeyPath()}, } client, err := ssh.NewClient(d.GetSSHUsername(), addr, port, auth) if err != nil { return err } command := "[ ! -d " + shareDir + " ]&& sudo mkdir " + shareDir + "; sudo mount -t vmhgfs .host:/" + shareName + " " + shareDir log.Debugf("About to run SSH command:\n%s", command) output, err := client.Output(command) log.Debugf("SSH cmd err, output: %v: %s", err, output) return err }
func (d *Driver) addDockerEndpoints(vmConfig *vmClient.Role) error { configSets := vmConfig.ConfigurationSets.ConfigurationSet if len(configSets) == 0 { return errors.New("no configuration set") } for i := 0; i < len(configSets); i++ { if configSets[i].ConfigurationSetType != "NetworkConfiguration" { continue } ep := vmClient.InputEndpoint{ Name: "docker", Protocol: "tcp", Port: d.DockerPort, LocalPort: d.DockerPort, } if d.SwarmMaster { swarm_ep := vmClient.InputEndpoint{ Name: "docker swarm", Protocol: "tcp", Port: d.DockerSwarmMasterPort, LocalPort: d.DockerSwarmMasterPort, } configSets[i].InputEndpoints.InputEndpoint = append(configSets[i].InputEndpoints.InputEndpoint, swarm_ep) log.Debugf("added Docker swarm master endpoint (port %d) to configuration", d.DockerSwarmMasterPort) } configSets[i].InputEndpoints.InputEndpoint = append(configSets[i].InputEndpoints.InputEndpoint, ep) log.Debugf("added Docker endpoint (port %d) to configuration", d.DockerPort) } 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) } }
// Fix the routing rules func fixRoutingRules(sshClient ssh.Client) { output, err := sshClient.Output("route del -net 172.16.0.0/12") log.Debugf("Delete route command err, output: %v: %s", err, output) output, err = sshClient.Output("if [ -e /etc/network/interfaces ]; then sed -i -r 's/^(up route add \\-net 172\\.16\\.0\\.0\\..*)$/#\\1/' /etc/network/interfaces; fi") log.Debugf("Fix route in /etc/network/interfaces command err, output: %v: %s", err, output) output, err = sshClient.Output("if [ -e /etc/sysconfig/network-scripts/route-eth0 ]; then sed -i -r 's/^(172\\.16\\.0\\.0\\..* dev eth0)$/#\\1/' /etc/sysconfig/network-scripts/route-eth0; fi") log.Debugf("Fix route in /etc/sysconfig/network-scripts/route-eth0 command err, output: %v: %s", err, output) }
func execute(args []string) (string, error) { cmd := exec.Command(powershell, args...) log.Debugf("[executing ==>] : %v %v", powershell, strings.Join(args, " ")) var stdout bytes.Buffer var stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr err := cmd.Run() log.Debugf("[stdout =====>] : %s", stdout.String()) log.Debugf("[stderr =====>] : %s", stderr.String()) return stdout.String(), err }
func RunSSHCommandFromDriver(d Driver, command string) (string, error) { client, err := GetSSHClientFromDriver(d) if err != nil { return "", err } log.Debugf("About to run SSH command:\n%s", command) output, err := client.Output(command) log.Debugf("SSH cmd err, output: %v: %s", err, output) return output, err }
func (d *Driver) hostOnlyIpAvailable() bool { ip, err := d.GetIP() if err != nil { log.Debugf("ERROR getting IP: %s", err) return false } if ip != "" { log.Debugf("IP is %s", ip) return true } log.Debug("Strangely, there was no error attempting to get the IP, but it was still empty.") return false }
func (fwp *FirewallPolicy) WaitUntilDeleted() error { exists := true var err error for exists { exists, err = fwp.exists() if err != nil { return err } log.Debugf("Wait for firewall policy: '%s' to be deleted", fwp.Id) time.Sleep(5 * time.Second) } log.Debugf("The firewall policy: '%s' is now deleted", fwp.Id) return nil }
func (d *Driver) Remove() error { if d.InstanceId == "" { return fmt.Errorf("unknown instance") } s, err := d.GetState() if err == nil && s == state.Running { if err := d.Stop(); err != nil { log.Errorf("unable to stop instance: %s", err) } } instance, err := d.getInstance() if err != nil { log.Errorf("unable to describe instance: %s", err) } else { // Check and release EIP if exists if len(instance.EipAddress.AllocationId) != 0 { allocationId := instance.EipAddress.AllocationId err = d.getClient().UnassociateEipAddress(allocationId, instance.InstanceId) if err != nil { log.Errorf("Failed to unassociate EIP address: %v", err) } err = d.getClient().WaitForEip(instance.RegionId, allocationId, ecs.EipStatusAvailable, 0) if err != nil { log.Errorf("Failed to wait EIP %s: %v", allocationId, err) } err = d.getClient().ReleaseEipAddress(allocationId) if err != nil { log.Errorf("Failed to release EIP address: %v", err) } } log.Debugf("instance: %++v\n", instance) log.Debugf("instance.VpcAttributes: %++v\n", instance.VpcAttributes) vpcId := instance.VpcAttributes.VpcId if vpcId != "" { // Remove route entry firstly d.removeRouteEntry(vpcId, instance.RegionId, instance.InstanceId) } } log.Debugf("terminating instance: %s", d.InstanceId) if err := d.getClient().DeleteInstance(d.InstanceId); err != nil { return fmt.Errorf("unable to terminate instance: %s", err) } return nil }
func (server *Server) WaitUntilDeleted() error { exists := true var err error for exists { exists, err = server.exists() if err != nil { return err } log.Debugf("Wait for server: '%s' to be deleted", server.Id) time.Sleep(5 * time.Second) } log.Debugf("The server: '%s' is now deleted", server.Id) return nil }
func (d *Driver) Restart() error { if err := d.Stop(); err != nil { return err } // Check for 120 seconds for the machine to stop for i := 1; i <= 60; i++ { machineState, err := d.GetState() if err != nil { return err } if machineState == state.Running { log.Debugf("Not there yet %d/%d", i, 60) time.Sleep(2 * time.Second) continue } if machineState == state.Stopped { break } } machineState, err := d.GetState() // If the VM is still running after 120 seconds just kill it. if machineState == state.Running { if err = d.Kill(); err != nil { return fmt.Errorf("can't stop VM: %s", err) } } return d.Start() }
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 (d *Driver) GetIP() (string, error) { // DHCP is used to get the IP, so virtualbox hosts don't have IPs unless // they are running s, err := d.GetState() if err != nil { return "", err } if s != state.Running { return "", drivers.ErrHostIsNotRunning } output, err := drivers.RunSSHCommandFromDriver(d, "ip addr show dev eth1") if err != nil { return "", err } log.Debugf("SSH returned: %s\nEND SSH\n", output) // parse to find: inet 192.168.59.103/24 brd 192.168.59.255 scope global eth1 lines := strings.Split(output, "\n") for _, line := range lines { vals := strings.Split(strings.TrimSpace(line), " ") if len(vals) >= 2 && vals[0] == "inet" { return vals[1][:strings.Index(vals[1], "/")], nil } } return "", fmt.Errorf("No IP address found %s", output) }
func (client NativeClient) dialSuccess() bool { if _, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", client.Hostname, client.Port), &client.Config); err != nil { log.Debugf("Error dialing TCP: %s", err) return false } return true }
func (d *Driver) buildHostSpec() *HostSpec { spec := &HostSpec{ Hostname: d.deviceConfig.Hostname, Domain: d.deviceConfig.Domain, Cpu: d.deviceConfig.Cpu, Memory: d.deviceConfig.Memory, Datacenter: Datacenter{Name: d.deviceConfig.Region}, Os: d.deviceConfig.Image, HourlyBilling: d.deviceConfig.HourlyBilling, PrivateNetOnly: d.deviceConfig.PrivateNet, LocalDisk: d.deviceConfig.LocalDisk, } if d.deviceConfig.DiskSize > 0 { spec.BlockDevices = []BlockDevice{{Device: "0", DiskImage: DiskImage{Capacity: d.deviceConfig.DiskSize}}} } if d.deviceConfig.PublicVLAN > 0 { spec.PrimaryNetworkComponent = &NetworkComponent{ NetworkVLAN: &NetworkVLAN{ Id: d.deviceConfig.PublicVLAN, }, } } if d.deviceConfig.PrivateVLAN > 0 { spec.PrimaryBackendNetworkComponent = &NetworkComponent{ NetworkVLAN: &NetworkVLAN{ Id: d.deviceConfig.PrivateVLAN, }, } } log.Debugf("Built host spec %#v", spec) return spec }
func (d *Driver) configureSecurityGroup(groupName string) error { log.Debugf("configuring security group in %s", d.VpcId) var securityGroup *amz.SecurityGroup groups, err := d.getClient().GetSecurityGroups() if err != nil { return err } for _, grp := range groups { if grp.GroupName == groupName { log.Debugf("found existing security group (%s) in %s", groupName, d.VpcId) securityGroup = &grp break } } // if not found, create if securityGroup == nil { log.Debugf("creating security group (%s) in %s", groupName, d.VpcId) group, err := d.getClient().CreateSecurityGroup(groupName, "Docker Machine", d.VpcId) if err != nil { return err } securityGroup = group // wait until created (dat eventual consistency) log.Debugf("waiting for group (%s) to become available", group.GroupId) if err := utils.WaitFor(d.securityGroupAvailableFunc(group.GroupId)); err != nil { return err } } d.SecurityGroupId = securityGroup.GroupId perms := d.configureSecurityGroupPermissions(securityGroup) if len(perms) != 0 { log.Debugf("authorizing group %s with permissions: %v", securityGroup.GroupName, perms) if err := d.getClient().AuthorizeSecurityGroup(d.SecurityGroupId, perms); err != nil { return err } } 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) deleteKeyPair() error { log.Debugf("deleting key pair: %s", d.KeyName) if err := d.getClient().DeleteKeyPair(d.KeyName); err != nil { return err } return nil }
func (d *Driver) deleteSecurityGroup() error { log.Debugf("deleting security group %s", d.SecurityGroupId) if err := d.getClient().DeleteSecurityGroup(d.SecurityGroupId); err != nil { return err } return nil }
// GET /servers/{id}/status func (s *Server) GetStatus() (*Status, error) { log.Debugf("Requesting server status for server: '%s'", s.Id) result := new(Status) err := s.api.Client.Get(createUrl(s.api, "servers", s.Id, "status"), &result, http.StatusOK) if err != nil { return nil, err } return result, nil }
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 (provisioner *DebianProvisioner) Package(name string, action pkgaction.PackageAction) error { var packageAction string updateMetadata := true switch action { case pkgaction.Install, pkgaction.Upgrade: packageAction = "install" case pkgaction.Remove: packageAction = "remove" updateMetadata = false } switch name { case "docker": name = "docker-engine" } if updateMetadata { if _, err := provisioner.SSHCommand("sudo apt-get update"); err != nil { return err } } // handle the new docker-engine package; we can probably remove this // after we have a few versions if action == pkgaction.Upgrade && name == "docker-engine" { // run the force remove on the existing lxc-docker package // and remove the existing apt source list // also re-run the get.docker.com script to properly setup // the system again commands := []string{ "rm /etc/apt/sources.list.d/docker.list || true", "apt-get remove -y lxc-docker || true", "curl -sSL https://get.docker.com | sh", } for _, cmd := range commands { command := fmt.Sprintf("sudo DEBIAN_FRONTEND=noninteractive %s", cmd) if _, err := provisioner.SSHCommand(command); err != nil { return err } } } command := fmt.Sprintf("DEBIAN_FRONTEND=noninteractive sudo -E apt-get %s -y %s", packageAction, name) log.Debugf("package: action=%s name=%s", action.String(), name) if _, err := provisioner.SSHCommand(command); err != nil { return err } return nil }
// DELETE /load_balancers/{id} func (lb *LoadBalancer) Delete() (*LoadBalancer, error) { log.Debugf("Deleting load balancer: '%s'", lb.Id) result := new(LoadBalancer) err := lb.api.Client.Delete(createUrl(lb.api, "load_balancers", lb.Id), &result, http.StatusAccepted) if err != nil { return nil, err } result.api = lb.api return result, nil }
// GET /load_balancers/{id} func (api *API) GetLoadBalancer(id string) (*LoadBalancer, error) { log.Debugf("Requesting information about load balancer: '%s'", id) result := new(LoadBalancer) err := api.Client.Get(createUrl(api, "load_balancers", id), &result, http.StatusOK) if err != nil { return nil, err } result.api = api return result, nil }
// POST /load_balancers func (api *API) CreateLoadBalancer(loadBalancer LoadBalancer) (*LoadBalancer, error) { log.Debugf("Creating new load balancer: '%s'", loadBalancer.Name) result := new(LoadBalancer) err := api.Client.Post(createUrl(api, "load_balancers"), &loadBalancer, &result, http.StatusAccepted) if err != nil { return nil, err } result.api = api return result, nil }
// PUT /load_balancers/{id} func (lb *LoadBalancer) Update(loadBalancerUpdate LoadBalancerUpdate) (*LoadBalancer, error) { log.Debugf("Updateing load balancer configuration for: '%s'", lb.Id) result := new(LoadBalancer) err := lb.api.Client.Put(createUrl(lb.api, "load_balancers", lb.Id), &loadBalancerUpdate, &result, http.StatusAccepted) if err != nil { return nil, err } result.api = lb.api return result, nil }