Beispiel #1
0
func run() error {
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "forkstart":
			return startContainer(os.Args[1:])
		case "forkmigrate":
			return migration.MigrateContainer(os.Args[1:])
			/*
				case "forkputfile" and "forkgetfile" handled specially in copyfile.go
			*/
		}
	}

	gnuflag.Usage = func() {
		fmt.Printf("Usage: lxd [options]\n\nOptions:\n")
		gnuflag.PrintDefaults()
	}

	gnuflag.Parse(true)
	if *help {
		// The user asked for help via --help, so we shouldn't print to
		// stderr.
		gnuflag.SetOut(os.Stdout)
		gnuflag.Usage()
		return nil
	}

	if *version {
		fmt.Println(shared.Version)
		return nil
	}

	// Configure logging
	syslog := ""
	if *syslogFlag {
		syslog = "lxd"
	}

	err := shared.SetLogger(syslog, *logfile, *verbose, *debug)
	if err != nil {
		fmt.Printf("%s", err)
		return nil
	}

	if gnuflag.NArg() != 0 {
		gnuflag.Usage()
		return fmt.Errorf("Unknown arguments")
	}

	if *cpuProfile != "" {
		f, err := os.Create(*cpuProfile)
		if err != nil {
			fmt.Printf("Error opening cpu profile file: %s\n", err)
			return nil
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *memProfile != "" {
		go memProfiler()
	}

	neededPrograms := []string{"setfacl", "rsync", "tar", "xz"}
	for _, p := range neededPrograms {
		_, err := exec.LookPath(p)
		if err != nil {
			return err
		}
	}

	if *printGoroutines > 0 {
		go func() {
			for {
				time.Sleep(time.Duration(*printGoroutines) * time.Second)
				shared.PrintStack()
			}
		}()
	}

	d, err := startDaemon()

	if err != nil {
		if d != nil && d.db != nil {
			d.db.Close()
		}
		return err
	}

	var ret error
	var wg sync.WaitGroup
	wg.Add(1)

	go func() {
		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGPWR)
		sig := <-ch

		shared.Log.Info(
			fmt.Sprintf("Received '%s signal', shutting down containers.", sig))

		ret = d.Stop()

		containersShutdown(d)
		wg.Done()
	}()

	go func() {
		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGINT)
		signal.Notify(ch, syscall.SIGQUIT)
		signal.Notify(ch, syscall.SIGTERM)
		sig := <-ch

		shared.Log.Info(fmt.Sprintf("Received '%s signal', exiting.\n", sig))
		ret = d.Stop()
		wg.Done()
	}()

	wg.Wait()
	return ret
}
Beispiel #2
0
func run() error {
	gnuflag.Usage = func() {
		fmt.Printf("Usage: lxd [command] [options]\n\nOptions:\n")
		gnuflag.PrintDefaults()

		fmt.Printf("\nCommands:\n")
		fmt.Printf("    shutdown\n")
		fmt.Printf("        Perform a clean shutdown of LXD and all running containers\n")
		fmt.Printf("    activateifneeded\n")
		fmt.Printf("        Check if LXD should be started (at boot) and if so, spawn it through socket activation\n")

		fmt.Printf("\nInternal commands (don't call directly):\n")
		fmt.Printf("    forkgetfile\n")
		fmt.Printf("        Grab a file from a running container\n")
		fmt.Printf("    forkputfile\n")
		fmt.Printf("        Pushes a file to a running container\n")
		fmt.Printf("    forkstart\n")
		fmt.Printf("        Start a container\n")
		fmt.Printf("    forkmigrate\n")
		fmt.Printf("        Restore a container after migration\n")
	}

	gnuflag.Parse(true)
	if *help {
		// The user asked for help via --help, so we shouldn't print to
		// stderr.
		gnuflag.SetOut(os.Stdout)
		gnuflag.Usage()
		return nil
	}

	if *version {
		fmt.Println(shared.Version)
		return nil
	}

	// Configure logging
	syslog := ""
	if *syslogFlag {
		syslog = "lxd"
	}

	err := shared.SetLogger(syslog, *logfile, *verbose, *debug)
	if err != nil {
		fmt.Printf("%s", err)
		return nil
	}

	// Process sub-commands
	if len(os.Args) > 1 {
		// "forkputfile" and "forkgetfile" are handled specially in copyfile.go
		switch os.Args[1] {
		case "forkstart":
			return startContainer(os.Args[1:])
		case "forkmigrate":
			return migration.MigrateContainer(os.Args[1:])
		case "shutdown":
			return cleanShutdown()
		case "activateifneeded":
			return activateIfNeeded()
		}
	}

	if gnuflag.NArg() != 0 {
		gnuflag.Usage()
		return fmt.Errorf("Unknown arguments")
	}

	if *cpuProfile != "" {
		f, err := os.Create(*cpuProfile)
		if err != nil {
			fmt.Printf("Error opening cpu profile file: %s\n", err)
			return nil
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *memProfile != "" {
		go memProfiler()
	}

	neededPrograms := []string{"setfacl", "rsync", "tar", "xz"}
	for _, p := range neededPrograms {
		_, err := exec.LookPath(p)
		if err != nil {
			return err
		}
	}

	_, err = exec.LookPath("apparmor_parser")
	if err == nil && shared.IsDir("/sys/kernel/security/apparmor") {
		aaEnabled = true
	} else {
		shared.Log.Warn("apparmor_parser binary not found or apparmor " +
			"fs not mounted. AppArmor disabled.")
	}

	/* Can we create devices? */
	checkCanMknod()

	if *printGoroutines > 0 {
		go func() {
			for {
				time.Sleep(time.Duration(*printGoroutines) * time.Second)
				shared.PrintStack()
			}
		}()
	}

	d, err := startDaemon()

	if err != nil {
		if d != nil && d.db != nil {
			d.db.Close()
		}
		return err
	}

	var ret error
	var wg sync.WaitGroup
	wg.Add(1)

	go func() {
		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGPWR)
		sig := <-ch

		shared.Log.Info(
			fmt.Sprintf("Received '%s signal', shutting down containers.", sig))

		containersShutdown(d)

		ret = d.Stop()
		wg.Done()
	}()

	go func() {
		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGINT)
		signal.Notify(ch, syscall.SIGQUIT)
		signal.Notify(ch, syscall.SIGTERM)
		sig := <-ch

		shared.Log.Info(fmt.Sprintf("Received '%s signal', exiting.\n", sig))
		ret = d.Stop()
		wg.Done()
	}()

	wg.Wait()
	return ret
}