Пример #1
0
// 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
}
Пример #2
0
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)
		}
	}
}
Пример #3
0
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()
}
Пример #4
0
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
		}
	}
}
Пример #5
0
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
}
Пример #6
0
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)
	}
}
Пример #7
0
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
}
Пример #8
0
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
}