Esempio n. 1
0
// Daemon is the top-level entrypoint for the volsupervisor from the CLI.
func Daemon(ctx *cli.Context) {
	cfg, err := config.NewClient(ctx.String("prefix"), ctx.StringSlice("etcd"))
	if err != nil {
		logrus.Fatal(err)
	}

retry:
	global, err := cfg.GetGlobal()
	if err != nil {
		logrus.Errorf("Could not retrieve global configuration: %v. Retrying in 1 second", err)
		time.Sleep(time.Second)
		goto retry
	}

	dc := &DaemonConfig{Config: cfg, Global: global, Hostname: ctx.String("host-label")}
	dc.setDebug()

	globalChan := make(chan *watch.Watch)
	dc.Config.WatchGlobal(globalChan)
	go dc.watchAndSetGlobal(globalChan)
	go info.HandleDebugSignal()

	stopChan, err := lock.NewDriver(dc.Config).AcquireWithTTLRefresh(&config.UseVolsupervisor{Hostname: dc.Hostname}, dc.Global.TTL, dc.Global.Timeout)
	if err != nil {
		logrus.Fatal("Could not start volsupervisor: already in use")
	}

	sigChan := make(chan os.Signal, 1)

	go func() {
		<-sigChan
		logrus.Infof("Removing volsupervisor global lock; waiting %v for lock to clear", dc.Global.TTL)
		stopChan <- struct{}{}
		time.Sleep(wait.Jitter(dc.Global.TTL+time.Second, 0)) // give us enough time to try to clear the lock
		os.Exit(0)
	}()

	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)

	dc.signalSnapshot()
	dc.updateVolumes()
	// doing it here ensures the goroutine is created when the first poll completes.
	go func() {
		for {
			time.Sleep(wait.Jitter(time.Second, 0))
			dc.updateVolumes()
		}
	}()

	dc.loop()
}
Esempio n. 2
0
// Daemon starts the volplugin service.
func (dc *DaemonConfig) Daemon() error {
	global, err := dc.Client.GetGlobal()
	if err != nil {
		logrus.Errorf("Error fetching global configuration: %v", err)
		logrus.Infof("No global configuration. Proceeding with defaults...")
		global = config.NewGlobalConfig()
	}

	dc.Global = global
	errored.AlwaysDebug = dc.Global.Debug
	errored.AlwaysTrace = dc.Global.Debug
	if dc.Global.Debug {
		logrus.SetLevel(logrus.DebugLevel)
	}

	go info.HandleDebugSignal()

	activity := make(chan *watch.Watch)
	dc.Client.WatchGlobal(activity)
	go func() {
		for {
			dc.Global = (<-activity).Config.(*config.Global)

			logrus.Debugf("Received global %#v", dc.Global)

			errored.AlwaysDebug = dc.Global.Debug
			errored.AlwaysTrace = dc.Global.Debug
			if dc.Global.Debug {
				logrus.SetLevel(logrus.DebugLevel)
			}
		}
	}()

	dc.API = api.NewAPI(docker.NewVolplugin(), dc.Hostname, dc.Client, &dc.Global)

	if err := dc.updateMounts(); err != nil {
		return err
	}

	go dc.pollRuntime()

	driverPath := path.Join(basePath, fmt.Sprintf("%s.sock", dc.PluginName))
	if err := os.Remove(driverPath); err != nil && !os.IsNotExist(err) {
		return err
	}
	if err := os.MkdirAll(basePath, 0700); err != nil {
		return err
	}

	l, err := net.ListenUnix("unix", &net.UnixAddr{Name: driverPath, Net: "unix"})
	if err != nil {
		return err
	}

	srv := http.Server{Handler: dc.API.Router(dc.API)}
	srv.SetKeepAlivesEnabled(false)
	if err := srv.Serve(l); err != nil {
		logrus.Fatalf("Fatal error serving volplugin: %v", err)
	}
	l.Close()
	return os.Remove(driverPath)
}
Esempio n. 3
0
// Daemon initializes the daemon for use.
func (d *DaemonConfig) Daemon(listen string) {
	global, err := d.Config.GetGlobal()
	if err != nil {
		logrus.Errorf("Error fetching global configuration: %v", err)
		logrus.Infof("No global configuration. Proceeding with defaults...")
		global = config.NewGlobalConfig()
	}

	d.Global = global
	if d.Global.Debug {
		logrus.SetLevel(logrus.DebugLevel)
	}
	errored.AlwaysDebug = d.Global.Debug
	errored.AlwaysTrace = d.Global.Debug

	go info.HandleDebugSignal()
	go info.HandleDumpTarballSignal(d.Config)

	activity := make(chan *watch.Watch)
	d.Config.WatchGlobal(activity)
	go func() {
		for {
			d.Global = (<-activity).Config.(*config.Global)

			errored.AlwaysDebug = d.Global.Debug
			errored.AlwaysTrace = d.Global.Debug
			if d.Global.Debug {
				logrus.SetLevel(logrus.DebugLevel)
			}
		}
	}()

	r := mux.NewRouter()

	postRouter := map[string]func(http.ResponseWriter, *http.Request){
		"/global":                           d.handleGlobalUpload,
		"/volumes/create":                   d.handleCreate,
		"/volumes/copy":                     d.handleCopy,
		"/volumes/request":                  d.handleRequest,
		"/policies/{policy}":                d.handlePolicyUpload,
		"/runtime/{policy}/{volume}":        d.handleRuntimeUpload,
		"/snapshots/take/{policy}/{volume}": d.handleSnapshotTake,
	}

	if err := addRoute(r, postRouter, "POST", d.Global.Debug); err != nil {
		logrus.Fatalf("Error starting apiserver: %v", err)
	}

	deleteRouter := map[string]func(http.ResponseWriter, *http.Request){
		"/volumes/remove":      d.handleRemove,
		"/volumes/removeforce": d.handleRemoveForce,
		"/policies/{policy}":   d.handlePolicyDelete,
	}

	if err := addRoute(r, deleteRouter, "DELETE", d.Global.Debug); err != nil {
		logrus.Fatalf("Error starting apiserver: %v", err)
	}

	getRouter := map[string]func(http.ResponseWriter, *http.Request){
		"/global":                              d.handleGlobal,
		"/policy-archives/{policy}":            d.handlePolicyListRevisions,
		"/policy-archives/{policy}/{revision}": d.handlePolicyGetRevision,
		"/policies":                            d.handlePolicyList,
		"/policies/{policy}":                   d.handlePolicy,
		"/uses/mounts/{policy}/{volume}":       d.handleUsesMountsVolume,
		"/uses/snapshots/{policy}/{volume}":    d.handleUsesMountsSnapshots,
		"/volumes":                             d.handleListAll,
		"/volumes/{policy}":                    d.handleList,
		"/volumes/{policy}/{volume}":           d.handleGet,
		"/runtime/{policy}/{volume}":           d.handleRuntime,
		"/snapshots/{policy}/{volume}":         d.handleSnapshotList,
	}

	if err := addRoute(r, getRouter, "GET", d.Global.Debug); err != nil {
		logrus.Fatalf("Error starting apiserver: %v", err)
	}

	if d.Global.Debug {
		r.HandleFunc("{action:.*}", d.handleDebug)
	}

	if err := http.ListenAndServe(listen, r); err != nil {
		logrus.Fatalf("Error starting apiserver: %v", err)
	}
}