// uploadKeyPair upload the public key to docker-machine func (d *Driver) uploadKeyPair() error { ipAddr, err := d.GetIP() if err != nil { return err } port, _ := d.GetSSHPort() auth := ssh.Auth{ Passwords: []string{d.Password}, } ssh.SetDefaultClient(ssh.Native) sshClient, err := ssh.NewClient(d.GetSSHUsername(), ipAddr, port, &auth) if err != nil { return err } d.waitForSSHFunc(sshClient, "exit 0") publicKey, err := ioutil.ReadFile(d.GetSSHKeyPath() + ".pub") if err != nil { return err } command := fmt.Sprintf("mkdir -p ~/.ssh; echo '%s' > ~/.ssh/authorized_keys", string(publicKey)) log.Debugf("Upload the public key with command: %s", command) output, err := sshClient.Output(command) if err != nil { log.Debugf("Upload command err, output: %v: %s", err, output) return err } return nil }
func fatalOnError(command func(commandLine CommandLine, api libmachine.API) error) func(context *cli.Context) { return func(context *cli.Context) { api := libmachine.NewClient(mcndirs.GetBaseDir()) if context.GlobalBool("native-ssh") { api.SSHClientType = ssh.Native } api.GithubAPIToken = context.GlobalString("github-api-token") api.Filestore.Path = context.GlobalString("storage-path") crashreport.Configure(context.GlobalString("bugsnag-api-token")) // TODO (nathanleclaire): These should ultimately be accessed // through the libmachine client by the rest of the code and // not through their respective modules. For now, however, // they are also being set the way that they originally were // set to preserve backwards compatibility. mcndirs.BaseDir = api.Filestore.Path mcnutils.GithubAPIToken = api.GithubAPIToken ssh.SetDefaultClient(api.SSHClientType) defer rpcdriver.CloseDrivers() if err := command(&contextCommandLine{context}, api); err != nil { log.Fatal(err) } } }
func main() { setDebugOutputLevel() ssh.SetDefaultClient(ssh.Native) log.SetFormatter(&SimpleFormatter{}) dockerversion.VERSION = "0.1" dockerversion.GITCOMMIT = "HEAD" if os.Getenv("MACHINE_STORAGE_PATH") == "" { os.Setenv("MACHINE_STORAGE_PATH", ".gattai/machine") } dockerCommands = append(gattaiCommands, dockerCommands...) dockerMain() }
func runCommand(command func(commandLine CommandLine, api libmachine.API) error) func(context *cli.Context) { return func(context *cli.Context) { api := libmachine.NewClient(mcndirs.GetBaseDir(), mcndirs.GetMachineCertDir()) defer api.Close() if context.GlobalBool("native-ssh") { api.SSHClientType = ssh.Native } api.GithubAPIToken = context.GlobalString("github-api-token") api.Filestore.Path = context.GlobalString("storage-path") // TODO (nathanleclaire): These should ultimately be accessed // through the libmachine client by the rest of the code and // not through their respective modules. For now, however, // they are also being set the way that they originally were // set to preserve backwards compatibility. mcndirs.BaseDir = api.Filestore.Path mcnutils.GithubAPIToken = api.GithubAPIToken ssh.SetDefaultClient(api.SSHClientType) if err := command(&contextCommandLine{context}, api); err != nil { log.Error(err) if crashErr, ok := err.(crashreport.CrashError); ok { crashReporter := crashreport.NewCrashReporter(mcndirs.GetBaseDir(), context.GlobalString("bugsnag-api-token")) crashReporter.Send(crashErr) if _, ok := crashErr.Cause.(mcnerror.ErrDuringPreCreate); ok { osExit(3) return } } osExit(1) return } } }
func main() { setDebugOutputLevel() cli.AppHelpTemplate = AppHelpTemplate cli.CommandHelpTemplate = CommandHelpTemplate app := cli.NewApp() app.Name = path.Base(os.Args[0]) app.Author = "Docker Machine Contributors" app.Email = "https://github.com/docker/machine" app.Before = func(c *cli.Context) error { // TODO: Need better handling of config, everything is too // complected together right now. if c.GlobalBool("native-ssh") { ssh.SetDefaultClient(ssh.Native) } mcnutils.GithubApiToken = c.GlobalString("github-api-token") mcndirs.BaseDir = c.GlobalString("storage-path") return nil } app.Commands = commands.Commands app.CommandNotFound = cmdNotFound app.Usage = "Create and manage machines running Docker." app.Version = version.Version + " (" + version.GitCommit + ")" log.Debug("Docker Machine Version: ", app.Version) app.Flags = []cli.Flag{ cli.BoolFlag{ Name: "debug, D", Usage: "Enable debug mode", }, cli.StringFlag{ EnvVar: "MACHINE_STORAGE_PATH", Name: "s, storage-path", Value: mcndirs.GetBaseDir(), Usage: "Configures storage path", }, cli.StringFlag{ EnvVar: "MACHINE_TLS_CA_CERT", Name: "tls-ca-cert", Usage: "CA to verify remotes against", Value: "", }, cli.StringFlag{ EnvVar: "MACHINE_TLS_CA_KEY", Name: "tls-ca-key", Usage: "Private key to generate certificates", Value: "", }, cli.StringFlag{ EnvVar: "MACHINE_TLS_CLIENT_CERT", Name: "tls-client-cert", Usage: "Client cert to use for TLS", Value: "", }, cli.StringFlag{ EnvVar: "MACHINE_TLS_CLIENT_KEY", Name: "tls-client-key", Usage: "Private key used in client TLS auth", Value: "", }, cli.StringFlag{ EnvVar: "MACHINE_GITHUB_API_TOKEN", Name: "github-api-token", Usage: "Token to use for requests to the Github API", Value: "", }, cli.BoolFlag{ EnvVar: "MACHINE_NATIVE_SSH", Name: "native-ssh", Usage: "Use the native (Go-based) SSH implementation.", }, } go commands.DeferClosePluginServers() // Cleanup to run in case the user sends an interrupt (CTRL+C) to the // Machine program. Ensure that we do not leave dangling OS processes. signalCh := make(chan os.Signal, 1) signal.Notify(signalCh, os.Interrupt) // Atypical exit condition -- write to the cleanup done channel after // ensuring that we have closed all exec-ed plugin servers. go func() { for range signalCh { log.Info("\nReceieved an interrupt, performing cleanup work...") close(commands.RpcClientDriversCh) <-commands.RpcDriversClosedCh os.Exit(1) } }() // TODO: Close plugin servers in case of client panic. if err := app.Run(os.Args); err != nil { log.Error(err) } close(commands.RpcClientDriversCh) <-commands.RpcDriversClosedCh }
func main() { setDebugOutputLevel() cli.AppHelpTemplate = AppHelpTemplate cli.CommandHelpTemplate = CommandHelpTemplate app := cli.NewApp() app.Name = path.Base(os.Args[0]) app.Author = "Docker Machine Contributors" app.Email = "https://github.com/docker/machine" app.Before = func(c *cli.Context) error { // TODO: Need better handling of config, everything is too // complected together right now. if c.GlobalBool("native-ssh") { ssh.SetDefaultClient(ssh.Native) } mcnutils.GithubAPIToken = c.GlobalString("github-api-token") mcndirs.BaseDir = c.GlobalString("storage-path") return nil } app.Commands = commands.Commands app.CommandNotFound = cmdNotFound app.Usage = "Create and manage machines running Docker." app.Version = version.Version + " (" + version.GitCommit + ")" log.Debug("Docker Machine Version: ", app.Version) app.Flags = []cli.Flag{ cli.BoolFlag{ Name: "debug, D", Usage: "Enable debug mode", }, cli.StringFlag{ EnvVar: "MACHINE_STORAGE_PATH", Name: "s, storage-path", Value: mcndirs.GetBaseDir(), Usage: "Configures storage path", }, cli.StringFlag{ EnvVar: "MACHINE_TLS_CA_CERT", Name: "tls-ca-cert", Usage: "CA to verify remotes against", Value: "", }, cli.StringFlag{ EnvVar: "MACHINE_TLS_CA_KEY", Name: "tls-ca-key", Usage: "Private key to generate certificates", Value: "", }, cli.StringFlag{ EnvVar: "MACHINE_TLS_CLIENT_CERT", Name: "tls-client-cert", Usage: "Client cert to use for TLS", Value: "", }, cli.StringFlag{ EnvVar: "MACHINE_TLS_CLIENT_KEY", Name: "tls-client-key", Usage: "Private key used in client TLS auth", Value: "", }, cli.StringFlag{ EnvVar: "MACHINE_GITHUB_API_TOKEN", Name: "github-api-token", Usage: "Token to use for requests to the Github API", Value: "", }, cli.BoolFlag{ EnvVar: "MACHINE_NATIVE_SSH", Name: "native-ssh", Usage: "Use the native (Go-based) SSH implementation.", }, } // TODO: Close plugin servers in case of client panic. if err := app.Run(os.Args); err != nil { log.Error(err) } }
func (d *Driver) Create() error { var ( err error ) VpcId := d.VpcId VSwitchId := d.VSwitchId if err := d.checkPrereqs(); err != nil { return err } log.Infof("%s | Creating key pair for instance ...", d.MachineName) if err := d.createKeyPair(); err != nil { return fmt.Errorf("%s | Failed to create key pair: %v", d.MachineName, err) } log.Infof("%s | Configuring security groups instance ...", d.MachineName) if err := d.configureSecurityGroup(VpcId, d.SecurityGroupName); err != nil { return err } // TODO Support data disk if d.SSHPassword == "" { d.SSHPassword = randomPassword() log.Infof("%s | Launching instance with generated password, please update password in console or log in with ssh key.", d.MachineName) } imageID := d.GetImageID(d.ImageID) log.Infof("%s | Creating instance with image %s ...", d.MachineName, imageID) args := ecs.CreateInstanceArgs{ RegionId: d.Region, InstanceName: d.GetMachineName(), ImageId: imageID, InstanceType: d.InstanceType, SecurityGroupId: d.SecurityGroupId, InternetChargeType: internetChargeType, Password: d.SSHPassword, VSwitchId: VSwitchId, ZoneId: d.Zone, ClientToken: d.getClient().GenerateClientToken(), } if d.DiskSize > 0 { // Allocate Data Disk disk := ecs.DataDiskType{ DiskName: d.MachineName + "_data", Description: "Data volume for Docker", Size: d.DiskSize, Category: d.DiskCategory, Device: "/dev/xvdb", DeleteWithInstance: true, } args.DataDisk = []ecs.DataDiskType{disk} } // Set InternetMaxBandwidthOut only for classic network if VSwitchId == "" { args.InternetMaxBandwidthOut = d.InternetMaxBandwidthOut } // Create instance instanceId, err := d.getClient().CreateInstance(&args) if err != nil { err = fmt.Errorf("%s | Failed to create instance: %s", d.MachineName, err) log.Error(err) return err } log.Infof("%s | Create instance %s successfully", d.MachineName, instanceId) d.InstanceId = instanceId // Wait for creation successfully err = d.getClient().WaitForInstance(instanceId, ecs.Stopped, timeout) if err != nil { err = fmt.Errorf("%s | Failed to wait instance to 'stopped': %s", d.MachineName, err) log.Error(err) } if err == nil { err = d.configNetwork(VpcId, instanceId) } if err == nil { // Start instance log.Infof("%s | Starting instance %s ...", d.MachineName, instanceId) err = d.getClient().StartInstance(instanceId) if err == nil { // Wait for running err = d.getClient().WaitForInstance(instanceId, ecs.Running, timeout) if err == nil { log.Infof("%s | Start instance %s successfully", d.MachineName, instanceId) instance, err := d.getInstance() if err == nil { d.Zone = instance.ZoneId d.PrivateIPAddress = d.GetPrivateIP(instance) d.IPAddress = d.getIP(instance) ssh.SetDefaultClient(ssh.Native) d.uploadKeyPair() log.Infof("%s | Created instance %s successfully with public IP address %s and private IP address %s", d.MachineName, d.InstanceId, d.IPAddress, d.PrivateIPAddress, ) } } else { err = fmt.Errorf("%s | Failed to wait instance to running state: %s", d.MachineName, err) } } else { err = fmt.Errorf("%s | Failed to start instance %s: %v", d.MachineName, instanceId, err) } } // Add instance tags if len(d.Tags) > 0 { log.Infof("%s | Adding tags %v to instance %s ...", d.MachineName, d.Tags, instanceId) args := ecs.AddTagsArgs{ RegionId: d.Region, ResourceId: instanceId, ResourceType: ecs.TagResourceInstance, Tag: d.Tags, } err2 := d.getClient().AddTags(&args) if err2 != nil { log.Warnf("%s | Failed to add tags %v to instance %s: %v", d.MachineName, d.Tags, instanceId, err) } } if err != nil { log.Warn(err) d.Remove() } return err }
func DoSsh(cli interface{}, args ...string) error { ssh.SetDefaultClient(ssh.External) cmd := Cli.Subcmd("ssh", []string{"MACHINES COMMAND"}, "Run SSH commands on machines specified. Use - to run SSH on the active host.", false) cmd.ParseFlags(args, true) store := machine.GetDefaultStore(utils.GetBaseDir()) p, err := machine.ReadProvision("provision.yml") if err != nil { log.Debugf("err: %s", err) return err } pattern := cmd.Args()[0] if pattern == "" { log.Fatal("Error: Please specify a machine name or pattern.") } // TODO if ssh -all var machineList []string if pattern == "-" { name, err := GetActiveHostName() if err != nil { return err } machineList = []string{name} } else { machineList = p.GetMachineList(pattern) } if len(machineList) == 1 && len(cmd.Args()) == 1 { host, err := loadHost(store, machineList[0], utils.GetBaseDir()) if err != nil { log.Fatal(err) } currentState, err := host.Driver.GetState() if err != nil { log.Fatal(err) } if currentState != state.Running { log.Fatalf("Error: Cannot run SSH command: Host %q is not running", host.Name) } client, err := host.CreateSSHClient() if err != nil { log.Fatal(err) } if err := client.Shell(cmd.Args()[1:]...); err != nil { log.Fatal(err) } } else { sshCmd := strings.Join(cmd.Args()[1:], " ") if strings.TrimSpace(sshCmd) == "" { return errors.New("Interative shell is not allowed for multiple hosts.") } // TODO should limit string channel limit := len(machineList) if limit > 4 { limit = 4 } outputs := make(chan string, limit) for _, name := range machineList { go func(name string) { host, err := loadHost(store, name, utils.GetBaseDir()) if err != nil { log.Fatal(err) } currentState, err := host.Driver.GetState() if err != nil { log.Fatal(err) } if currentState != state.Running { log.Fatalf("Error: Cannot run SSH command: Host %q is not running", host.Name) } output, err := host.RunSSHCommand(sshCmd) if err != nil { if len(machineList) == 1 { outputs <- err.Error() } else { outputs <- fmt.Sprintf("\n%s:\n%s", name, err.Error()) } } else { if len(machineList) == 1 { outputs <- string(output) } else { outputs <- fmt.Sprintf("\n%s:\n%s", name, string(output)) } } }(name) } for i := 0; i < len(machineList); i++ { fmt.Print(<-outputs) } } return nil }