// DeleteRole delete a CPM role func DeleteRole(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-user") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } if r.PathParam("ID") == "" { logit.Error.Println("DeleteRole: error ID required") rest.Error(w, "ID required", http.StatusBadRequest) return } err = secimpl.DeleteRole(dbConn, r.PathParam("ID")) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// RulesDelete deletes a given rule func RulesDelete(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-read") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") if ID == "" { rest.Error(w, "ID required", http.StatusBadRequest) return } err = DeleteRule(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } status := types.SimpleStatus{} status.Status = "OK" w.WriteHeader(http.StatusOK) w.WriteJson(&status) }
// StartCluster starts all nodes in a cluster func StartCluster(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-cluster") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") if ID == "" { logit.Error.Println("StartCluster: error cluster ID required") rest.Error(w, "cluster ID required", http.StatusBadRequest) return } cluster, err := admindb.GetCluster(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) } //start docker containers containers, err := admindb.GetAllContainersForCluster(dbConn, cluster.ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) } i := 0 i = 0 var response swarmapi.DockerStartResponse for i = range containers { req := &swarmapi.DockerStartRequest{} req.ContainerName = containers[i].Name logit.Info.Println("will attempt to start container " + req.ContainerName) response, err = swarmapi.DockerStart(req) if err != nil { logit.Error.Println("StartCluster: error when trying to start container" + err.Error()) } logit.Info.Println("StartCluster: started " + response.Output) i++ } status := types.SimpleStatus{} status.Status = "OK" w.WriteHeader(http.StatusOK) w.WriteJson(&status) }
// Logout perform a logout based on a given token func Logout(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() token := r.PathParam("Token") if token == "" { logit.Error.Println("Logout: Token not supplied") rest.Error(w, "Token not supplied", http.StatusBadRequest) } err = secimpl.Logout(dbConn, token) if err != nil { logit.Error.Println("Logout: error secimpl call" + err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
func Status(w rest.ResponseWriter, r *rest.Request) { w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// ChangePassword change a user password func ChangePassword(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() //logit.Info.Println("ChangePassword: in ChangePassword") changePass := ChgPassword{} err = r.DecodeJsonPayload(&changePass) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } err = secimpl.Authorize(dbConn, changePass.Token, "perm-read") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } var sameUser bool sameUser, err = secimpl.CompareUserToToken(dbConn, changePass.Username, changePass.Token) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //enforce perm-user if the username is not the same as the token's //username (e.g. bob tries to change larry's password) if !sameUser { err = secimpl.Authorize(dbConn, changePass.Token, "perm-user") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } } err = secimpl.ChangePassword(dbConn, changePass.Username, changePass.Password) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// AdminStartNode starts a container func AdminStartNode(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-read") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") if ID == "" { logit.Error.Println("AdminStartNode: error ID required") rest.Error(w, "ID required", http.StatusBadRequest) return } node, err := admindb.GetContainer(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } /** server := types.Server{} server, err = admindb.GetServer(dbConn, node.ServerID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } */ var response swarmapi.DockerStartResponse request := &swarmapi.DockerStartRequest{} request.ContainerName = node.Name response, err = swarmapi.DockerStart(request) if err != nil { logit.Error.Println(err.Error()) logit.Error.Println(response.Output) } //logit.Info.Println(response.Output) w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// AdminStopServerContainers stops all containers on a given server func AdminStopServerContainers(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-read") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } //serverID serverid := r.PathParam("ID") if serverid == "" { logit.Error.Println("AdminStopoServerContainers: error ID required") rest.Error(w, "ID required", http.StatusBadRequest) return } cleanIP := strings.Replace(serverid, "_", ".", -1) containers, err := swarmapi.DockerPs(cleanIP) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //for each, get server, stop container for _, each := range containers.Output { if strings.HasPrefix(each.Status, "Up") { //stop container request := &swarmapi.DockerStopRequest{} request.ContainerName = each.Name logit.Info.Println("stopping " + request.ContainerName) _, err = swarmapi.DockerStop(request) if err != nil { logit.Error.Println("AdminStopServerContainers: error when trying to start container " + err.Error()) } } } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// AdminStoppg stops a postgres database on a given container func AdminStoppg(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-cluster") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } //logit.Info.Println("AdminStoppg:called") ID := r.PathParam("ID") if ID == "" { logit.Error.Println("AdminStoppg:ID not found error") rest.Error(w, "node ID required", http.StatusBadRequest) return } var dbNode types.Container dbNode, err = admindb.GetContainer(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //logit.Info.Println("AdminStoppg: in stop with dbnode") if dbNode.Role == "pgpool" { var stoppoolResp cpmcontainerapi.StopPgpoolResponse stoppoolResp, err = cpmcontainerapi.StopPgpoolClient(dbNode.Name) logit.Info.Println("AdminStoppg:" + stoppoolResp.Output) } else { var stoppgResp cpmcontainerapi.StopPGResponse stoppgResp, err = cpmcontainerapi.StopPGClient(dbNode.Name) logit.Info.Println("AdminStoppg:" + stoppgResp.Output) } if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// ProxyUpdate updates a proxy node definition func ProxyUpdate(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() req := ProxyRequest{} err = r.DecodeJsonPayload(&req) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } //logit.Info.Println("ID=" + req.ID) //logit.Info.Println("Port" + req.Port) //logit.Info.Println("Host" + req.Host) //logit.Info.Println("Database" + req.Database) //logit.Info.Println("Usename" + req.Usename) //logit.Info.Println("Passwd" + req.Passwd) //encrypt the password...passwords at rest are encrypted var encrypted string encrypted, err = sec.EncryptPassword(req.Passwd) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } queryStr := fmt.Sprintf("update proxy set ( port, host, usename, passwd, databasename, updatedt) = ( '%s', '%s', '%s', '%s', '%s', now()) where id = %s returning id", req.Port, req.Host, req.Usename, encrypted, req.Database, req.ID) logit.Info.Println("UpdateProxy:" + queryStr) var proxyid int err = dbConn.QueryRow(queryStr).Scan(&proxyid) switch { case err != nil: logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return default: logit.Info.Println("UpdateProxy: update " + strconv.Itoa(proxyid)) } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// RulesUpdate updates a given rule func RulesUpdate(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() //logit.Info.Println("RulesUpdate: in RulesUpdate") rule := Rule{} err = r.DecodeJsonPayload(&rule) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } err = secimpl.Authorize(dbConn, rule.Token, "perm-container") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } if rule.ID == "" { logit.Error.Println("RulesUpdate: error in ID") rest.Error(w, "rule ID required", http.StatusBadRequest) return } if rule.Name == "" { logit.Error.Println("RulesUpdate: error in Name") rest.Error(w, "rule name required", http.StatusBadRequest) return } err = UpdateRule(dbConn, rule) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } status := types.SimpleStatus{} status.Status = "OK" w.WriteHeader(http.StatusOK) w.WriteJson(&status) }
// DeleteSchedule deletes an existing task schedule func DeleteSchedule(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-backup") if err != nil { logit.Error.Println("validate token error " + err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") if ID == "" { rest.Error(w, "schedule ID required", 400) return } err = task.DeleteSchedule(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } //notify task server to reload schedules var output task.ReloadResponse output, err = task.ReloadClient() if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } logit.Info.Println("reload output=" + output.Output) w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// UpdateUser update a CPM user security settings func UpdateUser(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() //logit.Info.Println("UpdateUser: in UpdateUser") user := sec.User{} err = r.DecodeJsonPayload(&user) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } //logit.Info.Println("UpdateUser: Name=" + user.Name) //logit.Info.Println("UpdateUser: token=" + user.Token) err = secimpl.Authorize(dbConn, user.Token, "perm-user") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } err = secimpl.UpdateUser(dbConn, user) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// SaveSetting update an existing setting value func SaveSetting(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() //logit.Info.Println("SaveSetting:") setting := types.Setting{} err = r.DecodeJsonPayload(&setting) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } err = secimpl.Authorize(dbConn, setting.Token, "perm-setting") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } dbSetting := types.Setting{} dbSetting.Name = setting.Name dbSetting.Value = setting.Value err2 := admindb.UpdateSetting(dbConn, dbSetting) if err2 != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// AddRole create a new CPM role func AddRole(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() //logit.Info.Println("AddRole: in AddRole") role := sec.Role{} err = r.DecodeJsonPayload(&role) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } err = secimpl.Authorize(dbConn, role.Token, "perm-user") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } err = secimpl.AddRole(dbConn, role) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// TODO func ConfigureCluster(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-cluster") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") cluster, err := admindb.GetCluster(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } err = configureCluster("SM", dbConn, cluster, false) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
/* TODO refactor this to share code with DeleteCluster!!!!! */ func DeleteNode(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-container") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") if ID == "" { logit.Error.Println("DeleteNode: error node ID required") rest.Error(w, "node ID required", http.StatusBadRequest) return } //go get the node we intend to delete var dbNode types.Container dbNode, err = admindb.GetContainer(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var infoResponse swarmapi.DockerInfoResponse infoResponse, err = swarmapi.DockerInfo() if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } servers := make([]types.Server, len(infoResponse.Output)) i := 0 for i = range infoResponse.Output { servers[i].ID = infoResponse.Output[i] servers[i].Name = infoResponse.Output[i] servers[i].IPAddress = infoResponse.Output[i] i++ } var pgdatapath types.Setting pgdatapath, err = admindb.GetSetting(dbConn, "PG-DATA-PATH") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } err = admindb.DeleteContainer(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } logit.Info.Println("remove 1") //it is possible that someone can remove a container //outside of us, so we let it pass that we can't remove //it request := &swarmapi.DockerRemoveRequest{} request.ContainerName = dbNode.Name _, err = swarmapi.DockerRemove(request) if err != nil { logit.Error.Println(err.Error()) } logit.Info.Println("remove 2") //send the server a deletevolume command request2 := &cpmserverapi.DiskDeleteRequest{} request2.Path = pgdatapath.Value + "/" + dbNode.Name for _, each := range servers { _, err = cpmserverapi.DiskDeleteClient(each.Name, request2) if err != nil { logit.Error.Println(err.Error()) } } logit.Info.Println("remove 3") //we should not have to delete the DNS entries because //of the dnsbridge, it should remove them when we remove //the containers via the docker api w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// AutoCluster creates a new cluster func AutoCluster(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() logit.Info.Println("AUTO CLUSTER PROFILE starts") params := AutoClusterInfo{} err = r.DecodeJsonPayload(¶ms) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } err = secimpl.Authorize(dbConn, params.Token, "perm-cluster") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } if params.Name == "" { logit.Error.Println("AutoCluster: error in Name") rest.Error(w, "cluster name required", http.StatusBadRequest) return } if params.ClusterType == "" { logit.Error.Println("AutoCluster: error in ClusterType") rest.Error(w, "ClusterType name required", http.StatusBadRequest) return } if params.ProjectID == "" { logit.Error.Println("AutoCluster: error in ProjectID") rest.Error(w, "ProjectID name required", http.StatusBadRequest) return } if params.ClusterProfile == "" { logit.Error.Println("AutoCluster: error in ClusterProfile") rest.Error(w, "ClusterProfile name required", http.StatusBadRequest) return } logit.Info.Println("AutoCluster: Name=" + params.Name + " ClusterType=" + params.ClusterType + " Profile=" + params.ClusterProfile + " ProjectID=" + params.ProjectID) //create cluster definition dbcluster := types.Cluster{} dbcluster.ID = "" dbcluster.ProjectID = params.ProjectID dbcluster.Name = util.CleanName(params.Name) dbcluster.ClusterType = params.ClusterType dbcluster.Status = "uninitialized" dbcluster.Containers = make(map[string]string) var ival int ival, err = admindb.InsertCluster(dbConn, dbcluster) clusterID := strconv.Itoa(ival) dbcluster.ID = clusterID //logit.Info.Println(clusterID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, "Insert Cluster error:"+err.Error(), http.StatusBadRequest) return } //lookup profile profile, err2 := getClusterProfileInfo(dbConn, params.ClusterProfile) if err2 != nil { logit.Error.Println(err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } //var masterServer types.Server //var chosenServers []types.Server if profile.Algo == "round-robin" { //masterServer, chosenServers, err2 = roundRobin(dbConn, profile) } else { logit.Error.Println("AutoCluster: error-unsupported algorithm request") rest.Error(w, "AutoCluster error: unsupported algorithm", http.StatusBadRequest) return } //create master container dockermaster := swarmapi.DockerRunRequest{} dockermaster.Image = "cpm-node" dockermaster.ContainerName = params.Name + "-master" dockermaster.ProjectID = params.ProjectID dockermaster.Standalone = "false" dockermaster.Profile = profile.MasterProfile if err != nil { logit.Error.Println("AutoCluster: error-create master node " + err.Error()) rest.Error(w, "AutoCluster error"+err.Error(), http.StatusBadRequest) return } // provision the master logit.Info.Println("dockermaster profile is " + dockermaster.Profile) _, err2 = provisionImpl(dbConn, &dockermaster, false) if err2 != nil { logit.Error.Println("AutoCluster: error-provision master " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } logit.Info.Println("AUTO CLUSTER PROFILE master container created") var node types.Container //update node with cluster iD node, err2 = admindb.GetContainerByName(dbConn, dockermaster.ContainerName) if err2 != nil { logit.Error.Println("AutoCluster: error-get node by name " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } node.ClusterID = clusterID node.Role = "master" err2 = admindb.UpdateContainer(dbConn, node) if err2 != nil { logit.Error.Println("AutoCluster: error-update standby node " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } var sleepSetting types.Setting sleepSetting, err2 = admindb.GetSetting(dbConn, "SLEEP-PROV") if err2 != nil { logit.Error.Println("SLEEP-PROV setting error " + err2.Error()) rest.Error(w, err2.Error(), http.StatusInternalServerError) return } var sleepTime time.Duration sleepTime, err2 = time.ParseDuration(sleepSetting.Value) if err2 != nil { logit.Error.Println(err2.Error()) rest.Error(w, err2.Error(), http.StatusInternalServerError) return } //create standby containers var count int count, err2 = strconv.Atoi(profile.Count) if err2 != nil { logit.Error.Println(err2.Error()) rest.Error(w, err2.Error(), http.StatusBadRequest) return } dockerstandby := make([]swarmapi.DockerRunRequest, count) for i := 0; i < count; i++ { logit.Info.Println("working on standby ....") // loop - provision standby dockerstandby[i].ProjectID = params.ProjectID dockerstandby[i].Image = "cpm-node" dockerstandby[i].ContainerName = params.Name + "-" + STANDBY + "-" + strconv.Itoa(i) dockerstandby[i].Standalone = "false" dockerstandby[i].Profile = profile.StandbyProfile _, err2 = provisionImpl(dbConn, &dockerstandby[i], true) if err2 != nil { logit.Error.Println("AutoCluster: error-provision master " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } //update node with cluster iD node, err2 = admindb.GetContainerByName(dbConn, dockerstandby[i].ContainerName) if err2 != nil { logit.Error.Println("AutoCluster: error-get node by name " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } node.ClusterID = clusterID node.Role = STANDBY err2 = admindb.UpdateContainer(dbConn, node) if err2 != nil { logit.Error.Println("AutoCluster: error-update standby node " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } } logit.Info.Println("AUTO CLUSTER PROFILE standbys created") //create pgpool container // provision dockerpgpool := swarmapi.DockerRunRequest{} dockerpgpool.ContainerName = params.Name + "-pgpool" dockerpgpool.Image = "cpm-pgpool" dockerpgpool.ProjectID = params.ProjectID dockerpgpool.Standalone = "false" dockerpgpool.Profile = profile.StandbyProfile _, err2 = provisionImpl(dbConn, &dockerpgpool, true) if err2 != nil { logit.Error.Println("AutoCluster: error-provision pgpool " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } logit.Info.Println("AUTO CLUSTER PROFILE pgpool created") //update node with cluster ID node, err2 = admindb.GetContainerByName(dbConn, dockerpgpool.ContainerName) if err2 != nil { logit.Error.Println("AutoCluster: error-get pgpool node by name " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } node.ClusterID = clusterID node.Role = "pgpool" err2 = admindb.UpdateContainer(dbConn, node) if err2 != nil { logit.Error.Println("AutoCluster: error-update pgpool node " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } //init the master DB // provision the master dockermaster.Profile = profile.MasterProfile err2 = provisionImplInit(dbConn, &dockermaster, false) if err2 != nil { logit.Error.Println("AutoCluster: error-provisionInit master " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } //make sure every node is ready err2 = waitTillAllReady(dockermaster, dockerpgpool, dockerstandby, sleepTime) if err2 != nil { logit.Error.Println("cluster members not responding in time") rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } //configure cluster // ConfigureCluster logit.Info.Println("AUTO CLUSTER PROFILE configure cluster ") err2 = configureCluster(profile.MasterProfile, dbConn, dbcluster, true) if err2 != nil { logit.Error.Println("AutoCluster: error-configure cluster " + err2.Error()) rest.Error(w, "AutoCluster error"+err2.Error(), http.StatusBadRequest) return } logit.Info.Println("AUTO CLUSTER PROFILE done") w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// TODO func EventJoinCluster(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-cluster") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } IDList := r.PathParam("IDList") if IDList == "" { logit.Error.Println("IDList required") rest.Error(w, "IDList required", http.StatusBadRequest) return } else { logit.Info.Println("EventJoinCluster: IDList=[" + IDList + "]") } MasterID := r.PathParam("MasterID") if MasterID == "" { logit.Error.Println("MasterID required") rest.Error(w, "MasterID required", http.StatusBadRequest) return } else { logit.Info.Println("EventJoinCluster: MasterID=[" + MasterID + "]") } ClusterID := r.PathParam("ClusterID") if ClusterID == "" { logit.Error.Println("ClusterID required") rest.Error(w, "node ClusterID required", http.StatusBadRequest) return } else { logit.Info.Println("EventJoinCluster: ClusterID=[" + ClusterID + "]") } var idList = strings.Split(IDList, "_") i := 0 pgpoolCount := 0 origDBNode := types.Container{} for i = range idList { if idList[i] != "" { logit.Info.Println("EventJoinCluster: idList[" + strconv.Itoa(i) + "]=" + idList[i]) origDBNode, err = admindb.GetContainer(dbConn, idList[i]) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //update the node to be in the cluster origDBNode.ClusterID = ClusterID if origDBNode.Image == "cpm-node" { origDBNode.Role = STANDBY } else { origDBNode.Role = "pgpool" pgpoolCount++ } if pgpoolCount > 1 { logit.Error.Println("EventJoinCluster: more than 1 pgpool is in the cluster") rest.Error(w, "only 1 pgpool is allowed in a cluster", http.StatusBadRequest) return } err = admindb.UpdateContainer(dbConn, origDBNode) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } } i++ } //we use the -1 value to indicate that we are only adding //to an existing cluster, the UI doesn't know who the master //is at this point if MasterID != "-1" { //update the master node origDBNode, err = admindb.GetContainer(dbConn, MasterID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } origDBNode.ClusterID = ClusterID origDBNode.Role = "master" err = admindb.UpdateContainer(dbConn, origDBNode) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// AdminFailover causes a cluster failorver to be performed for a given cluster func AdminFailover(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-cluster") if err != nil { logit.Error.Println("authorize error " + err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") if ID == "" { logit.Error.Println("node ID required error") rest.Error(w, "node ID required", http.StatusBadRequest) return } //dbNode is the standby node we are going to fail over and //make the new master in the cluster var dbNode types.Container dbNode, err = admindb.GetContainer(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } cluster, err := admindb.GetCluster(dbConn, dbNode.ClusterID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var failoverResp cpmcontainerapi.FailoverResponse failoverResp, err = cpmcontainerapi.FailoverClient(dbNode.Name) if err != nil { logit.Error.Println("fail-over error " + err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } logit.Info.Println("AdminFailover: fail-over output " + failoverResp.Output) //update the old master to standalone role oldMaster := types.Container{} oldMaster, err = admindb.GetContainerMaster(dbConn, dbNode.ClusterID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } oldMaster.Role = "standalone" oldMaster.ClusterID = "-1" err = admindb.UpdateContainer(dbConn, oldMaster) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //update the failover node to master role dbNode.Role = "master" err = admindb.UpdateContainer(dbConn, dbNode) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //stop pg on the old master //params.IPAddress1 = oldMaster.IPAddress var stopPGResp cpmcontainerapi.StopPGResponse stopPGResp, err = cpmcontainerapi.StopPGClient(oldMaster.Name) if err != nil { logit.Error.Println(err.Error() + stopPGResp.Output) rest.Error(w, err.Error(), http.StatusBadRequest) return } err = configureCluster("SM", dbConn, cluster, false) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) return }
// DeleteCluster deletes an existing cluster definition func DeleteCluster(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-cluster") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") if ID == "" { logit.Error.Println("cluster ID required") rest.Error(w, "cluster ID required", http.StatusBadRequest) return } cluster, err := admindb.GetCluster(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) } //delete docker containers containers, err := admindb.GetAllContainersForCluster(dbConn, cluster.ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) } var infoResponse swarmapi.DockerInfoResponse infoResponse, err = swarmapi.DockerInfo() if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } i := 0 servers := make([]types.Server, len(infoResponse.Output)) for i = range infoResponse.Output { servers[i].ID = infoResponse.Output[i] servers[i].Name = infoResponse.Output[i] servers[i].IPAddress = infoResponse.Output[i] i++ } var pgdatapath types.Setting pgdatapath, err = admindb.GetSetting(dbConn, "PG-DATA-PATH") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } i = 0 //server := types.Server{} for i = range containers { //logit.Info.Println("DeleteCluster: got server IP " + server.IPAddress) //it is possible that someone can remove a container //outside of us, so we let it pass that we can't remove //it //err = removeContainer(server.IPAddress, containers[i].Name) dremreq := &swarmapi.DockerRemoveRequest{} dremreq.ContainerName = containers[i].Name //logit.Info.Println("will attempt to delete container " + dremreq.ContainerName) _, err = swarmapi.DockerRemove(dremreq) if err != nil { logit.Error.Println("error when trying to remove container" + err.Error()) } //send all the servers a deletevolume command ddreq := &cpmserverapi.DiskDeleteRequest{} ddreq.Path = pgdatapath.Value + "/" + containers[i].Name for _, each := range servers { _, err = cpmserverapi.DiskDeleteClient(each.Name, ddreq) if err != nil { logit.Error.Println("error when trying to remove disk volume" + err.Error()) } } i++ } //delete the container entries //delete the cluster entry admindb.DeleteCluster(dbConn, ID) for i = range containers { err = admindb.DeleteContainer(dbConn, containers[i].ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } } status := types.SimpleStatus{} status.Status = "OK" w.WriteHeader(http.StatusOK) w.WriteJson(&status) }
// UpdateContainerUser updates a database users preferences on a given container db func UpdateContainerUser(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() postMsg := types.NodeUser{} err = r.DecodeJsonPayload(&postMsg) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } err = secimpl.Authorize(dbConn, postMsg.Token, "perm-user") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } if postMsg.ID == "" { logit.Error.Println("UpdateContainerUser: error node ID required") rest.Error(w, "ID required", 400) return } if postMsg.Rolname == "" { logit.Error.Println("UpdateContainerUser: error node Rolname required") rest.Error(w, "Rolname required", 400) return } //create user on the container //get container info var node types.Container node, err = admindb.GetContainer(dbConn, postMsg.ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } if postMsg.Passwd == "" { } else { //update the password } var credential types.Credential credential, err = admindb.GetUserCredentials(dbConn, &node) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var dbConn2 *sql.DB dbConn2, err = util.GetMonitoringConnection(credential.Host, credential.Username, credential.Port, credential.Database, credential.Password) defer dbConn2.Close() var SUPERUSER = "******" var INHERIT = "INHERIT" var CREATEROLE = "CREATEROLE" var CREATEDB = "CREATEDB" var LOGIN = "******" var REPLICATION = "REPLICATION" logit.Info.Println("Rolsuper is " + strconv.FormatBool(postMsg.Rolsuper)) if !postMsg.Rolsuper { SUPERUSER = "******" } if !postMsg.Rolinherit { INHERIT = "NOINHERIT" } if !postMsg.Rolcreaterole { CREATEROLE = "NOCREATEROLE" } if !postMsg.Rolcreatedb { CREATEDB = "NOCREATEDB" } if !postMsg.Rollogin { LOGIN = "******" } if !postMsg.Rolreplication { REPLICATION = "NOREPLICATION" } query := "alter user " + postMsg.Rolname + " " + SUPERUSER + " " + INHERIT + " " + CREATEROLE + " " + CREATEDB + " " + LOGIN + " " + REPLICATION + " " if postMsg.Passwd != "" { query = query + " PASSWORD '" + postMsg.Passwd + "'" } logit.Info.Println(query) _, err = dbConn2.Query(query) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var userexists = true _, err = admindb.GetContainerUser(dbConn, node.Name, postMsg.Rolname) if err == sql.ErrNoRows { // Handle no rows userexists = false } else if err != nil { // Handle actual error logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } if postMsg.Passwd != "" { //update user's password dbuser := types.ContainerUser{} dbuser.Containername = node.Name dbuser.Passwd = postMsg.Passwd dbuser.Rolname = postMsg.Rolname if userexists { err = admindb.UpdateContainerUser(dbConn, dbuser) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } } } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// UpdateSchedule updates a given task schedule func UpdateSchedule(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() postMsg := AddSchedulePost{} err = r.DecodeJsonPayload(&postMsg) if err != nil { logit.Error.Println("decode" + err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } err = secimpl.Authorize(dbConn, postMsg.Token, "perm-backup") if err != nil { logit.Error.Println("validate token error " + err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } if postMsg.ID == "" { logit.Error.Println("schedule ID required") rest.Error(w, "schedule ID required", 400) return } if postMsg.Enabled == "" { logit.Error.Println("Enabled required") rest.Error(w, "Enabled required", 400) return } if postMsg.Minutes == "" { logit.Error.Println("Minutes required") rest.Error(w, "schedule Minutes required", 400) return } if postMsg.Hours == "" { logit.Error.Println("Hours required") rest.Error(w, "schedule Hours required", 400) return } if postMsg.DayOfMonth == "" { logit.Error.Println("DayOfMonth required") rest.Error(w, "schedule DayOfMonth required", 400) return } if postMsg.Month == "" { logit.Error.Println("Month required") rest.Error(w, "schedule Month required", 400) return } if postMsg.DayOfWeek == "" { logit.Error.Println("DayOfWeek required") rest.Error(w, "schedule DayOfWeek required", 400) return } if postMsg.Name == "" { logit.Error.Println("Name required") rest.Error(w, "schedule Name required", 400) return } s := task.TaskSchedule{} s.ID = postMsg.ID s.Minutes = postMsg.Minutes s.Hours = postMsg.Hours s.Enabled = postMsg.Enabled s.DayOfMonth = postMsg.DayOfMonth s.Month = postMsg.Month s.DayOfWeek = postMsg.DayOfWeek s.Name = postMsg.Name s.RestoreSet = postMsg.RestoreSet s.RestoreRemotePath = postMsg.RestoreRemotePath s.RestoreRemoteHost = postMsg.RestoreRemoteHost s.RestoreRemoteUser = postMsg.RestoreRemoteUser s.RestoreDbUser = postMsg.RestoreDbUser s.RestoreDbPass = postMsg.RestoreDbPass s.Serverip = postMsg.Serverip err = task.UpdateSchedule(dbConn, s) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } //notify task server to reload it's schedules output, err := task.ReloadClient() if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } logit.Info.Println("reload output=" + output.Output) w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// AddContainerUser creates a new database user for a given container func AddContainerUser(w rest.ResponseWriter, r *rest.Request) { postMsg := types.NodeUser{} err := r.DecodeJsonPayload(&postMsg) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } var dbConn *sql.DB dbConn, err = util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, postMsg.Token, "perm-user") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } if postMsg.ID == "" { logit.Error.Println("AddContainerUser: error node ID required") rest.Error(w, "ID required", 400) return } if postMsg.Rolname == "" { logit.Error.Println("AddContainerUser: error node Rolname required") rest.Error(w, "Rolname required", 400) return } if postMsg.Passwd == "" { logit.Error.Println("AddContainerUser: error node Passwd required") rest.Error(w, "Passwd required", 400) return } //create user on the container //get container info node, err := admindb.GetContainer(dbConn, postMsg.ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var credential types.Credential credential, err = admindb.GetUserCredentials(dbConn, &node) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var dbConn2 *sql.DB dbConn2, err = util.GetMonitoringConnection(credential.Host, credential.Username, credential.Port, credential.Database, credential.Password) defer dbConn2.Close() var SUPERUSER = "" var INHERIT = "" var CREATEROLE = "" var CREATEDB = "" var LOGIN = "" var REPLICATION = "" //logit.Info.Println("Rolsuper is " + strconv.FormatBool(postMsg.Rolsuper)) if postMsg.Rolsuper { SUPERUSER = "******" } if postMsg.Rolinherit { INHERIT = "INHERIT" } if postMsg.Rolcreaterole { CREATEROLE = "CREATEROLE" } if postMsg.Rolcreatedb { CREATEDB = "CREATEDB" } if postMsg.Rollogin { LOGIN = "******" } if postMsg.Rolreplication { REPLICATION = "REPLICATION" } query := "create user " + postMsg.Rolname + " " + SUPERUSER + " " + INHERIT + " " + CREATEROLE + " " + CREATEDB + " " + LOGIN + " " + REPLICATION + " " + "PASSWORD '" + postMsg.Passwd + "'" logit.Info.Println(query) _, err = dbConn2.Query(query) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //create user in the admin db dbuser := types.ContainerUser{} dbuser.Containername = node.Name dbuser.Passwd = postMsg.Passwd dbuser.Rolname = postMsg.Rolname result, err := admindb.AddContainerUser(dbConn, dbuser) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } logit.Info.Printf("AddContainerUser: new ID %d\n", result) w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// DeleteContainerUser deletes a database user on a given container func DeleteContainerUser(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-backup") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ContainerID := r.PathParam("ContainerID") if ContainerID == "" { rest.Error(w, "ContainerID required", 400) return } rolname := r.PathParam("Rolname") if rolname == "" { rest.Error(w, "Rolname required", 400) return } //get node info node, err := admindb.GetContainer(dbConn, ContainerID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var userexists = true _, err = admindb.GetContainerUser(dbConn, node.Name, rolname) if err == sql.ErrNoRows { // Handle no rows userexists = false } else if err != nil { // Handle actual error logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } //only delete if there is a container user if userexists { err = admindb.DeleteContainerUser(dbConn, node.Name, rolname) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } } var credential types.Credential credential, err = admindb.GetUserCredentials(dbConn, &node) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var dbConn2 *sql.DB dbConn2, err = util.GetMonitoringConnection(credential.Host, credential.Username, credential.Port, credential.Database, credential.Password) defer dbConn2.Close() query := "drop role " + rolname logit.Info.Println(query) _, err = dbConn2.Query(query) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// ExecuteNow executes a task schedule on demand allowing an immediate task execution func ExecuteNow(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() postMsg := BackupNowPost{} err = r.DecodeJsonPayload(&postMsg) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } err = secimpl.Authorize(dbConn, postMsg.Token, "perm-backup") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } if postMsg.ProfileName == "" { logit.Error.Println("node ProfileName required") rest.Error(w, "ProfileName required", 400) return } if postMsg.ScheduleID == "" { logit.Error.Println("schedule ID required") rest.Error(w, "schedule ID required", 400) return } schedule, err2 := task.GetSchedule(dbConn, postMsg.ScheduleID) if err2 != nil { logit.Error.Println(err2.Error()) rest.Error(w, err2.Error(), 400) return } request := task.TaskRequest{} request.ScheduleID = postMsg.ScheduleID //in the case of a restore job, the user can supply a new containername if postMsg.ContainerName == "" { request.ContainerName = schedule.ContainerName } else { request.ContainerName = postMsg.ContainerName } //the restore command requires the task schedule statusID request.StatusID = postMsg.StatusID request.ProfileName = postMsg.ProfileName //for restore jobs, we go ahead and create the new //database container here, could possible move to the //restore job task later on if postMsg.ProfileName == "restore" { var newid string provisionParams := swarmapi.DockerRunRequest{} provisionParams.Profile = "SM" provisionParams.ProjectID = postMsg.ProjectID provisionParams.ContainerName = postMsg.ContainerName provisionParams.Image = "cpm-node" provisionParams.IPAddress = schedule.Serverip //logit.Info.Println("before restore provision with...") //logit.Info.Println("profile=" + provisionParams.Profile) //logit.Info.Println("projectid=" + provisionParams.ProjectID) //logit.Info.Println("containername=" + provisionParams.ContainerName) //logit.Info.Println("image=" + provisionParams.Image) //logit.Info.Println("ipaddress=" + provisionParams.IPAddress) newid, err = provisionImpl(dbConn, &provisionParams, false) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } logit.Info.Printf("created node for restore job id = " + newid) } output, err := task.ExecuteNowClient(&request) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } logit.Info.Println("output=" + output.Output) w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// AdminStartServerContainers starts all containers on a given server func AdminStartServerContainers(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-read") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } //serverID serverid := r.PathParam("ID") if serverid == "" { logit.Error.Println(" error ID required") rest.Error(w, "ID required", http.StatusBadRequest) return } cleanIP := strings.Replace(serverid, "_", ".", -1) containers, err := swarmapi.DockerPs(cleanIP) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //for each, get server, start container //use a 'best effort' approach here since containers //can be removed outside of CPM's control for _, each := range containers.Output { //start the container var response swarmapi.DockerStartResponse var err error request := &swarmapi.DockerStartRequest{} logit.Info.Println("trying to start " + each.Name) request.ContainerName = each.Name response, err = swarmapi.DockerStart(request) if err != nil { logit.Error.Println("AdminStartServerContainers: error when trying to start container " + err.Error()) logit.Error.Println(response.Output) } //logit.Info.Println(response.Output) } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// ScaleUpCluster increases the count of standby containers in a cluster func ScaleUpCluster(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-read") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } ID := r.PathParam("ID") cluster, err := admindb.GetCluster(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } var containers []types.Container containers, err = admindb.GetAllContainersForCluster(dbConn, ID) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //determine number of standby nodes currently standbyCnt := 0 for i := range containers { if containers[i].Role == STANDBY { standbyCnt++ } } //logit.Info.Printf("standbyCnt ends at %d\n", standbyCnt) //provision new container params := new(swarmapi.DockerRunRequest) params.Image = "cpm-node" //TODO make the server choice smart params.ProjectID = cluster.ProjectID params.ContainerName = cluster.Name + "-" + STANDBY + "-" + fmt.Sprintf("%d", standbyCnt) params.Standalone = "false" var standby = true params.Profile = "LG" //logit.Info.Printf("here with ProjectID %s\n", cluster.ProjectID) _, err = provisionImpl(dbConn, params, standby) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } err = provisionImplInit(dbConn, params, false) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } //need to update the new container's ClusterID var node types.Container node, err = admindb.GetContainerByName(dbConn, params.ContainerName) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, "error"+err.Error(), http.StatusBadRequest) return } node.ClusterID = cluster.ID node.Role = STANDBY err = admindb.UpdateContainer(dbConn, node) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, "error"+err.Error(), http.StatusBadRequest) return } err = configureCluster(params.Profile, dbConn, cluster, false) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// ProvisionProxy creates a Docker image for a proxy node definition func ProvisionProxy(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() proxyrequest := ProxyRequest{} err = r.DecodeJsonPayload(&proxyrequest) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } logit.Info.Println("ProvisionProxy: Token=[" + proxyrequest.Token + "]") err = secimpl.Authorize(dbConn, proxyrequest.Token, "perm-container") if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } errorStr := "" if proxyrequest.ProjectID == "" { logit.Error.Println("ProvisionProxy error ProjectID required") errorStr = "ProjectID required" rest.Error(w, errorStr, http.StatusBadRequest) return } if proxyrequest.ContainerName == "" { logit.Error.Println("ProvisionProxy error containername required") errorStr = "ContainerName required" rest.Error(w, errorStr, http.StatusBadRequest) return } if proxyrequest.Image == "" { logit.Error.Println("ProvisionProxy error image required") errorStr = "Image required" rest.Error(w, errorStr, http.StatusBadRequest) return } if proxyrequest.Host == "" { logit.Error.Println("ProvisionProxy error DatabaseHost required") errorStr = "DatabaseHost required" rest.Error(w, errorStr, http.StatusBadRequest) return } if proxyrequest.Host == "127.0.0.1" || proxyrequest.Host == "localhost" { logit.Error.Println("ProvisionProxy error DatabaseHost can not be localhost") errorStr = "DatabaseHost can not be localhost" rest.Error(w, errorStr, http.StatusBadRequest) return } if proxyrequest.Database == "" { logit.Error.Println("ProvisionProxy error Database required") errorStr = "Database required" rest.Error(w, errorStr, http.StatusBadRequest) return } if proxyrequest.Usename == "" { logit.Error.Println("ProvisionProxy error Usename required") errorStr = "Usename required" rest.Error(w, errorStr, http.StatusBadRequest) return } if proxyrequest.Passwd == "" { logit.Error.Println("ProvisionProxy error Passwd required") errorStr = "Passwd required" rest.Error(w, errorStr, http.StatusBadRequest) return } //logit.Info.Println("Image=" + proxyrequest.Image) //logit.Info.Println("Profile=" + proxyrequest.Profile) //logit.Info.Println("ProjectID=" + proxyrequest.ProjectID) //logit.Info.Println("ContainerName=" + proxyrequest.ContainerName) //logit.Info.Println("Standalone=" + proxyrequest.Standalone) params := &swarmapi.DockerRunRequest{} params.Image = proxyrequest.Image params.ProjectID = proxyrequest.ProjectID params.ContainerName = util.CleanName(proxyrequest.ContainerName) params.Standalone = proxyrequest.Standalone params.Profile = proxyrequest.Profile _, err = provisionImpl(dbConn, params, false) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } err = insertProxy(&proxyrequest) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) status := types.SimpleStatus{} status.Status = "OK" w.WriteJson(&status) }
// ContainerAccessRuleUpdate updates the rules assigned to a container func ContainerAccessRuleUpdate(w rest.ResponseWriter, r *rest.Request) { dbConn, err := util.GetConnection(CLUSTERADMIN_DB) if err != nil { logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } defer dbConn.Close() logit.Info.Println("ContainerAccessRuleInsert") cars := make([]ContainerAccessRule, 0) err = r.DecodeJsonPayload(&cars) if err != nil { logit.Error.Println("ContainerAccessRuleInsert: error in decode" + err.Error()) rest.Error(w, err.Error(), http.StatusInternalServerError) return } if len(cars) > 0 { err = secimpl.Authorize(dbConn, cars[0].Token, "perm-container") if err != nil { logit.Error.Println("ContainerAccessRuleInsert: authorize error " + err.Error()) rest.Error(w, err.Error(), http.StatusUnauthorized) return } } var updatesRequired = false var ContainerID string for i := range cars { if cars[i].Selected == "true" { if cars[i].ID != "-1" { //do nothing logit.Info.Println("doing nothing on " + cars[i].ContainerID + " " + cars[i].AccessRuleID + " " + cars[i].AccessRuleName) } else { //insert updatesRequired = true ContainerID = cars[i].ContainerID logit.Info.Println("doing insert on " + cars[i].ContainerID + " " + cars[i].AccessRuleID + " " + cars[i].AccessRuleName) err = InsertContainerAccessRule(dbConn, cars[i]) if err != nil { logit.Error.Println("error doing insert on " + cars[i].ContainerID + " " + cars[i].AccessRuleID + " " + cars[i].AccessRuleName) logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } } } else { if cars[i].ID != "-1" { updatesRequired = true ContainerID = cars[i].ContainerID //delete logit.Info.Println("doing delete on " + cars[i].ContainerID + " " + cars[i].AccessRuleID + " " + cars[i].AccessRuleName) err = DeleteContainerAccessRule(dbConn, cars[i].ID) if err != nil { logit.Error.Println("error doing delete on " + cars[i].ContainerID + " " + cars[i].AccessRuleID + " " + cars[i].AccessRuleName) logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } } } } if updatesRequired { err = performConfigUpdate(dbConn, ContainerID) if err != nil { logit.Error.Println("error on config update ContainerID=" + ContainerID) logit.Error.Println(err.Error()) rest.Error(w, err.Error(), 400) return } } status := types.SimpleStatus{} status.Status = "OK" w.WriteHeader(http.StatusOK) w.WriteJson(&status) }