func init() { token, err := getEnvironmentVar("token") if err != nil { log.Error("The 1&1 cloud server api token must be set in the environment variable 'token'") os.Exit(1) } apiEndpoint, err := getEnvironmentVar("endpoint") if err != nil { log.Error("The 1&1 cloud server api endpoint must be set in the environment variable 'endpoint'") os.Exit(1) } api = oaocs.New(token, apiEndpoint) }
// runActionForeachMachine will run the command across multiple machines func runActionForeachMachine(actionName string, machines []*libmachine.Host) { var ( numConcurrentActions = 0 serialMachines = []*libmachine.Host{} errorChan = make(chan error) ) for _, machine := range machines { // Virtualbox is temperamental about doing things concurrently, // so we schedule the actions in a "queue" to be executed serially // after the concurrent actions are scheduled. switch machine.DriverName { case "virtualbox": machine := machine serialMachines = append(serialMachines, machine) default: numConcurrentActions++ go machineCommand(actionName, machine, errorChan) } } // While the concurrent actions are running, // do the serial actions. As the name implies, // these run one at a time. for _, machine := range serialMachines { serialChan := make(chan error) go machineCommand(actionName, machine, serialChan) if err := <-serialChan; err != nil { log.Error(err) } close(serialChan) } // TODO: We should probably only do 5-10 of these // at a time, since otherwise cloud providers might // rate limit us. for i := 0; i < numConcurrentActions; i++ { if err := <-errorChan; err != nil { log.Error(err) } } close(errorChan) }
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) if err != nil && !isErr255Exit(err) { log.Error("SSH cmd error!") log.Errorf("command: %s", command) log.Errorf("err : %v", err) log.Fatalf("output : %s", output) } return output, err }
func (d *Driver) Create() error { b2dutils := utils.NewB2dUtils("", "", isoFilename) 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 } 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.GetIP() 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 // use ssh to set keys sshClient, err := d.getLocalSSHClient() if err != nil { return err } // add pub key for user pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath()) if err != nil { return err } if out, err := sshClient.Output(fmt.Sprintf( "mkdir -p /home/%s/.ssh", d.GetSSHUsername(), )); err != nil { log.Error(out) return err } if out, err := sshClient.Output(fmt.Sprintf( "printf '%%s' '%s' | tee /home/%s/.ssh/authorized_keys", string(pubKey), d.GetSSHUsername(), )); err != nil { log.Error(out) return err } // Enable Shared Folders vmrun("-gu", B2DUser, "-gp", B2DPass, "enableSharedFolders", d.vmxPath()) if err := d.setupSharedDirs(); err != nil { return err } return nil }
func (d *Driver) Create() error { if err := d.checkPrereqs(); err != nil { return err } log.Infof("Creating key pair for instances...") if err := d.createKeyPair(); err != nil { return fmt.Errorf("unable to create key pair: %s", err) } log.Infof("Configuring security groups...") if err := d.configureSecurityGroup(d.SecurityGroupName); err != nil { return err } // TODO Support data disk if d.SSHPassword == "" { d.SSHPassword = randomPassword() log.Info("Launching instance with generated password, please update password in console or log in with ssh key.") } imageID := d.GetImageID(d.ImageID) log.Infof("Launching instance with image %s ...", imageID) args := ecs.CreateInstanceArgs{ RegionId: d.Region, ImageId: imageID, InstanceType: d.InstanceType, SecurityGroupId: d.SecurityGroupId, Password: d.SSHPassword, VSwitchId: d.VSwitchId, ClientToken: d.getClient().GenerateClientToken(), } // Set InternetMaxBandwidthOut only for classic network if d.VSwitchId == "" { args.InternetMaxBandwidthOut = d.InternetMaxBandwidthOut } //log.Debugf("CreateInstanceArgs: %++v", args) // Create instance instanceId, err := d.getClient().CreateInstance(&args) if err != nil { err = fmt.Errorf("Error create instance: %s", err) log.Error(err) return err } d.InstanceId = instanceId // Wait for creation successfully err = d.getClient().WaitForInstance(instanceId, ecs.Stopped, 300) if err != nil { err = fmt.Errorf("Error wait instance to Stopped: %s", err) log.Error(err) } // Assign public IP if not private IP only if err == nil && !d.PrivateIPOnly { if d.VSwitchId == "" { // Allocate public IP address for classic network _, err = d.getClient().AllocatePublicIpAddress(instanceId) if err != nil { err = fmt.Errorf("Error allocate public IP address for instance %s: %v", instanceId, err) } } else { err = d.configNetwork(instanceId) } } if err == nil { // Start instance err = d.getClient().StartInstance(instanceId) if err == nil { // Wait for running err = d.getClient().WaitForInstance(instanceId, ecs.Running, 300) if err == nil { instance, err := d.getInstance() if err == nil { if len(instance.InnerIpAddress.IpAddress) > 0 { d.PrivateIPAddress = instance.InnerIpAddress.IpAddress[0] } d.IPAddress = d.getIP(instance) ssh.SetDefaultClient(ssh.Native) d.uploadKeyPair() log.Debugf("created instance ID %s, IP address %s, Private IP address %s", d.InstanceId, d.IPAddress, d.PrivateIPAddress, ) } } else { err = fmt.Errorf("Failed to wait instance to running state: %s", err) } } else { err = fmt.Errorf("Failed to start instance %s: %v", instanceId, err) } } if err != nil { log.Warn(err) d.Remove() } return err }
func (d *Driver) Create() error { err := hypervAvailable() if err != nil { return err } d.setMachineNameIfNotSet() b2dutils := utils.NewB2dUtils("", "", isoFilename) 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 } if err := d.generateDiskImage(); 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(isoFilename))} if _, err = execute(command); err != nil { return err } command = []string{ "Add-VMHardDiskDrive", "-VMName", d.MachineName, "-Path", fmt.Sprintf("'%s'", d.diskImage)} if _, err = execute(command); err != nil { return err } command = []string{ "Connect-VMNetworkAdapter", "-VMName", d.MachineName, "-SwitchName", fmt.Sprintf("'%s'", virtualSwitch)} if _, err = execute(command); err != nil { return err } log.Infof("Starting VM...") if err := d.Start(); err != nil { return err } // use ssh to set keys sshClient, err := d.getLocalSSHClient() if err != nil { return err } // add pub key for user pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath()) if err != nil { return err } if out, err := sshClient.Output(fmt.Sprintf( "mkdir -p /home/%s/.ssh", d.GetSSHUsername(), )); err != nil { log.Error(out) return err } if out, err := sshClient.Output(fmt.Sprintf( "printf '%%s' '%s' | tee /home/%s/.ssh/authorized_keys", string(pubKey), d.GetSSHUsername(), )); err != nil { log.Error(out) return err } return nil }
func (d *Driver) Create() error { var ( err error ) // Check that VBoxManage exists and works if err = vbm(); err != nil { return err } b2dutils := utils.NewB2dUtils("", "", isoFilename) 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 _ = vbm("controlvm", name, "poweroff") diskInfo, err := getVMDiskInfo(name) if err != nil { return err } if _, err := os.Stat(diskInfo.Path); err != nil { return err } if err := vbm("clonehd", diskInfo.Path, d.diskPath()); err != nil { return err } log.Debugf("Importing VM settings...") vmInfo, err := getVMInfo(name) if err != nil { return err } d.CPU = vmInfo.CPUs d.Memory = vmInfo.Memory log.Debugf("Importing SSH key...") keyPath := filepath.Join(utils.GetHomeDir(), ".ssh", "id_boot2docker") if err := utils.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 := vbm("createhd", "--size", fmt.Sprintf("%d", d.DiskSize), "--format", "VMDK", "--filename", d.diskPath()); err != nil { return err } } if err := 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 := 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 := 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 := vbm("storagectl", d.MachineName, "--name", "SATA", "--add", "sata", "--hostiocache", "on"); err != nil { return err } if err := vbm("storageattach", d.MachineName, "--storagectl", "SATA", "--port", "0", "--device", "0", "--type", "dvddrive", "--medium", d.ResolveStorePath(isoFilename)); err != nil { return err } if err := vbm("storageattach", d.MachineName, "--storagectl", "SATA", "--port", "1", "--device", "0", "--type", "hdd", "--medium", d.diskPath()); err != nil { return err } shareDir := homedir.Get() shareName := shareDir log.Debugf("creating share: path=%s", shareDir) // let VBoxService do nice magic automounting (when it's used) if err := vbm("guestproperty", "set", d.MachineName, "/VirtualBox/GuestAdd/SharedFolders/MountDir", "/"); err != nil { return err } if err := vbm("guestproperty", "set", d.MachineName, "/VirtualBox/GuestAdd/SharedFolders/MountPrefix", "/"); err != nil { return err } if shareDir != "" { log.Debugf("setting up shareDir") if _, err := os.Stat(shareDir); err != nil && !os.IsNotExist(err) { log.Debugf("setting up share failed: %s", err) return err } else if !os.IsNotExist(err) { // parts of the VBox internal code are buggy with share names that start with "/" shareName = strings.TrimLeft(shareDir, "/") // translate to msys git path if runtime.GOOS == "windows" { mountName, err := translateWindowsMount(shareDir) if err != nil { return err } shareName = mountName } log.Debugf("adding shared folder: name=%q dir=%q", shareName, shareDir) // woo, shareDir exists! let's carry on! if err := vbm("sharedfolder", "add", d.MachineName, "--name", shareName, "--hostpath", shareDir, "--automount"); err != nil { return err } // enable symlinks if err := vbm("setextradata", d.MachineName, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/"+shareName, "1"); err != nil { return err } } } log.Infof("Starting VirtualBox VM...") if err := d.Start(); err != nil { return err } // use ssh to set keys sshClient, err := d.getLocalSSHClient() if err != nil { return err } // add pub key for user pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath()) if err != nil { return err } if out, err := sshClient.Output(fmt.Sprintf( "mkdir -p /home/%s/.ssh", d.GetSSHUsername(), )); err != nil { log.Error(out) return err } if out, err := sshClient.Output(fmt.Sprintf( "printf '%%s' '%s' | tee /home/%s/.ssh/authorized_keys", string(pubKey), d.GetSSHUsername(), )); err != nil { log.Error(out) return err } ip, err := d.GetIP() if err != nil { return err } d.IPAddress = ip return nil }