Ejemplo n.º 1
0
// GetEtcdConfig will return reference to embed.Config object. This
// is to be passed to embed.StartEtcd() function.
func GetEtcdConfig(readConf bool) (*embed.Config, error) {

	// NOTE: This sets most of the fields internally with default values.
	// For example, most of *URL fields are filled with all available IPs
	// of local node i.e binds on all addresses.
	cfg := embed.NewConfig()

	// etcd member names doesn't have to be unique as etcd internally uses
	// UUIDs for member IDs. In practice, etcd instance names are usually
	// set to hostname of node. But we also need to keep the mapping
	// between peers and their etcd names simple. So etcd member names are
	// set to (peer) UUID of glusterd instance.
	cfg.Name = gdctx.MyUUID.String()
	cfg.Dir = cfg.Name + ".etcd"

	listenClientURL, err := url.Parse("http://" + config.GetString("etcdclientaddress"))
	if err != nil {
		return nil, err
	}
	cfg.ACUrls = []url.URL{*listenClientURL}
	cfg.LCUrls = []url.URL{*listenClientURL}

	listenPeerURL, err := url.Parse("http://" + config.GetString("etcdpeeraddress"))
	if err != nil {
		return nil, err
	}
	cfg.APUrls = []url.URL{*listenPeerURL}
	cfg.LPUrls = []url.URL{*listenPeerURL}

	cfg.InitialCluster = cfg.Name + "=" + listenPeerURL.String()
	cfg.ClusterState = embed.ClusterStateFlagNew

	if readConf {
		oldCfg, err := readEtcdConfig()
		if err == nil {
			log.Info("Found saved etcd config file. Using that.")
			cfg.InitialCluster = oldCfg.InitialCluster
			cfg.ClusterState = oldCfg.ClusterState
			cfg.Name = oldCfg.Name
			cfg.Dir = oldCfg.Dir
		}
	}

	return cfg, nil
}
Ejemplo n.º 2
0
func TestEmbedEtcd(t *testing.T) {
	tests := []struct {
		cfg embed.Config

		werr     string
		wpeers   int
		wclients int
	}{
		{werr: "multiple discovery"},
		{werr: "advertise-client-urls is required"},
		{werr: "should be at least"},
		{werr: "is too long"},
		{wpeers: 1, wclients: 1},
		{wpeers: 2, wclients: 1},
		{wpeers: 1, wclients: 2},
	}

	urls := newEmbedURLs(10)

	// setup defaults
	for i := range tests {
		tests[i].cfg = *embed.NewConfig()
	}

	tests[0].cfg.Durl = "abc"
	setupEmbedCfg(&tests[1].cfg, []url.URL{urls[0]}, []url.URL{urls[1]})
	tests[1].cfg.ACUrls = nil
	tests[2].cfg.TickMs = tests[2].cfg.ElectionMs - 1
	tests[3].cfg.ElectionMs = 999999
	setupEmbedCfg(&tests[4].cfg, []url.URL{urls[2]}, []url.URL{urls[3]})
	setupEmbedCfg(&tests[5].cfg, []url.URL{urls[4]}, []url.URL{urls[5], urls[6]})
	setupEmbedCfg(&tests[6].cfg, []url.URL{urls[7], urls[8]}, []url.URL{urls[9]})

	dir := path.Join(os.TempDir(), fmt.Sprintf("embed-etcd"))
	os.RemoveAll(dir)
	defer os.RemoveAll(dir)

	for i, tt := range tests {
		tests[i].cfg.Dir = dir
		e, err := embed.StartEtcd(&tests[i].cfg)
		if tt.werr != "" {
			if err == nil || !strings.Contains(err.Error(), tt.werr) {
				t.Errorf("%d: expected error with %q, got %v", i, tt.werr, err)
			}
			if e != nil {
				e.Close()
			}
			continue
		}
		if err != nil {
			t.Errorf("%d: expected success, got error %v", i, err)
			continue
		}
		if len(e.Peers) != tt.wpeers {
			t.Errorf("%d: expected %d peers, got %d", i, tt.wpeers, len(e.Peers))
		}
		if len(e.Clients) != tt.wclients {
			t.Errorf("%d: expected %d peers, got %d", i, tt.wclients, len(e.Clients))
		}
		e.Close()
	}
}
Ejemplo n.º 3
0
func newConfig() *config {
	cfg := &config{
		Config: *embed.NewConfig(),
		configProxy: configProxy{
			Proxy:                  proxyFlagOff,
			ProxyFailureWaitMs:     5000,
			ProxyRefreshIntervalMs: 30000,
			ProxyDialTimeoutMs:     1000,
			ProxyWriteTimeoutMs:    5000,
		},
		ignored: ignored,
	}
	cfg.configFlags = configFlags{
		FlagSet: flag.NewFlagSet("etcd", flag.ContinueOnError),
		clusterState: flags.NewStringsFlag(
			embed.ClusterStateFlagNew,
			embed.ClusterStateFlagExisting,
		),
		fallback: flags.NewStringsFlag(
			fallbackFlagExit,
			fallbackFlagProxy,
		),
		proxy: flags.NewStringsFlag(
			proxyFlagOff,
			proxyFlagReadonly,
			proxyFlagOn,
		),
	}

	fs := cfg.FlagSet
	fs.Usage = func() {
		fmt.Fprintln(os.Stderr, usageline)
	}

	fs.StringVar(&cfg.configFile, "config-file", "", "Path to the server configuration file")

	// member
	fs.Var(cfg.CorsInfo, "cors", "Comma-separated white list of origins for CORS (cross-origin resource sharing).")
	fs.StringVar(&cfg.Dir, "data-dir", cfg.Dir, "Path to the data directory.")
	fs.StringVar(&cfg.WalDir, "wal-dir", cfg.WalDir, "Path to the dedicated wal directory.")
	fs.Var(flags.NewURLsValue(embed.DefaultListenPeerURLs), "listen-peer-urls", "List of URLs to listen on for peer traffic.")
	fs.Var(flags.NewURLsValue(embed.DefaultListenClientURLs), "listen-client-urls", "List of URLs to listen on for client traffic.")
	fs.UintVar(&cfg.MaxSnapFiles, "max-snapshots", cfg.MaxSnapFiles, "Maximum number of snapshot files to retain (0 is unlimited).")
	fs.UintVar(&cfg.MaxWalFiles, "max-wals", cfg.MaxWalFiles, "Maximum number of wal files to retain (0 is unlimited).")
	fs.StringVar(&cfg.Name, "name", cfg.Name, "Human-readable name for this member.")
	fs.Uint64Var(&cfg.SnapCount, "snapshot-count", cfg.SnapCount, "Number of committed transactions to trigger a snapshot to disk.")
	fs.UintVar(&cfg.TickMs, "heartbeat-interval", cfg.TickMs, "Time (in milliseconds) of a heartbeat interval.")
	fs.UintVar(&cfg.ElectionMs, "election-timeout", cfg.ElectionMs, "Time (in milliseconds) for an election to timeout.")
	fs.Int64Var(&cfg.QuotaBackendBytes, "quota-backend-bytes", cfg.QuotaBackendBytes, "Raise alarms when backend size exceeds the given quota. 0 means use the default quota.")

	// clustering
	fs.Var(flags.NewURLsValue(embed.DefaultInitialAdvertisePeerURLs), "initial-advertise-peer-urls", "List of this member's peer URLs to advertise to the rest of the cluster.")
	fs.Var(flags.NewURLsValue(embed.DefaultAdvertiseClientURLs), "advertise-client-urls", "List of this member's client URLs to advertise to the public.")
	fs.StringVar(&cfg.Durl, "discovery", cfg.Durl, "Discovery URL used to bootstrap the cluster.")
	fs.Var(cfg.fallback, "discovery-fallback", fmt.Sprintf("Valid values include %s", strings.Join(cfg.fallback.Values, ", ")))
	if err := cfg.fallback.Set(fallbackFlagProxy); err != nil {
		// Should never happen.
		plog.Panicf("unexpected error setting up discovery-fallback flag: %v", err)
	}
	fs.StringVar(&cfg.Dproxy, "discovery-proxy", cfg.Dproxy, "HTTP proxy to use for traffic to discovery service.")
	fs.StringVar(&cfg.DNSCluster, "discovery-srv", cfg.DNSCluster, "DNS domain used to bootstrap initial cluster.")
	fs.StringVar(&cfg.InitialCluster, "initial-cluster", cfg.InitialCluster, "Initial cluster configuration for bootstrapping.")
	fs.StringVar(&cfg.InitialClusterToken, "initial-cluster-token", cfg.InitialClusterToken, "Initial cluster token for the etcd cluster during bootstrap.")
	fs.Var(cfg.clusterState, "initial-cluster-state", "Initial cluster state ('new' or 'existing').")
	if err := cfg.clusterState.Set(embed.ClusterStateFlagNew); err != nil {
		// Should never happen.
		plog.Panicf("unexpected error setting up clusterStateFlag: %v", err)
	}
	fs.BoolVar(&cfg.StrictReconfigCheck, "strict-reconfig-check", cfg.StrictReconfigCheck, "Reject reconfiguration requests that would cause quorum loss.")

	// proxy
	fs.Var(cfg.proxy, "proxy", fmt.Sprintf("Valid values include %s", strings.Join(cfg.proxy.Values, ", ")))
	if err := cfg.proxy.Set(proxyFlagOff); err != nil {
		// Should never happen.
		plog.Panicf("unexpected error setting up proxyFlag: %v", err)
	}
	fs.UintVar(&cfg.ProxyFailureWaitMs, "proxy-failure-wait", cfg.ProxyFailureWaitMs, "Time (in milliseconds) an endpoint will be held in a failed state.")
	fs.UintVar(&cfg.ProxyRefreshIntervalMs, "proxy-refresh-interval", cfg.ProxyRefreshIntervalMs, "Time (in milliseconds) of the endpoints refresh interval.")
	fs.UintVar(&cfg.ProxyDialTimeoutMs, "proxy-dial-timeout", cfg.ProxyDialTimeoutMs, "Time (in milliseconds) for a dial to timeout.")
	fs.UintVar(&cfg.ProxyWriteTimeoutMs, "proxy-write-timeout", cfg.ProxyWriteTimeoutMs, "Time (in milliseconds) for a write to timeout.")
	fs.UintVar(&cfg.ProxyReadTimeoutMs, "proxy-read-timeout", cfg.ProxyReadTimeoutMs, "Time (in milliseconds) for a read to timeout.")

	// security
	fs.StringVar(&cfg.ClientTLSInfo.CAFile, "ca-file", "", "DEPRECATED: Path to the client server TLS CA file.")
	fs.StringVar(&cfg.ClientTLSInfo.CertFile, "cert-file", "", "Path to the client server TLS cert file.")
	fs.StringVar(&cfg.ClientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.")
	fs.BoolVar(&cfg.ClientTLSInfo.ClientCertAuth, "client-cert-auth", false, "Enable client cert authentication.")
	fs.StringVar(&cfg.ClientTLSInfo.TrustedCAFile, "trusted-ca-file", "", "Path to the client server TLS trusted CA key file.")
	fs.BoolVar(&cfg.ClientAutoTLS, "auto-tls", false, "Client TLS using generated certificates")
	fs.StringVar(&cfg.PeerTLSInfo.CAFile, "peer-ca-file", "", "DEPRECATED: Path to the peer server TLS CA file.")
	fs.StringVar(&cfg.PeerTLSInfo.CertFile, "peer-cert-file", "", "Path to the peer server TLS cert file.")
	fs.StringVar(&cfg.PeerTLSInfo.KeyFile, "peer-key-file", "", "Path to the peer server TLS key file.")
	fs.BoolVar(&cfg.PeerTLSInfo.ClientCertAuth, "peer-client-cert-auth", false, "Enable peer client cert authentication.")
	fs.StringVar(&cfg.PeerTLSInfo.TrustedCAFile, "peer-trusted-ca-file", "", "Path to the peer server TLS trusted CA file.")
	fs.BoolVar(&cfg.PeerAutoTLS, "peer-auto-tls", false, "Peer TLS using generated certificates")

	// logging
	fs.BoolVar(&cfg.Debug, "debug", false, "Enable debug-level logging for etcd.")
	fs.StringVar(&cfg.LogPkgLevels, "log-package-levels", "", "Specify a particular log level for each etcd package (eg: 'etcdmain=CRITICAL,etcdserver=DEBUG').")
	fs.StringVar(&cfg.logOutput, "log-output", "default", "Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd.")

	// unsafe
	fs.BoolVar(&cfg.ForceNewCluster, "force-new-cluster", false, "Force to create a new one member cluster.")

	// version
	fs.BoolVar(&cfg.printVersion, "version", false, "Print the version and exit.")

	fs.IntVar(&cfg.AutoCompactionRetention, "auto-compaction-retention", 0, "Auto compaction retention for mvcc key value store in hour. 0 means disable auto compaction.")

	// pprof profiler via HTTP
	fs.BoolVar(&cfg.EnablePprof, "enable-pprof", false, "Enable runtime profiling data via HTTP server. Address is at client URL + \"/debug/pprof/\"")

	// ignored
	for _, f := range cfg.ignored {
		fs.Var(&flags.IgnoredFlag{Name: f}, f, "")
	}
	return cfg
}
Ejemplo n.º 4
0
// RunEtcd starts an etcd server and runs it forever
func RunEtcd(etcdServerConfig *configapi.EtcdConfig) {
	cfg := embed.NewConfig()
	cfg.Debug = true
	cfg.Name = defaultName
	cfg.Dir = etcdServerConfig.StorageDir

	clientTLS := configapi.UseTLS(etcdServerConfig.ServingInfo)
	if clientTLS {
		cfg.ClientTLSInfo.CAFile = etcdServerConfig.ServingInfo.ClientCA
		cfg.ClientTLSInfo.CertFile = etcdServerConfig.ServingInfo.ServerCert.CertFile
		cfg.ClientTLSInfo.KeyFile = etcdServerConfig.ServingInfo.ServerCert.KeyFile
		cfg.ClientTLSInfo.ClientCertAuth = len(cfg.ClientTLSInfo.CAFile) > 0
	}
	u, err := types.NewURLs(addressToURLs(etcdServerConfig.ServingInfo.BindAddress, clientTLS))
	if err != nil {
		glog.Fatalf("Unable to build etcd peer URLs: %v", err)
	}
	cfg.LCUrls = []url.URL(u)

	peerTLS := configapi.UseTLS(etcdServerConfig.PeerServingInfo)
	if peerTLS {
		cfg.PeerTLSInfo.CAFile = etcdServerConfig.PeerServingInfo.ClientCA
		cfg.PeerTLSInfo.CertFile = etcdServerConfig.PeerServingInfo.ServerCert.CertFile
		cfg.PeerTLSInfo.KeyFile = etcdServerConfig.PeerServingInfo.ServerCert.KeyFile
		cfg.PeerTLSInfo.ClientCertAuth = len(cfg.PeerTLSInfo.CAFile) > 0
	}
	u, err = types.NewURLs(addressToURLs(etcdServerConfig.PeerServingInfo.BindAddress, peerTLS))
	if err != nil {
		glog.Fatalf("Unable to build etcd peer URLs: %v", err)
	}
	cfg.LPUrls = []url.URL(u)

	u, err = types.NewURLs(addressToURLs(etcdServerConfig.Address, clientTLS))
	if err != nil {
		glog.Fatalf("Unable to build etcd announce client URLs: %v", err)
	}
	cfg.ACUrls = []url.URL(u)

	u, err = types.NewURLs(addressToURLs(etcdServerConfig.PeerAddress, peerTLS))
	if err != nil {
		glog.Fatalf("Unable to build etcd announce peer URLs: %v", err)
	}
	cfg.APUrls = []url.URL(u)

	cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name)

	osutil.HandleInterrupts()

	e, err := embed.StartEtcd(cfg)
	if err != nil {
		glog.Fatalf("Unable to start etcd: %v", err)
	}

	go func() {
		defer e.Close()

		select {
		case <-e.Server.ReadyNotify():
			glog.Infof("Started etcd at %s", etcdServerConfig.Address)
		case <-time.After(60 * time.Second):
			glog.Warning("etcd took too long to start, stopped")
			e.Server.Stop() // trigger a shutdown
		}
		glog.Fatalf("etcd has returned an error: %v", <-e.Err())
	}()
}