예제 #1
0
func main() {
	cfg := config.NewDefaultConfig("", "", "")
	err := cfg.LoadConfig()
	if err != nil {
		fmt.Printf("Error loading config")
	}

	err = canolog.Init(".canopy-ops.log")
	if err != nil {
		fmt.Println(err)
		return
	}
	flag.Parse()
	cmd := canopy_ops.FindCommand(cmds, flag.Arg(0))
	info := canopy_ops.CommandInfo{
		CmdList: cmds,
		Cfg:     cfg,
		Args:    flag.Args(),
	}
	if cmd != nil {
		cmd.Perform(info)
	} else if flag.Arg(0) == "create-account" {
		dl := cassandra_datalayer.NewDatalayer(cfg)
		conn, _ := dl.Connect("canopy")
		conn.CreateAccount(flag.Arg(1), flag.Arg(2), flag.Arg(3))
	} else if flag.Arg(0) == "delete-account" {
		dl := cassandra_datalayer.NewDatalayer(cfg)
		conn, _ := dl.Connect("canopy")
		conn.DeleteAccount(flag.Arg(1))
	} else if flag.Arg(0) == "create-device" {
		dl := cassandra_datalayer.NewDatalayer(cfg)
		conn, _ := dl.Connect("canopy")

		account, err := conn.LookupAccount(flag.Arg(1))
		if err != nil {
			fmt.Println("Unable to lookup account ", flag.Arg(1), ":", err)
			return
		}

		device, err := conn.CreateDevice(flag.Arg(2), nil, "", datalayer.NoAccess)
		if err != nil {
			fmt.Println("Unable to create device: ", err)
			return
		}

		err = device.SetAccountAccess(account, datalayer.ReadWriteAccess, datalayer.ShareRevokeAllowed)
		if err != nil {
			fmt.Println("Unable to grant account access to device: ", err)
			return
		}
	} else if flag.Arg(0) == "list-devices" {
		dl := cassandra_datalayer.NewDatalayer(cfg)
		conn, _ := dl.Connect("canopy")

		account, err := conn.LookupAccount(flag.Arg(1))
		if err != nil {
			fmt.Println("Unable to lookup account ", flag.Arg(1), ":", err)
			return
		}

		devices, err := account.Devices().DeviceList(0, -1)
		if err != nil {
			fmt.Println("Error reading devices: ", err)
			return
		}
		for _, device := range devices {
			fmt.Printf("%s %s\n", device.ID(), device.Name())
		}

	} else if flag.Arg(0) == "gen-fake-sensor-data" {
		dl := cassandra_datalayer.NewDatalayer(cfg)
		conn, _ := dl.Connect("canopy")
		deviceId, err := gocql.ParseUUID(flag.Arg(1))
		if err != nil {
			fmt.Println("Error parsing UUID: ", flag.Arg(1), ":", err)
			return
		}
		_, err = conn.LookupDevice(deviceId)
		if err != nil {
			fmt.Println("Device not found: ", flag.Arg(1), ":", err)
			return
		}
		for i := 0; i < 100; i++ {
			//val := float64(i % 16);
			//t := time.Now().Add(time.Duration(-i)*time.Second)
			//err = device.InsertSensorSample(flag.Arg(2), t, val)
			//if err != nil {
			fmt.Println("Error inserting sample: ", err)
			//}
		}
	} else if flag.Arg(0) == "clear-sensor-data" {
		dl := cassandra_datalayer.NewDatalayer(cfg)
		conn, _ := dl.Connect("canopy")
		conn.ClearSensorData()

	} else if flag.Arg(0) == "test-email" {
		mailer, err := mail.NewMailClient(cfg)
		if err != nil {
			fmt.Println("Error initializing mail client: ", err)
			return
		}
		mail := mailer.NewMail()
		err = mail.AddTo(flag.Arg(1), "Customer")
		if err != nil {
			fmt.Println("Invalid recipient: ", flag.Arg(1), err)
			return
		}
		mail.SetSubject("Test email from Canopy")
		mail.SetHTML("<b>Canopy Rulez</b>")
		mail.SetFrom("*****@*****.**", "The Canopy Team")
		err = mailer.Send(mail)
		if err != nil {
			fmt.Println("Error sending email:", err)
			return
		}
		fmt.Println("Email sent.")
	} else if flag.Arg(0) == "migrate-db" {
		startVersion := flag.Arg(1)
		if startVersion == "" {
			fmt.Println("<startVersion> required")
			return
		}
		endVersion := flag.Arg(2)
		if endVersion == "" {
			fmt.Println("<endVersion> required")
			return
		}
		dl := cassandra_datalayer.NewDatalayer(cfg)
		err := dl.MigrateDB("canopy", startVersion, endVersion)
		if err != nil {
			fmt.Println(err.Error())
		}
	} else if len(flag.Args()) == 0 {
		cmds[0].Perform(info)
	} else {
		fmt.Println("Unknown command '" + flag.Arg(0) + "'.  See 'canopy-ops help'.")
	}
}
예제 #2
0
func main() {
	/*if true {
	    passed := device_filter.RunTests()
	    fmt.Println(passed)
	    return
	}*/
	r := mux.NewRouter()

	cfg := config.NewDefaultConfig(buildVersion, buildDate, buildCommit)
	err := cfg.LoadConfig()
	if err != nil {
		logFilename := config.JustGetOptLogFile()

		err2 := canolog.Init(logFilename)
		if err2 != nil {
			fmt.Println(err)
			return
		}
		canolog.Info("Starting Canopy Cloud Service")
		canolog.Error("Configuration error: %s", err)
		canolog.Info("Exiting")
		return
	}

	err = canolog.Init(cfg.OptLogFile())
	if err != nil {
		fmt.Println(err)
		return
	}

	canolog.Info("Starting Canopy Cloud Service")
	canolog.Info("Version:", cfg.BuildVersion())
	canolog.Info("Build Date:", cfg.BuildDate())
	canolog.Info("Build Commit:", cfg.BuildCommit())

	// Log crashes
	defer func() {
		r := recover()
		if r != nil {
			var buf [4096]byte
			runtime.Stack(buf[:], false)
			canolog.Error("PANIC ", r, string(buf[:]))
			panic(r)
		}
		shutdown()
	}()
	// handle SIGINT & SIGTERM
	c := make(chan os.Signal, 1)
	c2 := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c2, syscall.SIGTERM)
	go func() {
		<-c
		canolog.Info("SIGINT recieved")
		shutdown()
		os.Exit(1)
	}()
	go func() {
		<-c2
		canolog.Info("SIGTERM recieved")
		shutdown()
		os.Exit(1)
	}()

	if cfg.OptHostname() == "" {
		canolog.Error("You must set the configuration option \"hostname\"")
		return
	}

	if cfg.OptPasswordSecretSalt() == "" {
		canolog.Error("You must set the configuration option \"password-secret-salt\"")
		return
	}
	canolog.Info(cfg.ToString())

	pigeonSys, err := jobqueue.NewPigeonSystem(cfg)
	if err != nil {
		canolog.Error("Error initializing messaging system (Pigeon):", err)
		return
	}

	pigeonServer, err := pigeonSys.StartServer("localhost") // TODO use configured host
	if err != nil {
		canolog.Error("Unable to start messaging server (Pigeon):", err)
		return
	}

	pigeonOutbox := pigeonSys.NewOutbox()

	err = jobs.InitJobServer(cfg, pigeonServer)
	if err != nil {
		canolog.Error("Unable to initialize Job Server", err)
		return
	}

	if cfg.OptForwardOtherHosts() != "" {
		canolog.Info("Requests to hosts other than ", cfg.OptHostname(), " will be forwarded to ", cfg.OptForwardOtherHosts())
		targetUrl, _ := url.Parse(cfg.OptForwardOtherHosts())
		reverseProxy := httputil.NewSingleHostReverseProxy(targetUrl)
		http.Handle("/", reverseProxy)
	} else {
		canolog.Info("No reverse proxy for other hosts consfigured.")
	}

	hostname := cfg.OptHostname()
	webManagerPath := cfg.OptWebManagerPath()
	jsClientPath := cfg.OptJavascriptClientPath()
	http.Handle(hostname+"/echo", websocket.Handler(ws.NewCanopyWebsocketServer(cfg, pigeonOutbox, pigeonServer)))

	webapp.AddRoutes(r)
	rest.AddRoutes(r, cfg, pigeonSys)

	http.Handle(hostname+"/", r)

	if webManagerPath != "" {
		http.Handle(hostname+"/mgr/", http.StripPrefix("/mgr/", http.FileServer(http.Dir(webManagerPath))))
	}

	if jsClientPath != "" {
		http.Handle(hostname+"/canopy-js-client/", http.StripPrefix("/canopy-js-client/", http.FileServer(http.Dir(jsClientPath))))
	}

	// Run HTTP and HTTPS servers simultaneously (if both are enabled)
	httpResultChan := make(chan error)
	httpsResultChan := make(chan error)
	if cfg.OptEnableHTTP() {
		go func() {
			httpPort := cfg.OptHTTPPort()
			srv := &http.Server{
				Addr:    fmt.Sprintf(":%d", httpPort),
				Handler: context.ClearHandler(http.DefaultServeMux),
			}
			err = srv.ListenAndServe()
			httpResultChan <- err
		}()
	}
	if cfg.OptEnableHTTPS() {
		go func() {
			httpsPort := cfg.OptHTTPSPort()
			httpsCertFile := cfg.OptHTTPSCertFile()
			httpsPrivKeyFile := cfg.OptHTTPSPrivKeyFile()
			srv := &http.Server{
				Addr:    fmt.Sprintf(":%d", httpsPort),
				Handler: context.ClearHandler(http.DefaultServeMux),
			}
			err := srv.ListenAndServeTLS(httpsCertFile, httpsPrivKeyFile)
			httpsResultChan <- err
		}()
	}

	// Exit if either server has error
	select {
	case err := <-httpResultChan:
		canolog.Error(err)
	case err := <-httpsResultChan:
		canolog.Error(err)
	}

}