func main() { var ( hostPtr = flag.String("host", "", "remote host IP address") repoPtr = flag.String("repo", "", "installation repository") autoyastPtr = flag.String("autoyast", "", "location of autoyast xml") imageSizePtr = flag.Uint64("size", 10, "image size (G)") namePtr = flag.String("name", "", "name of the Virtual Machine") ) flag.Parse() var remoteURL string if *hostPtr == "" { remoteURL = "qemu+ssh:///system" } else { remoteURL = "qemu+ssh://root@" + *hostPtr + "/system" } if *repoPtr == "" { fmt.Println("MISSING repo") usage() return } repo := *repoPtr if *namePtr == "" { fmt.Println("MISSING name") usage() return } name := *namePtr if *autoyastPtr == "" { fmt.Println("You did not have autoyast.xml") } autoinst := *autoyastPtr // GB > Byte imageSize := *imageSizePtr << 30 fmt.Printf("Install From :%s \n", remoteURL) fmt.Printf("Name :%s \n", name) fmt.Printf("Disk Size :%dG\n", *imageSizePtr) fmt.Printf("Repository :%s \n", repo) fmt.Printf("AutoYast :%s \n", autoinst) startListen() // create remote pool fmt.Printf("Creating connection to %s\n", *hostPtr) conn, err := libvirt.NewVirConnection(remoteURL) if err != nil { fmt.Println(err) return } defer conn.CloseConnection() ch := make(chan string) go vminstall.VmInstall(conn, name, repo, autoinst, uint64(imageSize), ch) for m := range ch { if m == vminstall.VMINSTALL_SUCCESS { break } fmt.Println(m) } startVNCviewer(conn, name, *hostPtr) }
//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) }