func run() error { gettext.BindTextdomain("lxd", "", nil) gettext.Textdomain("lxd") verbose := gnuflag.Bool("v", false, gettext.Gettext("Enables verbose mode.")) debug := gnuflag.Bool("debug", false, gettext.Gettext("Enables debug mode.")) gnuflag.StringVar(&lxd.ConfigDir, "config", lxd.ConfigDir, gettext.Gettext("Alternate config directory.")) if len(os.Args) >= 3 && os.Args[1] == "config" && os.Args[2] == "profile" { fmt.Fprintf(os.Stderr, "`lxc config profile` is deprecated, please use `lxc profile`\n") os.Args = append(os.Args[:1], os.Args[2:]...) } if len(os.Args) == 2 && (os.Args[1] == "-h" || os.Args[1] == "--help") { os.Args[1] = "help" } if len(os.Args) == 2 && os.Args[1] == "--version" { os.Args[1] = "version" } if len(os.Args) < 2 { commands["help"].run(nil, nil) os.Exit(1) } name := os.Args[1] cmd, ok := commands[name] if !ok { fmt.Fprintf(os.Stderr, gettext.Gettext("error: unknown command: %s\n"), name) commands["help"].run(nil, nil) os.Exit(1) } cmd.flags() gnuflag.Usage = func() { fmt.Fprintf(os.Stderr, gettext.Gettext("Usage: %s\n\nOptions:\n\n"), strings.TrimSpace(cmd.usage())) gnuflag.PrintDefaults() } os.Args = os.Args[1:] gnuflag.Parse(true) if *verbose || *debug { shared.SetLogger(log.New(os.Stderr, "", log.LstdFlags)) shared.SetDebug(*debug) } config, err := lxd.LoadConfig() if err != nil { return err } certf := lxd.ConfigPath("client.crt") keyf := lxd.ConfigPath("client.key") if os.Args[0] != "help" && os.Args[0] != "version" && (!shared.PathExists(certf) || !shared.PathExists(keyf)) { fmt.Fprintf(os.Stderr, gettext.Gettext("Generating a client certificate. This may take a minute...\n")) err = shared.FindOrGenCert(certf, keyf) if err != nil { return err } fmt.Fprintf(os.Stderr, gettext.Gettext("If this is your first run, you will need to import images using the 'lxd-images' script.\n")) fmt.Fprintf(os.Stderr, gettext.Gettext("For example: 'lxd-images import lxc ubuntu trusty amd64 --alias ubuntu/trusty'.\n")) } err = cmd.run(config, gnuflag.Args()) if err == errArgs { fmt.Fprintf(os.Stderr, gettext.Gettext("error: %v\n%s"), err, cmd.usage()) os.Exit(1) } return err }
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 } if *verbose || *debug { shared.SetLogger(log.New(os.Stderr, "", log.LstdFlags)) shared.SetDebug(*debug) } 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() } needed_programs := []string{"setfacl", "rsync", "tar", "xz"} for _, p := range needed_programs { _, 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(*listenAddr) if err != nil { if d != nil && d.db != nil { d.db.Close() } return err } defer d.db.Close() 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.Debugf("Received '%s signal', shutting down containers.\n", 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.Debugf("Received '%s signal', exiting.\n", sig) ret = d.Stop() wg.Done() }() wg.Wait() return ret }