Browse code

cluster up: use rslave propagation mode with nsenter mounter

Cesar Wong authored on 2016/08/23 03:23:00
Showing 4 changed files
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"io"
8 8
 	"net"
9 9
 	"net/url"
10
+	"regexp"
10 11
 	"strconv"
11 12
 	"time"
12 13
 
... ...
@@ -76,26 +77,36 @@ func (h *Helper) HasInsecureRegistryArg() (bool, error) {
76 76
 	return hasCIDR(openShiftInsecureCIDR, registryConfig.InsecureRegistryCIDRs), nil
77 77
 }
78 78
 
79
-// Version returns the Docker version
80
-func (h *Helper) Version() (*semver.Version, error) {
79
+var (
80
+	fedoraPackage = regexp.MustCompile("\\.fc[0-9_]*\\.")
81
+	rhelPackage   = regexp.MustCompile("\\.el[0-9_]*\\.")
82
+)
83
+
84
+// Version returns the Docker version and whether it is a Red Hat distro version
85
+func (h *Helper) Version() (*semver.Version, bool, error) {
81 86
 	glog.V(5).Infof("Retrieving Docker version")
82 87
 	env, err := h.client.Version()
83 88
 	if err != nil {
84 89
 		glog.V(2).Infof("Error retrieving version: %v", err)
85
-		return nil, err
90
+		return nil, false, err
86 91
 	}
87 92
 	glog.V(5).Infof("Docker version results: %#v", env)
88 93
 	versionStr := env.Get("Version")
89 94
 	if len(versionStr) == 0 {
90
-		return nil, errors.New("did not get a version")
95
+		return nil, false, errors.New("did not get a version")
91 96
 	}
92 97
 	glog.V(5).Infof("Version: %s", versionStr)
93 98
 	dockerVersion, err := semver.Parse(versionStr)
94 99
 	if err != nil {
95 100
 		glog.V(2).Infof("Error parsing Docker version %q", versionStr)
96
-		return nil, err
101
+		return nil, false, err
102
+	}
103
+	isRedHat := false
104
+	packageVersion := env.Get("PkgVersion")
105
+	if len(packageVersion) > 0 {
106
+		isRedHat = fedoraPackage.MatchString(packageVersion) || rhelPackage.MatchString(packageVersion)
97 107
 	}
98
-	return &dockerVersion, nil
108
+	return &dockerVersion, isRedHat, nil
99 109
 }
100 110
 
101 111
 // CheckAndPull checks whether a Docker image exists. If not, it pulls it.
... ...
@@ -7,7 +7,6 @@ import (
7 7
 	"os"
8 8
 	"path"
9 9
 	"path/filepath"
10
-	"runtime"
11 10
 	"strings"
12 11
 
13 12
 	docker "github.com/fsouza/go-dockerclient"
... ...
@@ -55,12 +54,6 @@ func NewHostHelper(client *docker.Client, image, volumesDir, configDir, dataDir
55 55
 
56 56
 // CanUseNsenterMounter returns true if the Docker host machine can execute findmnt through nsenter
57 57
 func (h *HostHelper) CanUseNsenterMounter() (bool, error) {
58
-	// For now, use a shared mount on Windows/Mac
59
-	// Eventually it also needs to be used on Linux, but nsenter
60
-	// is still needed for Docker 1.9
61
-	if runtime.GOOS == "darwin" || runtime.GOOS == "windows" {
62
-		return false, nil
63
-	}
64 58
 	rc, err := h.runner().
65 59
 		Image(h.image).
66 60
 		DiscardContainer().
... ...
@@ -62,18 +62,19 @@ type Helper struct {
62 62
 
63 63
 // StartOptions represent the parameters sent to the start command
64 64
 type StartOptions struct {
65
-	ServerIP          string
66
-	DNSPort           int
67
-	UseSharedVolume   bool
68
-	Images            string
69
-	HostVolumesDir    string
70
-	HostConfigDir     string
71
-	HostDataDir       string
72
-	UseExistingConfig bool
73
-	Environment       []string
74
-	LogLevel          int
75
-	MetricsHost       string
76
-	PortForwarding    bool
65
+	ServerIP           string
66
+	DNSPort            int
67
+	UseSharedVolume    bool
68
+	SetPropagationMode bool
69
+	Images             string
70
+	HostVolumesDir     string
71
+	HostConfigDir      string
72
+	HostDataDir        string
73
+	UseExistingConfig  bool
74
+	Environment        []string
75
+	LogLevel           int
76
+	MetricsHost        string
77
+	PortForwarding     bool
77 78
 }
78 79
 
79 80
 // NewHelper creates a new OpenShift helper
... ...
@@ -218,7 +219,11 @@ func (h *Helper) Start(opt *StartOptions, out io.Writer) (string, error) {
218 218
 		env = append(env, "OPENSHIFT_CONTAINERIZED=false")
219 219
 	} else {
220 220
 		binds = append(binds, "/:/rootfs:ro")
221
-		binds = append(binds, fmt.Sprintf("%[1]s:%[1]s", opt.HostVolumesDir))
221
+		propagationMode := ""
222
+		if opt.SetPropagationMode {
223
+			propagationMode = ":rslave"
224
+		}
225
+		binds = append(binds, fmt.Sprintf("%[1]s:%[1]s%[2]s", opt.HostVolumesDir, propagationMode))
222 226
 	}
223 227
 	env = append(env, opt.Environment...)
224 228
 	binds = append(binds, fmt.Sprintf("%s:/var/lib/origin/openshift.local.config:z", opt.HostConfigDir))
... ...
@@ -100,6 +100,8 @@ var (
100 100
 		"jenkins pipeline persistent": "examples/jenkins/jenkins-persistent-template.json",
101 101
 		"sample pipeline":             "examples/jenkins/pipeline/samplepipeline.json",
102 102
 	}
103
+	dockerVersion19  = semver.MustParse("1.9.0")
104
+	dockerVersion110 = semver.MustParse("1.10.0")
103 105
 )
104 106
 
105 107
 // NewCmdUp creates a command that starts openshift on Docker with reasonable defaults
... ...
@@ -158,16 +160,17 @@ type ClientStartConfig struct {
158 158
 	ShouldInstallMetrics      bool
159 159
 	PortForwarding            bool
160 160
 
161
-	UseNsenterMount bool
162
-	Out             io.Writer
163
-	TaskPrinter     *TaskPrinter
164
-	Tasks           []task
165
-	HostName        string
166
-	ServerIP        string
167
-	CACert          string
168
-	PublicHostname  string
169
-	RoutingSuffix   string
170
-	DNSPort         int
161
+	UseNsenterMount    bool
162
+	SetPropagationMode bool
163
+	Out                io.Writer
164
+	TaskPrinter        *TaskPrinter
165
+	Tasks              []task
166
+	HostName           string
167
+	ServerIP           string
168
+	CACert             string
169
+	PublicHostname     string
170
+	RoutingSuffix      string
171
+	DNSPort            int
171 172
 
172 173
 	LocalConfigDir    string
173 174
 	HostVolumesDir    string
... ...
@@ -216,6 +219,9 @@ func (c *ClientStartConfig) Complete(f *osclientcmd.Factory, cmd *cobra.Command)
216 216
 	// running. Otherwise, use environment variables.
217 217
 	c.addTask("Checking Docker client", c.GetDockerClient)
218 218
 
219
+	// Check that we have the minimum Docker version available to run OpenShift
220
+	c.addTask("Checking Docker version", c.CheckDockerVersion)
221
+
219 222
 	// Check for an OpenShift container. If one exists and is running, exit.
220 223
 	// If one exists but not running, delete it.
221 224
 	c.addTask("Checking for existing OpenShift container", c.CheckExistingOpenShiftContainer)
... ...
@@ -237,9 +243,6 @@ func (c *ClientStartConfig) Complete(f *osclientcmd.Factory, cmd *cobra.Command)
237 237
 	// If not, use a shared volume to mount volumes on OpenShift
238 238
 	c.addTask("Checking type of volume mount", c.CheckNsenterMounter)
239 239
 
240
-	// Check that we have the minimum Docker version available to run OpenShift
241
-	c.addTask("Checking Docker version", c.CheckDockerVersion)
242
-
243 240
 	// Ensure that host directories exist.
244 241
 	// If not using the nsenter mounter, create a volume share on the host machine to
245 242
 	// mount OpenShift volumes.
... ...
@@ -479,20 +482,19 @@ func (c *ClientStartConfig) CheckNsenterMounter(out io.Writer) error {
479 479
 // CheckDockerVersion checks that the appropriate Docker version is installed based on whether we are using the nsenter mounter
480 480
 // or shared volumes for OpenShift
481 481
 func (c *ClientStartConfig) CheckDockerVersion(io.Writer) error {
482
-	var minDockerVersion semver.Version
483
-	if c.UseNsenterMount {
484
-		minDockerVersion = semver.MustParse("1.8.1")
485
-	} else {
486
-		minDockerVersion = semver.MustParse("1.10.0")
487
-	}
488
-	ver, err := c.DockerHelper().Version()
482
+	ver, rh, err := c.DockerHelper().Version()
489 483
 	if err != nil {
490 484
 		return err
491 485
 	}
492
-	glog.V(5).Infof("Checking that docker version is at least %v", minDockerVersion)
493
-	if ver.LT(minDockerVersion) {
494
-		return fmt.Errorf("Docker version is %v, it needs to be %v", ver, minDockerVersion)
486
+	needVersion := dockerVersion19
487
+	if !rh {
488
+		needVersion = dockerVersion110
489
+	}
490
+	glog.V(5).Infof("Checking that docker version is at least %v", needVersion)
491
+	if ver.LT(needVersion) {
492
+		return fmt.Errorf("Docker version is %v, it needs to be %v", ver, needVersion)
495 493
 	}
494
+	c.SetPropagationMode = ver.GTE(dockerVersion110)
496 495
 	return nil
497 496
 }
498 497
 
... ...
@@ -546,17 +548,18 @@ func (c *ClientStartConfig) DetermineServerIP(out io.Writer) error {
546 546
 func (c *ClientStartConfig) StartOpenShift(out io.Writer) error {
547 547
 	var err error
548 548
 	opt := &openshift.StartOptions{
549
-		ServerIP:          c.ServerIP,
550
-		UseSharedVolume:   !c.UseNsenterMount,
551
-		Images:            c.imageFormat(),
552
-		HostVolumesDir:    c.HostVolumesDir,
553
-		HostConfigDir:     c.HostConfigDir,
554
-		HostDataDir:       c.HostDataDir,
555
-		UseExistingConfig: c.UseExistingConfig,
556
-		Environment:       c.Environment,
557
-		LogLevel:          c.ServerLogLevel,
558
-		DNSPort:           c.DNSPort,
559
-		PortForwarding:    c.PortForwarding,
549
+		ServerIP:           c.ServerIP,
550
+		UseSharedVolume:    !c.UseNsenterMount,
551
+		SetPropagationMode: c.SetPropagationMode,
552
+		Images:             c.imageFormat(),
553
+		HostVolumesDir:     c.HostVolumesDir,
554
+		HostConfigDir:      c.HostConfigDir,
555
+		HostDataDir:        c.HostDataDir,
556
+		UseExistingConfig:  c.UseExistingConfig,
557
+		Environment:        c.Environment,
558
+		LogLevel:           c.ServerLogLevel,
559
+		DNSPort:            c.DNSPort,
560
+		PortForwarding:     c.PortForwarding,
560 561
 	}
561 562
 	if c.ShouldInstallMetrics {
562 563
 		opt.MetricsHost = openshift.MetricsHost(c.RoutingSuffix, c.ServerIP)