// ProvisionRestoreJob creates a docker container to orchestrate a restore job func ProvisionRestoreJob(dbConn *sql.DB, args *TaskRequest) error { logit.Info.Println("task.ProvisionRestoreJob called") logit.Info.Println("with scheduleid=" + args.ScheduleID) logit.Info.Println("with containername=" + args.ContainerName) logit.Info.Println("with profilename=" + args.ProfileName) logit.Info.Println("with statusid=" + args.StatusID) restorecontainername := args.ContainerName + "-restore-job" //remove any existing container with the same name inspectReq := &swarmapi.DockerInspectRequest{} inspectReq.ContainerName = restorecontainername inspectResponse, err := swarmapi.DockerInspect(inspectReq) if err != nil { logit.Error.Println(err.Error()) return err } if inspectResponse.RunningState != "not-found" { rreq := &swarmapi.DockerRemoveRequest{} rreq.ContainerName = restorecontainername _, err = swarmapi.DockerRemove(rreq) if err != nil { logit.Error.Println(err.Error()) return err } } //create the new container params := &swarmapi.DockerRunRequest{} params.Image = "cpm-restore-job" params.ContainerName = restorecontainername params.Standalone = "false" params.Profile = "SM" schedule, err := GetSchedule(dbConn, args.ScheduleID) if err != nil { logit.Error.Println(err.Error()) return err } logit.Info.Println("schedule serverip is " + schedule.Serverip) var taskstatus TaskStatus taskstatus, err = GetStatus(dbConn, args.StatusID) if err != nil { logit.Error.Println(err.Error()) return err } //params.PGDataPath = server.PGDataPath + "/" + restorecontainername + "/" + getFormattedDate() //get the docker profile settings var setting types.Setting setting, err = admindb.GetSetting(dbConn, "S-DOCKER-PROFILE-CPU") params.CPU = setting.Value setting, err = admindb.GetSetting(dbConn, "S-DOCKER-PROFILE-MEM") params.MEM = setting.Value setting, err = admindb.GetSetting(dbConn, "PG-DATA-PATH") var datapath string datapath = setting.Value //this gets mounted under /pgdata and allows us to access //both the backup files and the restored containers files params.PGDataPath = datapath params.EnvVars = make(map[string]string) params.EnvVars["RestoreServerip"] = schedule.Serverip params.EnvVars["RestoreBackupPath"] = taskstatus.Path params.EnvVars["RestorePath"] = args.ContainerName params.EnvVars["RestoreContainerName"] = args.ContainerName params.EnvVars["RestoreScheduleID"] = args.ScheduleID params.EnvVars["RestoreProfileName"] = args.ProfileName params.EnvVars["RestoreStatusID"] = args.StatusID //run the container //params.CommandPath = "docker-run-restore.sh" var response swarmapi.DockerRunResponse //var url = "http://" + server.IPAddress + ":10001" response, err = swarmapi.DockerRun(params) if err != nil { logit.Error.Println(response.ID) return err } logit.Info.Println("docker run output=" + response.ID) return nil }
// 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) }
/* 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) }
func provisionImpl(dbConn *sql.DB, params *swarmapi.DockerRunRequest, standby bool) (string, error) { logit.Info.Println("PROFILE: provisionImpl starts 1") var errorStr string //make sure the container name is not already taken _, err := admindb.GetContainerByName(dbConn, params.ContainerName) if err != nil { if err != sql.ErrNoRows { return "", err } } else { errorStr = "container name " + params.ContainerName + " already used can't provision" logit.Error.Println(errorStr) return "", errors.New(errorStr) } //get the pg data path var pgdatapath types.Setting pgdatapath, err = admindb.GetSetting(dbConn, "PG-DATA-PATH") if err != nil { logit.Error.Println(err.Error()) return "", err } var infoResponse swarmapi.DockerInfoResponse infoResponse, err = swarmapi.DockerInfo() 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++ } //for database nodes, on the target server, we need to allocate //a disk volume on all CPM servers for the /pgdata container volume to work with //this causes a volume to be created with the directory //named the same as the container name params.PGDataPath = pgdatapath.Value + "/" + params.ContainerName logit.Info.Println("PROFILE provisionImpl 2 about to provision volume " + params.PGDataPath) if params.Image != "cpm-pgpool" { preq := &cpmserverapi.DiskProvisionRequest{} preq.Path = params.PGDataPath var response cpmserverapi.DiskProvisionResponse for _, each := range servers { logit.Info.Println("Provision: provisionvolume on server " + each.Name) response, err = cpmserverapi.DiskProvisionClient(each.Name, preq) if err != nil { logit.Info.Println("Provision: provisionvolume error" + err.Error()) logit.Error.Println(err.Error()) return "", err } logit.Info.Println("Provision: provisionvolume call response=" + response.Status) } } logit.Info.Println("PROFILE provisionImpl 3 provision volume completed") //run docker run to create the container params.CPU, params.MEM, err = getDockerResourceSettings(dbConn, params.Profile) if err != nil { logit.Error.Println(err.Error()) return "", err } //inspect and remove any existing container logit.Info.Println("PROFILE provisionImpl inspect 4") inspectReq := &swarmapi.DockerInspectRequest{} inspectReq.ContainerName = params.ContainerName var inspectResponse swarmapi.DockerInspectResponse inspectResponse, err = swarmapi.DockerInspect(inspectReq) if err != nil { logit.Error.Println(err.Error()) return "", err } if inspectResponse.RunningState != "not-found" { logit.Info.Println("PROFILE provisionImpl remove existing container 4a") rreq := &swarmapi.DockerRemoveRequest{} rreq.ContainerName = params.ContainerName _, err = swarmapi.DockerRemove(rreq) if err != nil { logit.Error.Println(err.Error()) return "", err } } //pass any restore env vars to the new container if params.RestoreJob != "" { if params.EnvVars == nil { //logit.Info.Println("making envvars map") params.EnvVars = make(map[string]string) } params.EnvVars["RestoreJob"] = params.RestoreJob params.EnvVars["RestoreRemotePath"] = params.RestoreRemotePath params.EnvVars["RestoreRemoteHost"] = params.RestoreRemoteHost params.EnvVars["RestoreRemoteUser"] = params.RestoreRemoteUser params.EnvVars["RestoreDbUser"] = params.RestoreDbUser params.EnvVars["RestoreDbPass"] = params.RestoreDbPass params.EnvVars["RestoreSet"] = params.RestoreSet } // runReq := swarmapi.DockerRunRequest{} runReq.PGDataPath = params.PGDataPath runReq.Profile = params.Profile runReq.Image = params.Image runReq.ContainerName = params.ContainerName runReq.EnvVars = params.EnvVars //logit.Info.Println("CPU=" + params.CPU) //logit.Info.Println("MEM=" + params.MEM) runReq.CPU = "0" runReq.MEM = "0" var runResp swarmapi.DockerRunResponse runResp, err = swarmapi.DockerRun(&runReq) if err != nil { logit.Error.Println(err.Error()) return "", err } logit.Info.Println("PROFILE provisionImpl created container 5 " + runResp.ID) dbnode := types.Container{} dbnode.ID = "" dbnode.Name = params.ContainerName dbnode.Image = params.Image dbnode.ClusterID = "-1" dbnode.ProjectID = params.ProjectID if params.Standalone == "true" { dbnode.Role = "standalone" } else { dbnode.Role = "unassigned" } var strid int strid, err = admindb.InsertContainer(dbConn, dbnode) newid := strconv.Itoa(strid) if err != nil { logit.Error.Println(err.Error()) return "", err } dbnode.ID = newid if params.Image != "cpm-node-proxy" { //register default db users on the new node err = createDBUsers(dbConn, dbnode) } return newid, err }