// 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 }
// 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 }
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 }
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 }
// 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, } }