func startListen() { fmt.Println("Running reboot listener") libvirt.EventRegisterDefaultImpl() // EventRunDefaultImpl has to be run before register. or no events caught, // I do not know why go func() { for { ret := libvirt.EventRunDefaultImpl() if ret == -1 { fmt.Println("RuN failed") break } } }() }
//TODO move all sql to model.go func main() { /* init database */ db, err := sql.Open("sqlite3", "/tmp/post_db.bin") if err != nil { checkErr(err, "open database failed") return } defer db.Close() var scanning int32 = 0 m := martini.Classic() m.Use(render.Renderer()) m.Get("/", func(r render.Render) { r.Redirect("index.html") }) //Install a new VM m.Get("/create", func(r render.Render) { var Name string var IpAddress string type HostInfo struct { Name string IpAddress string } type Hosts struct { Hosts []HostInfo } //var hosts []HostInfo var hosts Hosts rows, err := db.Query("select Name,IpAddress from physicalmachine") if err != nil { reportError(r, err, "failed to find physicalmachine") } for rows.Next() { rows.Scan(&Name, &IpAddress) hosts.Hosts = append(hosts.Hosts, HostInfo{Name, IpAddress}) //hosts = append(hosts, HostInfo{Name, IpAddress}) } log.Println(hosts) r.JSON(200, hosts) }) m.Post("/create", func(r render.Render, req *http.Request) { name := req.PostFormValue("Name") ip := req.PostFormValue("IpAddress") repo := req.PostFormValue("repo") diskSize := req.PostFormValue("disk") autoinst := req.PostFormValue("autoinst") //check input data imageSize, err := strconv.Atoi(diskSize) if err != nil { reportError(r, err, "convert failed") return } //convert to GB imageSize = imageSize << 30 conn, err := getConnectionFromCacheByIP(ip) if err != nil { reportError(r, err, "no connections") return } log.Println(conn) ch := make(chan string, 100) go vminstall.VmInstall(conn, name, repo, autoinst, uint64(imageSize), ch) //map token_uuid <=> {channel,name,connection,ip} token := uuid.New() t := TokenContentForVMInstall{Ch: ch, Name: name, Conn: conn, IPAddress: ip} tokenMap.Set(token, t) type TokenJson struct { Token string } var tokenJson TokenJson tokenJson.Token = token r.JSON(200, tokenJson) }) m.Get("/add", func(r render.Render) { r.HTML(200, "add", nil) }) //missing validation //ADD new PhysicalMachine m.Post("/add", func(r render.Render, req *http.Request) { var existingname string name := req.PostFormValue("Name") description := req.PostFormValue("Description") IPAddress := req.PostFormValue("IPAddress") log.Println(name + description + IPAddress) //TODO: add more validations err := db.QueryRow("select name from physicalmachine where IpAddress = ?", IPAddress).Scan(&existingname) switch { case err == sql.ErrNoRows: // good to insert the PhysicalMachine db.Exec("insert into physicalmachine (Name, IpAddress, Description) values(?,?,?)", name, IPAddress, description) r.Redirect("/") case err != nil: //other error happens r.HTML(501, "error", err) default: //no error happens r.HTML(501, "error", fmt.Errorf("already has the physical machine %s", existingname)) } }) m.Get("/vm/(?P<id>[0-9]+)", func(r render.Render, params martini.Params) { id, _ := strconv.Atoi(params["id"]) vm := getVirtualMachine(db, id) r.HTML(200, "vm", vm) }) m.Post("/vm/delete/(?P<id>[0-9]+)", func(r render.Render, params martini.Params) { id, _ := strconv.Atoi(params["id"]) vm := getVirtualMachine(db, id) err := vm.Delete(db) defer vm.Free() if err != nil { reportError(r, err, "I can not delete the vm") } r.HTML(200, "vm", vm) }) m.Post("/rescan", func(req *http.Request) { if atomic.LoadInt32(&scanning) == 0 { go func() { atomic.StoreInt32(&scanning, 1) RescanIPAddress(db) atomic.StoreInt32(&scanning, 0) }() } }) m.Post("/vm/(?P<id>[0-9]+)", func(r render.Render, params martini.Params, req *http.Request) { req.ParseForm() submitType := req.PostFormValue("submit") id, _ := strconv.Atoi(params["id"]) vm := getVirtualMachine(db, id) var err error switch submitType { case "Start": err = vm.Start() vm.Free() case "Stop": err = vm.Stop() //TODO: wait a while vm.Free() case "ForceStop": err = vm.ForceStop() vm.Free() case "Update": owner := req.PostForm["Owner"][0] description := req.PostForm["Description"][0] err = vm.UpdateDatabase(db, owner, description) } if err != nil { //error page r.HTML(501, "error", err) log.Println(err) } else { //redirect page r.Redirect("/") } }) //API part m.Get("/api/list", func(r render.Render) { pm := getListofPhysicalMachineAndVirtualMachine(db) r.JSON(200, pm) }) m.Get("/api/vm/(?P<id>[0-9]+)", func(r render.Render, params martini.Params) { id, _ := strconv.Atoi(params["id"]) vm := getVirtualMachine(db, id) r.JSON(200, vm) }) vncProxy := websocket.Server{Handler: proxyHandler, Handshake: func(ws *websocket.Config, req *http.Request) error { ws.Protocol = []string{"base64"} return nil }} m.Get("/websockify", vncProxy.ServeHTTP) installState := websocket.Server{Handler: stateReportHandler} m.Get("/installsockify", installState.ServeHTTP) // rescan IP address every 6 hour go func() { for { time.Sleep(time.Hour * 6) if atomic.LoadInt32(&scanning) == 0 { log.Println("start planed rescan IP address") atomic.StoreInt32(&scanning, 1) RescanIPAddress(db) atomic.StoreInt32(&scanning, 0) } } }() //EventRunDefault //this must be before any connection libvirt.EventRegisterDefaultImpl() go func() { for { ret := libvirt.EventRunDefaultImpl() if ret == -1 { fmt.Println("RuN failed") break } } }() //start web server http.ListenAndServe(":3000", m) }