Пример #1
0
func loadHost(store persist.Store, hostName string, storePath string) (*host.Host, error) {
	h, err := store.Load(hostName)
	if err != nil {
		return nil, fmt.Errorf("Loading host from store failed: %s", err)
	}

	d, err := driverfactory.NewDriver(h.DriverName, h.Name, storePath)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(h.RawDriver, &d)
	if err != nil {
		return nil, err
	}
	h.Driver = d

	return h, nil
}
Пример #2
0
// Usage: gattai provision
func DoProvision(cli interface{}, args ...string) error {

	cmd := Cli.Subcmd("provision",
		[]string{"PATTERNS"},
		"Provision a set of machines. Patterns, e.g. machine-[1:10], are allowed.",
		false)

	provisionFilename := cmd.String(
		[]string{"f", "-file"},
		"provision.yml",
		"Name of the provision file")

	// TODO: EnvVar: "MACHINE_STORAGE_PATH"
	machineStoragePath := cmd.String(
		[]string{"s", "-storge-path"},
		utils.GetBaseDir(),
		"Configure Docker Machine's storage path")

	quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Do not list machines at the end of provisioning")

	cmd.ParseFlags(args, true)

	p, err := machine.ReadProvision(*provisionFilename)
	if err != nil {
		log.Debugf("err: %s", err)
		return err
	}

	// extract pattern
	// fmt.Printf("args: %s\n",args)

	machineList := p.GetMachineList(cmd.Args()...)

	log.Debugf("machines: %s", machineList)

	if len(machineList) == 0 {
		return errors.New("no machine in list")
	}

	// create libmachine's store
	log.Debugf("storage: %s", *machineStoragePath)

	certInfo := machine.GetCertInfo()
	authOptions := &auth.AuthOptions{
		CertDir:          filepath.Join(*machineStoragePath, "certs"),
		CaCertPath:       certInfo.CaCertPath,
		CaPrivateKeyPath: certInfo.CaPrivateKeyPath,
		ClientCertPath:   certInfo.ClientCertPath,
		ClientKeyPath:    certInfo.ClientKeyPath,
	}

	// TODO authOptions :=

	if err := cert.BootstrapCertificates(authOptions); err != nil {
		log.Fatalf("Error generating certificates: %s", err)
	}

	store := machine.GetDefaultStore(*machineStoragePath)

	spacing := len(machineList) > 1

	// check each machine existing
	for _, name := range machineList {

		parts := strings.SplitN(name, "-", 2)
		group := parts[0]
		index := -1
		if len(parts) > 1 {
			// node-master is not a group, but a machine name, for example.
			i, err := strconv.Atoi(parts[1])
			if err != nil {
				group = name
			} else {
				index = i - 1
			}
		}
		details := p.Machines[group]

		if details.BaseAddress != "" {
			ip, _, err := net.ParseCIDR(details.BaseAddress)
			if err != nil {
				return err
			}

			for i := details.BaseIndex; i <= index; i++ {
				utils.IncAddress(ip)
			}
			os.Setenv("MACHINE_IP", ip.String())
		}

		if details.PreProvision != nil && len(details.PreProvision) > 0 {
			fmt.Println("Processing pre-provision commands...")
			for _, pre := range details.PreProvision {
				log.Debugf("pre-provision: %s", os.ExpandEnv(pre))
				// if strings.HasPrefix(pre, "bash") {
				err := executeBash(strings.TrimSpace(os.ExpandEnv(pre)))
				if err != nil {
					log.Debug(err)
				}
				// }
			}
		}

		h, err := store.Load(name)
		if err != nil {
			if _, ok := err.(mcnerror.ErrHostDoesNotExist); ok {
				fmt.Printf("Machine '%s' not found, creating...\n", name)
				spacing = true

				// spew.Dump(hostOptions)

				driver, err := driverfactory.NewDriver(details.Driver, name, *machineStoragePath)
				if err != nil {
					log.Fatalf("Error trying to get driver: %s", err)
				}

				// TODO populate Env Vars from all hosts
				// to use with .SetConfigFromFlags

				h, err = store.NewHost(driver)
				if err != nil {
					log.Fatalf("Error getting new host: %s", err)
				}

				c := machine.Options(make(map[string]interface{}))
				for k, v := range details.Options {
					c[k] = v
				}

				hostOptions := &host.HostOptions{
					AuthOptions: &auth.AuthOptions{
						CertDir:          utils.GetMachineCertDir(),
						CaCertPath:       certInfo.CaCertPath,
						CaPrivateKeyPath: certInfo.CaPrivateKeyPath,
						ClientCertPath:   certInfo.ClientCertPath,
						ClientKeyPath:    certInfo.ClientKeyPath,
						ServerCertPath:   filepath.Join(utils.GetMachineDir(), name, "server.pem"),
						ServerKeyPath:    filepath.Join(utils.GetMachineDir(), name, "server-key.pem"),
						StorePath:        filepath.Join(utils.GetMachineDir(), name),
					},
					EngineOptions: &engine.EngineOptions{
						ArbitraryFlags:   c.StringSlice("engine-opt"),
						Env:              c.StringSlice("engine-env"),
						InsecureRegistry: c.StringSlice("engine-insecure-registry"),
						Labels:           c.StringSlice("engine-label"),
						RegistryMirror:   c.StringSlice("engine-registry-mirror"),
						StorageDriver:    c.String("engine-storage-driver"),
						TlsVerify:        true,
						InstallURL:       c.String("engine-install-url"),
					},
					SwarmOptions: &swarm.SwarmOptions{
						IsSwarm:        c.Bool("swarm"),
						Image:          c.String("swarm-image"),
						Master:         c.Bool("swarm-master"),
						Discovery:      c.String("swarm-discovery"),
						Address:        c.String("swarm-addr"),
						Host:           c.String("swarm-host"),
						Strategy:       c.String("swarm-strategy"),
						ArbitraryFlags: c.StringSlice("swarm-opt"),
					},
				}

				h.HostOptions = hostOptions

				if err := h.Driver.SetConfigFromFlags(details.Options); err != nil {
					log.Fatalf("Error setting machine configuration from flags provided: %s", err)
				}

				// make it compatible with RpcDriver
				driverData, err := json.Marshal(h.Driver)
				if err != nil {
					log.Fatal("Cannot marshal host driver")
				}
				h.RawDriver = driverData

				err = create(store, h, func(hh *host.Host) {
					c := machine.Options(make(map[string]interface{}))
					for k, v := range details.Options {
						c[k] = v
					}

					kvstoreName := details.NetworkKvstore
					log.Debug("Cluster store: " + kvstoreName)
					if kvstoreName != "" {
						kvstore, err := loadHost(store, kvstoreName, *machineStoragePath)
						if err != nil {
							panic(err)
						}

						c, url, err := configureClusterStore(h, kvstore, c)
						if err != nil {
							panic(err)
						} else {
							hh.HostOptions.EngineOptions.ArbitraryFlags = c.StringSlice("engine-opt")
							saveDiscoveryUrl(url + "/" + kvstoreName)
						}
					}

				})
				if err != nil {
					log.Errorf("Error creating machine: %s", err)
					log.Fatal("You will want to check the provider to make sure the machine and associated resources were properly removed.")
				}

				// make it compatible with RpcDriver
				driverData, err = json.Marshal(h.Driver)
				if err != nil {
					log.Fatal("Cannot marshal host driver")
				}
				h.RawDriver = driverData
				err = store.Save(h)

				if err != nil {
					log.Fatalf("Error saving machine: %s", err)
				}

			}
		} else {
			fmt.Printf("Machine '%s' exists, starting...\n", name)
			h, err = loadHost(store, name, *machineStoragePath)
			// TODO reprovision
			h.Start()
			spacing = false
		}

		_ = removeAllContainers(h)
		// TODO delete all containers during re-provision?

		if details.PostProvision != nil && len(details.PostProvision) > 0 {
			fmt.Println("Processing post-provision commands...")
			for _, post := range details.PostProvision {
				log.Debugf("post-provision: %s", post)
				if strings.HasPrefix(post, "docker") {
					err := engineExecute(h, strings.TrimSpace(post[6:]))
					if err != nil {
						// if error, goes on
						log.Debug(err)
					}
				}
			}
		}

		if spacing {
			if len(machineList) > 1 {
				fmt.Println()
			}
		}

	}

	if !spacing {
		fmt.Println()
	}

	if *quiet == false {
		w := tabwriter.NewWriter(os.Stdout, 5, 1, 3, ' ', 0)
		fmt.Fprintln(w, "NAME\tURL\tSTATE")

		for _, machineName := range machineList {
			h, err := loadHost(store, machineName, utils.GetBaseDir())
			items := getHostListItems([]*host.Host{h})
			if err == nil {
				url, _ := h.GetURL()
				fmt.Fprintf(w, "%s\t%s\t%s\n", machineName, url, items[0].State)
			}
		}
		w.Flush()
	}

	return err
}