// CopyFromHost copies a set of files from the Docker host to the local file system func (h *HostHelper) CopyFromHost(sourceDir, destDir string) error { container, err := h.runner(). Image(h.image). Bind(fmt.Sprintf("%[1]s:%[1]s:ro", sourceDir)). Create() if err != nil { return err } defer func() { errors.LogError(h.client.RemoveContainer(docker.RemoveContainerOptions{ID: container})) }() localTarFile, err := ioutil.TempFile("", "local-copy-tar-") if err != nil { return err } localTarClosed := false defer func() { if !localTarClosed { errors.LogError(localTarFile.Close()) } errors.LogError(os.Remove(localTarFile.Name())) }() glog.V(4).Infof("Downloading from host path %s to local tar file: %s", sourceDir, localTarFile.Name()) err = h.client.DownloadFromContainer(container, docker.DownloadFromContainerOptions{ Path: sourceDir, OutputStream: localTarFile, }) if err != nil { return err } if err = localTarFile.Close(); err != nil { return err } localTarClosed = true inputTar, err := os.Open(localTarFile.Name()) if err != nil { return err } defer func() { errors.LogError(inputTar.Close()) }() tarHelper := tarhelper.New() tarHelper.SetExclusionPattern(nil) glog.V(4).Infof("Extracting temporary tar %s to directory %s", inputTar.Name(), destDir) var tarLog io.Writer if glog.V(5) { tarLog = os.Stderr } return tarHelper.ExtractTarStreamWithLogging(destDir, inputTar, tarLog) }
func (h *Helper) TestIP(ip string) error { // Start test server on host id, err := h.runHelper.New().Image(h.image). Privileged(). HostNetwork(). Entrypoint("socat"). Command("TCP-LISTEN:8443,crlf,reuseaddr,fork", "SYSTEM:\"echo 'hello world'\"").Start() if err != nil { return errors.NewError("cannnot start simple server on Docker host").WithCause(err) } defer func() { errors.LogError(h.dockerHelper.StopAndRemoveContainer(id)) }() // Attempt to connect to test container testHost := fmt.Sprintf("%s:8443", ip) glog.V(4).Infof("Attempting to dial %s", testHost) if err = cmdutil.WaitForSuccessfulDial(false, "tcp", testHost, 200*time.Millisecond, 1*time.Second, 10); err != nil { glog.V(2).Infof("Dial error: %v", err) return err } glog.V(4).Infof("Successfully dialed %s", testHost) return nil }
func (h *Helper) TestForwardedIP(ip string) error { // Start test server on host id, err := h.runHelper.New().Image(h.image). PortForward(8443, 8443). Entrypoint("socat"). Command("TCP-LISTEN:8443,crlf,reuseaddr,fork", "SYSTEM:\"echo 'hello world'\"").Start() if err != nil { return errors.NewError("cannnot start simple server on Docker host").WithCause(err) } defer func() { errors.LogError(h.dockerHelper.StopAndRemoveContainer(id)) }() return testIPDial(ip) }
// makeTempCopy creates a temporary directory and places a copy of the source file // in it. It returns the directory where the temporary copy was made. func makeTempCopy(file string) (string, error) { tempDir, err := ioutil.TempDir("", "") if err != nil { return "", err } destPath := filepath.Join(tempDir, filepath.Base(file)) destFile, err := os.Create(destPath) if err != nil { return "", err } defer func() { errors.LogError(destFile.Close()) }() sourceFile, err := os.Open(file) if err != nil { return "", err } defer func() { errors.LogError(sourceFile.Close()) }() _, err = io.Copy(destFile, sourceFile) return tempDir, err }
// DownloadDirFromContainer copies a set of files from the Docker host to the local file system func (h *HostHelper) DownloadDirFromContainer(sourceDir, destDir string) error { container, err := h.runner(). Image(h.image). Bind(h.defaultBinds()...). Entrypoint("/bin/true"). Create() if err != nil { return err } defer func() { errors.LogError(h.client.RemoveContainer(docker.RemoveContainerOptions{ID: container})) }() err = dockerhelper.DownloadDirFromContainer(h.client, container, sourceDir, destDir) if err != nil { glog.V(4).Infof("An error occurred downloading the directory: %v", err) } else { glog.V(4).Infof("Successfully downloaded directory.") } return err }
// UploadFileToContainer copies a local file to the Docker host func (h *HostHelper) UploadFileToContainer(src, dst string) error { container, err := h.runner(). Image(h.image). Bind(h.defaultBinds()...). Entrypoint("/bin/true"). Create() if err != nil { return err } defer func() { errors.LogError(h.client.RemoveContainer(docker.RemoveContainerOptions{ID: container})) }() err = dockerhelper.UploadFileToContainer(h.client, container, src, dst) if err != nil { glog.V(4).Infof("An error occurred uploading the file: %v", err) } else { glog.V(4).Infof("Successfully uploaded file.") } return err }
// Start starts the OpenShift master as a Docker container // and returns a directory in the local file system where // the OpenShift configuration has been copied func (h *Helper) Start(opt *StartOptions, out io.Writer) (string, error) { // Ensure that socat is available locally if opt.PortForwarding { err := CheckSocat() if err != nil { return "", err } } binds := openShiftContainerBinds env := []string{} if opt.UseSharedVolume { binds = append(binds, fmt.Sprintf("%[1]s:%[1]s:shared", opt.HostVolumesDir)) env = append(env, "OPENSHIFT_CONTAINERIZED=false") } else { binds = append(binds, "/:/rootfs:ro") propagationMode := "" if opt.SetPropagationMode { propagationMode = ":rslave" } binds = append(binds, fmt.Sprintf("%[1]s:%[1]s%[2]s", opt.HostVolumesDir, propagationMode)) } env = append(env, opt.Environment...) binds = append(binds, fmt.Sprintf("%s:/var/lib/origin/openshift.local.config:z", opt.HostConfigDir)) // Check if a configuration exists before creating one if UseExistingConfig // was specified var configDir string cleanupConfig := func() { errors.LogError(os.RemoveAll(configDir)) } skipCreateConfig := false if opt.UseExistingConfig { var err error configDir, err = h.copyConfig(opt.HostConfigDir) if err == nil { _, err = os.Stat(filepath.Join(configDir, "master", "master-config.yaml")) if err == nil { skipCreateConfig = true } } } // Create configuration if needed var nodeHost string if !skipCreateConfig { glog.V(1).Infof("Creating openshift configuration at %s on Docker host", opt.HostConfigDir) fmt.Fprintf(out, "Creating initial OpenShift configuration\n") createConfigCmd := []string{ "start", fmt.Sprintf("--images=%s", opt.Images), fmt.Sprintf("--volume-dir=%s", opt.HostVolumesDir), fmt.Sprintf("--dns=0.0.0.0:%d", opt.DNSPort), "--write-config=/var/lib/origin/openshift.local.config", } if opt.PortForwarding { internalIP, err := h.ServerIP() if err != nil { return "", err } nodeHost = internalIP createConfigCmd = append(createConfigCmd, fmt.Sprintf("--master=%s", internalIP)) createConfigCmd = append(createConfigCmd, fmt.Sprintf("--public-master=https://%s:8443", opt.ServerIP)) } else { nodeHost = opt.ServerIP createConfigCmd = append(createConfigCmd, fmt.Sprintf("--master=%s", opt.ServerIP)) if len(h.publicHost) > 0 { createConfigCmd = append(createConfigCmd, fmt.Sprintf("--public-master=https://%s:8443", h.publicHost)) } } createConfigCmd = append(createConfigCmd, fmt.Sprintf("--hostname=%s", nodeHost)) _, err := h.runHelper.New().Image(h.image). Privileged(). DiscardContainer(). HostNetwork(). HostPid(). Bind(binds...). Env(env...). Command(createConfigCmd...).Run() if err != nil { return "", errors.NewError("could not create OpenShift configuration").WithCause(err) } configDir, err = h.copyConfig(opt.HostConfigDir) if err != nil { return "", errors.NewError("could not copy OpenShift configuration").WithCause(err) } err = h.updateConfig(configDir, opt.HostConfigDir, opt.RouterIP, opt.MetricsHost, opt.LoggingHost) if err != nil { cleanupConfig() return "", errors.NewError("could not update OpenShift configuration").WithCause(err) } } if nodeHost == "" { if opt.PortForwarding { var err error nodeHost, err = h.ServerIP() if err != nil { return "", err } } else { var err error hostName, err := h.hostHelper.Hostname() if err != nil { return "", err } nodeHost, err = h.DetermineNodeHost(opt.HostConfigDir, opt.ServerIP, hostName) if err != nil { return "", err } } } masterConfig, nodeConfig, err := h.getOpenShiftConfigFiles(nodeHost) if err != nil { cleanupConfig() return "", errors.NewError("could not get OpenShift configuration file paths").WithCause(err) } fmt.Fprintf(out, "Starting OpenShift using container '%s'\n", h.containerName) startCmd := []string{ "start", fmt.Sprintf("--master-config=%s", masterConfig), fmt.Sprintf("--node-config=%s", nodeConfig), } if opt.LogLevel > 0 { startCmd = append(startCmd, fmt.Sprintf("--loglevel=%d", opt.LogLevel)) } if opt.PortForwarding { err = h.startSocatTunnel() if err != nil { return "", err } } if len(opt.HostDataDir) > 0 { binds = append(binds, fmt.Sprintf("%s:/var/lib/origin/openshift.local.etcd:z", opt.HostDataDir)) } _, err = h.runHelper.New().Image(h.image). Name(h.containerName). Privileged(). HostNetwork(). HostPid(). Bind(binds...). Env(env...). Command(startCmd...). Start() if err != nil { return "", errors.NewError("cannot start OpenShift daemon").WithCause(err) } // Wait a minimum amount of time and check whether we're still running. If not, we know the daemon didn't start time.Sleep(initialStatusCheckWait) _, running, err := h.dockerHelper.GetContainerState(h.containerName) if err != nil { return "", errors.NewError("cannot get state of OpenShift container %s", h.containerName).WithCause(err) } if !running { return "", ErrOpenShiftFailedToStart(h.containerName).WithDetails(h.OriginLog()) } // Wait until the API server is listening fmt.Fprintf(out, "Waiting for API server to start listening\n") masterHost := fmt.Sprintf("%s:8443", opt.ServerIP) if err = cmdutil.WaitForSuccessfulDial(true, "tcp", masterHost, 200*time.Millisecond, 1*time.Second, serverUpTimeout); err != nil { return "", ErrTimedOutWaitingForStart(h.containerName).WithDetails(h.OriginLog()) } // Check for healthz endpoint to be ready client, err := masterHTTPClient(configDir) if err != nil { return "", err } for { resp, ierr := client.Get(h.healthzReadyURL(opt.ServerIP)) if ierr != nil { return "", errors.NewError("cannot access master readiness URL %s", h.healthzReadyURL(opt.ServerIP)).WithCause(err).WithDetails(h.OriginLog()) } if resp.StatusCode == http.StatusOK { break } if resp.StatusCode == http.StatusServiceUnavailable || resp.StatusCode == http.StatusForbidden { time.Sleep(500 * time.Millisecond) continue } var responseBody string body, rerr := ioutil.ReadAll(resp.Body) if rerr == nil { responseBody = string(body) } return "", errors.NewError("server is not ready. Response (%d): %s", resp.StatusCode, responseBody).WithCause(ierr).WithDetails(h.OriginLog()) } fmt.Fprintf(out, "OpenShift server started\n") return configDir, nil }
// CopyMasterConfigToHost copies a local file to the Docker host func (h *HostHelper) CopyMasterConfigToHost(sourceFile, destDir string) error { localDir, err := makeTempCopy(sourceFile) if err != nil { return err } tarHelper := tarhelper.New() tarHelper.SetExclusionPattern(nil) var tarLog io.Writer if glog.V(5) { tarLog = os.Stderr } localTarFile, err := ioutil.TempFile("", "master-config") if err != nil { return err } localTarClosed := false defer func() { if !localTarClosed { errors.LogError(localTarFile.Close()) } }() glog.V(4).Infof("Creating temporary tar %s to upload to %s", localTarFile.Name(), destDir) err = tarHelper.CreateTarStreamWithLogging(localDir, false, localTarFile, tarLog) if err != nil { return err } err = localTarFile.Close() if err != nil { return err } localTarClosed = true localTarInputClosed := false localTarInput, err := os.Open(localTarFile.Name()) if err != nil { return err } defer func() { if !localTarInputClosed { localTarInput.Close() } }() bind := fmt.Sprintf("%s:/var/lib/origin/openshift.local.config:z", destDir) container, err := h.runner(). Image(h.image). Bind(bind).Create() _ = container if err != nil { return err } defer func() { errors.LogError(h.client.RemoveContainer(docker.RemoveContainerOptions{ID: container})) }() glog.V(4).Infof("Uploading tar file %s to remote dir: %s", localTarFile.Name(), destDir) err = h.client.UploadToContainer(container, docker.UploadToContainerOptions{ InputStream: localTarInput, Path: "/var/lib/origin/openshift.local.config/master", }) if err != nil { glog.V(4).Infof("An error occurred uploading the file: %v", err) } else { // If the upload succeeded the local input stream will be closed automatically localTarInputClosed = true glog.V(4).Infof("Successfully uploaded file.") } return err }