Example #1
0
// Create is the wrapper method which covers all of the boilerplate around
// actually creating, provisioning, and persisting an instance in the store.
func (api *Client) Create(h *host.Host) error {
	if err := cert.BootstrapCertificates(h.AuthOptions()); err != nil {
		return fmt.Errorf("Error generating certificates: %s", err)
	}

	log.Info("Running pre-create checks...")

	if err := h.Driver.PreCreateCheck(); err != nil {
		return mcnerror.ErrDuringPreCreate{
			Cause: err,
		}
	}

	if err := api.Save(h); err != nil {
		return fmt.Errorf("Error saving host to store before attempting creation: %s", err)
	}

	log.Info("Creating machine...")

	if err := api.performCreate(h); err != nil {
		return fmt.Errorf("Error creating machine: %s", err)
	}

	log.Debug("Reticulating splines...")

	return nil
}
Example #2
0
File: ls.go Project: chanwit/gattai
func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) {
	currentState, err := h.Driver.GetState()
	if err != nil {
		log.Errorf("error getting state for host %s: %s", h.Name, err)
	}

	url, err := h.GetURL()
	if err != nil {
		if err == drivers.ErrHostIsNotRunning {
			url = ""
		} else {
			log.Errorf("error getting URL for host %s: %s", h.Name, err)
		}
	}

	active, err := isActive(h)
	if err != nil {
		log.Errorf("error determining if host is active for host %s: %s",
			h.Name, err)
	}

	stateQueryChan <- HostListItem{
		Name:         h.Name,
		Active:       active,
		DriverName:   h.Driver.DriverName(),
		State:        currentState,
		URL:          url,
		SwarmOptions: h.HostOptions.SwarmOptions,
	}
}
Example #3
0
func engineExecute(h *host.Host, line string) error {
	p := shellwords.NewParser()
	args, err := p.Parse(line)
	if err != nil {
		return err
	}

	url, err := h.GetURL()
	if err != nil {
		return err
	}

	args = append([]string{
		"-H", url,
		"--tlscacert=" + h.HostOptions.AuthOptions.CaCertPath,
		"--tlscert=" + h.HostOptions.AuthOptions.ClientCertPath,
		"--tlskey=" + h.HostOptions.AuthOptions.ClientKeyPath,
		"--tlsverify=true"}, args...)

	cmd := exec.Command(os.Args[0], args...)
	log.Debugf("[engineExecute] Executing: %s", cmd)

	b, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Print(string(b))
		return err
	}

	return nil
}
Example #4
0
func (s Filestore) Save(host *host.Host) error {
	if serialDriver, ok := host.Driver.(*drivers.SerialDriver); ok {
		// Unwrap Driver
		host.Driver = serialDriver.Driver

		// Re-wrap Driver when done
		defer func() {
			host.Driver = serialDriver
		}()
	}

	// TODO: Does this belong here?
	if rpcClientDriver, ok := host.Driver.(*rpcdriver.RPCClientDriver); ok {
		data, err := rpcClientDriver.GetConfigRaw()
		if err != nil {
			return fmt.Errorf("Error getting raw config for driver: %s", err)
		}
		host.RawDriver = data
	}

	data, err := json.MarshalIndent(host, "", "    ")
	if err != nil {
		return err
	}

	hostPath := filepath.Join(s.getMachinesDir(), host.Name)

	// Ensure that the directory we want to save to exists.
	if err := os.MkdirAll(hostPath, 0700); err != nil {
		return err
	}

	return s.saveToFile(data, filepath.Join(hostPath, "config.json"))
}
Example #5
0
File: ls.go Project: chanwit/gattai
// IsActive provides a single function for determining if a host is active
// based on both the url and if the host is stopped.
func isActive(h *host.Host) (bool, error) {
	currentState, err := h.Driver.GetState()

	if err != nil {
		log.Errorf("error getting state for host %s: %s", h.Name, err)
		return false, err
	}

	url, err := h.GetURL()

	if err != nil {
		if err == drivers.ErrHostIsNotRunning {
			url = ""
		} else {
			log.Errorf("error getting URL for host %s: %s", h.Name, err)
			return false, err
		}
	}

	dockerHost := os.Getenv("DOCKER_HOST")

	notStopped := currentState != state.Stopped
	correctURL := url == dockerHost

	isActive := notStopped && correctURL

	return isActive, nil
}
Example #6
0
func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) {
	url := ""
	hostError := ""

	currentState, err := h.Driver.GetState()
	if err == nil {
		url, err = h.GetURL()
	}
	if err != nil {
		hostError = err.Error()
	}
	if hostError == drivers.ErrHostIsNotRunning.Error() {
		hostError = ""
	}

	var swarmOptions *swarm.Options
	if h.HostOptions != nil {
		swarmOptions = h.HostOptions.SwarmOptions
	}

	stateQueryChan <- HostListItem{
		Name:         h.Name,
		Active:       isActive(currentState, url),
		DriverName:   h.Driver.DriverName(),
		State:        currentState,
		URL:          url,
		SwarmOptions: swarmOptions,
		Error:        hostError,
	}
}
Example #7
0
func (s Filestore) loadConfig(h *host.Host) error {
	data, err := ioutil.ReadFile(filepath.Join(s.GetMachinesDir(), h.Name, "config.json"))
	if err != nil {
		return err
	}

	// Remember the machine name so we don't have to pass it through each
	// struct in the migration.
	name := h.Name

	migratedHost, migrationPerformed, err := host.MigrateHost(h, data)
	if err != nil {
		return fmt.Errorf("Error getting migrated host: %s", err)
	}

	*h = *migratedHost

	h.Name = name

	// If we end up performing a migration, we should save afterwards so we don't have to do it again on subsequent invocations.
	if migrationPerformed {
		if err := s.saveToFile(data, filepath.Join(s.GetMachinesDir(), h.Name, "config.json.bak")); err != nil {
			return fmt.Errorf("Error attempting to save backup after migration: %s", err)
		}

		if err := s.Save(h); err != nil {
			return fmt.Errorf("Error saving config after migration was performed: %s", err)
		}
	}

	return nil
}
Example #8
0
func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) {
	stateCh := make(chan state.State)
	urlCh := make(chan string)

	go func() {
		currentState, err := h.Driver.GetState()
		if err != nil {
			log.Errorf("error getting state for host %s: %s", h.Name, err)
		}

		stateCh <- currentState
	}()

	go func() {
		url, err := h.GetURL()
		if err != nil {
			if err.Error() == drivers.ErrHostIsNotRunning.Error() {
				url = ""
			} else {
				log.Errorf("error getting URL for host %s: %s", h.Name, err)
			}
		}

		urlCh <- url
	}()

	currentState := <-stateCh
	url := <-urlCh

	close(stateCh)
	close(urlCh)

	active, err := isActive(h, currentState, url)
	if err != nil {
		log.Errorf("error determining if host is active for host %s: %s",
			h.Name, err)
	}

	stateQueryChan <- HostListItem{
		Name:         h.Name,
		Active:       active,
		DriverName:   h.Driver.DriverName(),
		State:        currentState,
		URL:          url,
		SwarmOptions: h.HostOptions.SwarmOptions,
	}
}
Example #9
0
func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) {
	url := ""
	hostError := ""
	dockerVersion := "Unknown"

	currentState, err := h.Driver.GetState()
	if err == nil {
		url, err = h.URL()
	}
	if err == nil {
		dockerVersion, err = h.DockerVersion()
		if err != nil {
			dockerVersion = "Unknown"
		} else {
			dockerVersion = fmt.Sprintf("v%s", dockerVersion)
		}
	}

	if err != nil {
		hostError = err.Error()
	}
	if hostError == drivers.ErrHostIsNotRunning.Error() {
		hostError = ""
	}

	var swarmOptions *swarm.Options
	var engineOptions *engine.Options
	if h.HostOptions != nil {
		swarmOptions = h.HostOptions.SwarmOptions
		engineOptions = h.HostOptions.EngineOptions
	}

	stateQueryChan <- HostListItem{
		Name:          h.Name,
		Active:        isActive(currentState, url),
		DriverName:    h.Driver.DriverName(),
		State:         currentState,
		URL:           url,
		SwarmOptions:  swarmOptions,
		EngineOptions: engineOptions,
		DockerVersion: dockerVersion,
		Error:         hostError,
	}
}
Example #10
0
func (f *fakeLibMachineAPI) Create(h *host.Host) error {
	if f.driverName == "amazonec2" {
		f.ec2Driver = h.Driver.(*amazonec2.Driver)
	}
	h.Driver = &fakedriver.Driver{
		MockName:  h.Name,
		MockState: state.Running,
		MockIP:    "192.168.10.3",
	}
	f.Save(h)
	return nil
}
Example #11
0
// Create is the wrapper method which covers all of the boilerplate around
// actually creating, provisioning, and persisting an instance in the store.
func (api *Client) Create(h *host.Host) error {
	if err := cert.BootstrapCertificates(h.AuthOptions()); err != nil {
		return fmt.Errorf("Error generating certificates: %s", err)
	}

	log.Info("Running pre-create checks...")

	if err := h.Driver.PreCreateCheck(); err != nil {
		return mcnerror.ErrDuringPreCreate{err}
	}

	if err := api.Save(h); err != nil {
		return fmt.Errorf("Error saving host to store before attempting creation: %s", err)
	}

	log.Info("Creating machine...")

	if err := api.performCreate(h); err != nil {
		// Wait for all the logs to reach the client
		time.Sleep(2 * time.Second)

		vBoxLog := ""
		if h.DriverName == "virtualbox" {
			vBoxLog = filepath.Join(api.GetMachinesDir(), h.Name, h.Name, "Logs", "VBox.log")
		}

		return crashreport.CrashError{
			Cause:       err,
			Command:     "Create",
			Context:     "api.performCreate",
			DriverName:  h.DriverName,
			LogFilePath: vBoxLog,
		}
	}

	log.Debug("Reticulating splines...")

	return nil
}
Example #12
0
func (ps PluginStore) Save(host *host.Host) error {
	if serialDriver, ok := host.Driver.(*drivers.SerialDriver); ok {
		// Unwrap Driver
		host.Driver = serialDriver.Driver

		// Re-wrap Driver when done
		defer func() {
			host.Driver = serialDriver
		}()
	}

	// TODO: Does this belong here?
	if rpcClientDriver, ok := host.Driver.(*rpcdriver.RPCClientDriver); ok {
		data, err := rpcClientDriver.GetConfigRaw()
		if err != nil {
			return fmt.Errorf("Error getting raw config for driver: %s", err)
		}
		host.RawDriver = data
	}

	return ps.Filestore.Save(host)
}
Example #13
0
func (mcc *MachineConnChecker) Check(h *host.Host, swarm bool) (string, *auth.Options, error) {
	dockerHost, err := h.Driver.GetURL()
	if err != nil {
		return "", &auth.Options{}, err
	}

	dockerURL := dockerHost
	if swarm {
		dockerURL, err = parseSwarm(dockerHost, h)
		if err != nil {
			return "", &auth.Options{}, err
		}
	}

	u, err := url.Parse(dockerURL)
	if err != nil {
		return "", &auth.Options{}, fmt.Errorf("Error parsing URL: %s", err)
	}

	authOptions := h.AuthOptions()

	if err := checkCert(u.Host, authOptions); err != nil {
		if swarm {
			// Connection to the swarm port cannot be checked. Maybe it's just the swarm containers that are down
			// TODO: check the containers and restart them
			// Let's check the non-swarm connection to give a better error message to the user.
			if _, _, err := mcc.Check(h, false); err == nil {
				return "", &auth.Options{}, ErrSwarmNotStarted
			}
		}

		return "", &auth.Options{}, fmt.Errorf("Error checking and/or regenerating the certs: %s", err)
	}

	return dockerURL, authOptions, nil
}
Example #14
0
func newMachine(h *host.Host) (*Machine, error) {
	rawDriver, err := json.Marshal(h.Driver)
	if err != nil {
		return nil, errors.Wrap(err, "failed to marshal host driver")
	}
	var driverData map[string]interface{}
	err = json.Unmarshal(rawDriver, &driverData)
	if err != nil {
		return nil, errors.Wrap(err, "failed to unmarshal host driver")
	}
	m := &Machine{
		Base: &iaas.Machine{
			Id:         h.Name,
			Port:       engine.DefaultPort,
			Protocol:   "https",
			CustomData: driverData,
			CreationParams: map[string]string{
				"driver": h.DriverName,
			},
		},
		Host: h,
	}
	address, err := h.Driver.GetIP()
	if err != nil {
		return m, errors.Wrap(err, "failed to retrive host ip")
	}
	m.Base.Address = address
	if h.AuthOptions() != nil {
		m.Base.CaCert, err = ioutil.ReadFile(h.AuthOptions().CaCertPath)
		if err != nil {
			return m, errors.Wrap(err, "failed to read host ca cert")
		}
		m.Base.ClientCert, err = ioutil.ReadFile(h.AuthOptions().ClientCertPath)
		if err != nil {
			return m, errors.Wrap(err, "failed to read host client cert")
		}
		m.Base.ClientKey, err = ioutil.ReadFile(h.AuthOptions().ClientKeyPath)
		if err != nil {
			return m, errors.Wrap(err, "failed to read host client key")
		}
	}
	return m, nil
}
Example #15
0
// PERFORMANCE: The code of this function is complicated because we try
// to call the underlying drivers as less as possible to get the information
// we need.
func attemptGetHostItem(h *host.Host, stateQueryChan chan<- commands.HostListItem) {
	url := ""
	currentState := state.None
	dockerVersion := "Unknown"
	hostError := ""

	url, err := h.URL()

	// PERFORMANCE: if we have the url, it's ok to assume the host is running
	// This reduces the number of calls to the drivers
	if err == nil {
		if url != "" {
			currentState = state.Running
		} else {
			currentState, err = h.Driver.GetState()
		}
	} else {
		currentState, _ = h.Driver.GetState()
	}

	if err == nil && url != "" {
		// PERFORMANCE: Reuse the url instead of asking the host again.
		// This reduces the number of calls to the drivers
		dockerHost := &mcndockerclient.RemoteDocker{
			HostURL:    url,
			AuthOption: h.AuthOptions(),
		}
		dockerVersion, err = mcndockerclient.DockerVersion(dockerHost)

		if err != nil {
			dockerVersion = "Unknown"
		} else {
			dockerVersion = fmt.Sprintf("v%s", dockerVersion)
		}
	}

	if err != nil {
		hostError = err.Error()
	}
	if hostError == drivers.ErrHostIsNotRunning.Error() {
		hostError = ""
	}

	var swarmOptions *swarm.Options
	var engineOptions *engine.Options
	if h.HostOptions != nil {
		swarmOptions = h.HostOptions.SwarmOptions
		engineOptions = h.HostOptions.EngineOptions
	}

	isMaster := false
	swarmHost := ""
	if swarmOptions != nil {
		isMaster = swarmOptions.Master
		swarmHost = swarmOptions.Host
	}

	activeHost := isActive(currentState, url)
	activeSwarm := isSwarmActive(currentState, url, isMaster, swarmHost)
	active := "-"
	if activeHost {
		active = "*"
	}
	if activeSwarm {
		active = "* (swarm)"
	}

	stateQueryChan <- commands.HostListItem{
		Name:          h.Name,
		Active:        active,
		ActiveHost:    activeHost,
		ActiveSwarm:   activeSwarm,
		DriverName:    h.Driver.DriverName(),
		State:         currentState,
		URL:           url,
		SwarmOptions:  swarmOptions,
		EngineOptions: engineOptions,
		DockerVersion: dockerVersion,
		Error:         hostError,
	}
}
Example #16
0
func swarmManage(h *host.Host, image string, token string) error {

	provisioner, err := provision.DetectProvisioner(h.Driver)
	dockerDir := provisioner.GetDockerOptionsDir()
	authOptions := setRemoteAuthOptions(provisioner)

	url, err := h.GetURL()
	if err != nil {
		return err
	}

	retryCount := 0

retry:
	exec.Command(os.Args[0], []string{
		"-H", url,
		"--tlscacert=" + h.HostOptions.AuthOptions.CaCertPath,
		"--tlscert=" + h.HostOptions.AuthOptions.ClientCertPath,
		"--tlskey=" + h.HostOptions.AuthOptions.ClientKeyPath,
		"--tlsverify=true",
		"rm", "-f", "swarm-manager"}...).Output()

	cmd := exec.Command(os.Args[0], []string{
		"-H", url,
		"--tlscacert=" + h.HostOptions.AuthOptions.CaCertPath,
		"--tlscert=" + h.HostOptions.AuthOptions.ClientCertPath,
		"--tlskey=" + h.HostOptions.AuthOptions.ClientKeyPath,
		"--tlsverify=true",
		"run", "-d", "--restart=always",
		"--net=bridge",
		"--name", "swarm-manager",
		"-p", "3376:3376",
		"-v", dockerDir + ":" + dockerDir,
		image, "manage",
		"--tlsverify",
		"--tlscacert=" + authOptions.CaCertRemotePath,
		"--tlscert=" + authOptions.ServerCertRemotePath,
		"--tlskey=" + authOptions.ServerKeyRemotePath,
		"-H", "0.0.0.0:3376",
		token}...)

	err = cmd.Run()
	if err == nil {
		fmt.Printf("Manager '%s' started successfully...\n", h.Name)
		return nil
	}

	if _, ok := err.(*exec.ExitError); ok {
		retryCount++
		if retryCount <= 5 {
			fmt.Printf("Failed to start manager. Retry: %d\n", retryCount)
			goto retry
		}
		// if s, ok := exiterr.Sys().(syscall.WaitStatus); ok {
		// 	if s.ExitCode == 8 {
		// 		goto retry
		// 	}
		// }
	}

	return err
}