func GetUser(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetUser: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ID := r.PathParam("ID")
	if ID == "" {
		logit.Error.Println("GetUser: error User ID required")
		rest.Error(w, "User ID required", http.StatusBadRequest)
		return
	}

	status := SimpleStatus{}
	status.Status = "OK"
	w.WriteHeader(http.StatusOK)
	w.WriteJson(&status)
}
func GetHealthCheck(w rest.ResponseWriter, r *rest.Request) {

	dbConn, err := util.GetConnection("clusteradmin")
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	defer dbConn.Close()

	err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-read")
	if err != nil {
		logit.Error.Println("validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	var results []collect.HealthCheck

	results, err = collect.GetHealthCheck(dbConn)
	if err != nil {
		logit.Error.Println(err.Error())
		w.WriteJson(&results)
		return
	}

	w.WriteJson(&results)

}
func GetServer(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetServer: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	ID := r.PathParam("ID")
	logit.Info.Println("in GetServer with ID=" + ID)

	results, err := admindb.GetServer(dbConn, ID)
	if err != nil {
		logit.Error.Println("GetServer:" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	server := Server{results.ID, results.Name, results.IPAddress,
		results.DockerBridgeIP, results.PGDataPath, results.ServerClass, results.CreateDate}
	logit.Info.Println("GetServer: results=" + results.ID)

	w.WriteJson(&server)
}
func RulesGetAll(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("RulesGetAll: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	rules, err := GetAllRules(dbConn)
	if err != nil {
		logit.Error.Println("RulesGetAll:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&rules)
}
func Login(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		rest.Error(w, err.Error(), 400)
		return

	}
	defer dbConn.Close()
	ID := r.PathParam("ID")
	PSW := r.PathParam("PSW")
	if ID == "" || PSW == "" {
		logit.Error.Println("Login: ID or PSW not supplied")
		rest.Error(w, "ID or PSW not supplied", http.StatusBadRequest)
	}

	logit.Info.Println("Login: called")

	tokenContents, err := secimpl.Login(dbConn, ID, PSW)
	if err != nil {
		logit.Error.Println("Login: error secimpl call" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	//w.WriteHeader(http.StatusOK)
	token := LoginToken{tokenContents}
	logit.Info.Println("sending back token " + token.Contents)
	w.WriteJson(&token)
}
func GetAllUsers(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetAllUsers: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	usersList, err := secimpl.GetAllUsers(dbConn)
	if err != nil {
		logit.Error.Println("GetAllUsers: error " + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	for i := range usersList {
		logit.Info.Println("GetAllUsers: secimpl.GetAllUsers userName=" + usersList[i].Name)
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&usersList)
}
func DeleteServer(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		rest.Error(w, err.Error(), 400)
		return

	}
	defer dbConn.Close()

	err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-server")
	if err != nil {
		logit.Error.Println("DeleteServer: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ID := r.PathParam("ID")
	if ID == "" {
		logit.Error.Println("DeleteServer: error server id required")
		rest.Error(w, "Server ID required", http.StatusBadRequest)
		return
	}

	err = admindb.DeleteServer(dbConn, ID)
	if err != nil {
		logit.Error.Println("DeleteServer: " + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
	}

	w.WriteHeader(http.StatusOK)
}
func DeleteRole(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetAllRoles: validate token error " + 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("DeleteRole: error secimpl call" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	status := SimpleStatus{}
	status.Status = "OK"
	w.WriteJson(&status)
}
func GetSchedule(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetSchedule: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	ID := r.PathParam("ID")

	if ID == "" {
		rest.Error(w, "ID required", 400)
		return
	}

	result, err := backup.GetSchedule(dbConn, ID)
	if err != nil {
		logit.Error.Println("GetNode: " + err.Error())
		rest.Error(w, err.Error(), 400)
		return
	}

	w.WriteJson(result)

}
func GetCluster(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetCluster: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ID := r.PathParam("ID")
	results, err := admindb.GetCluster(dbConn, ID)
	if err != nil {
		logit.Error.Println("GetCluster:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
	}
	cluster := Cluster{results.ID, results.ProjectID, results.Name, results.ClusterType,
		results.Status, results.CreateDate, "", results.Containers}
	logit.Info.Println("GetCluser:db call results=" + results.ID)

	w.WriteJson(&cluster)
}
func GetRole(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetRole: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	Name := r.PathParam("Name")
	if Name == "" {
		logit.Error.Println("GetRole: error Name required")
		rest.Error(w, "Name required", http.StatusBadRequest)
		return
	}

	var role sec.Role
	role, err = secimpl.GetRole(dbConn, Name)
	if err != nil {
		logit.Error.Println("GetRole: error secimpl call" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusOK)
	w.WriteJson(&role)
}
func ContainerLoadTest(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("ContainerLoadTest: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ID := r.PathParam("ID")

	if ID == "" {
		rest.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	Writes := r.PathParam("Writes")

	if Writes == "" {
		rest.Error(w, "Writes required", http.StatusBadRequest)
		return
	}
	var writes int
	writes, err = strconv.Atoi(Writes)
	if err != nil {
		logit.Error.Println("ContainerLoadTest:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	node, err := admindb.GetContainer(dbConn, ID)
	if err != nil {
		logit.Error.Println("ContainerLoadTest:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	var host = node.Name
	if KubeEnv {
		host = node.Name + "-db"
	}

	results, err2 := loadtest(dbConn, node.Name, host, writes)
	if err2 != nil {
		logit.Error.Println("ContainerLoadTest:" + err2.Error())
		rest.Error(w, err2.Error(), http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&results)
}
func Logout(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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 := SimpleStatus{}
	status.Status = "OK"
	w.WriteJson(&status)
}
func ContainerAccessRuleGetAll(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("ContainerRulesGetAll: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ContainerID := r.PathParam("ID")
	if ContainerID == "" {
		rest.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	cars, err := GetAllContainerAccessRule(dbConn, ContainerID)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&cars)
}
func GetStatus(w rest.ResponseWriter, r *rest.Request) {
	Token := r.PathParam("Token")
	if Token == "" {
		rest.Error(w, "Token required", 400)
		return
	}
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		rest.Error(w, err.Error(), 400)
		return

	}
	defer dbConn.Close()
	err = secimpl.Authorize(dbConn, Token, "perm-read")
	if err != nil {
		logit.Error.Println("GetStatus: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	ID := r.PathParam("ID")
	if ID == "" {
		rest.Error(w, "ID required", 400)
		return
	}
	stat, err := backup.GetStatus(dbConn, ID)
	if err != nil {
		logit.Error.Println("GetStatus: " + err.Error())
		rest.Error(w, err.Error(), 400)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(stat)
}
func GetProject(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetProject: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ID := r.PathParam("ID")
	if ID == "" {
		logit.Error.Println("GetProject: error Project ID required")
		rest.Error(w, "Project ID required", http.StatusBadRequest)
		return
	}

	results, err := admindb.GetProject(dbConn, ID)
	if err != nil {
		logit.Error.Println("GetProject:" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	project := Project{results.ID, results.Name, results.Desc, results.UpdateDate, "", results.Containers, results.Clusters}

	w.WriteJson(&project)
}
func MonitorContainerControldata(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("MonitorContainerControldata: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ID := r.PathParam("ID")
	if ID == "" {
		rest.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	node, err := admindb.GetContainer(dbConn, ID)
	if err != nil {
		logit.Error.Println("MonitorContainerControldata:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	settings := make([]PostgresControldata, 0)

	//send the container a pg_controldata command
	var cdout cpmcontainerapi.ControldataResponse
	cdout, err = cpmcontainerapi.ControldataClient(node.Name)
	if err != nil {
		logit.Error.Println("MonitorContainerControldata:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	logit.Info.Println(cdout.Output)

	lines := strings.Split(cdout.Output, "\n")
	//fmt.Println(len(lines))
	for i := range lines {
		//fmt.Println(len(lines[i]))
		if len(lines[i]) > 1 {
			setting := PostgresControldata{}
			columns := strings.Split(lines[i], ":")
			setting.Name = strings.TrimSpace(columns[0])
			setting.Value = strings.TrimSpace(columns[1])
			//fmt.Println("name=[" + strings.TrimSpace(columns[0]) + "] value=[" + strings.TrimSpace(columns[1]) + "]")
			settings = append(settings, setting)
		}
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&settings)
}
func LoadSchedules() error {

	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		return err

	}
	defer dbConn.Close()

	logit.Info.Println("LoadSchedules called")

	var schedules []BackupSchedule
	schedules, err = GetSchedules(dbConn)
	if err != nil {
		logit.Error.Println("LoadSchedules error " + err.Error())
		return err
	}

	if CRONInstance != nil {
		logit.Info.Println("stopping current cron instance...")
		CRONInstance.Stop()
	}

	//kill off the old cron, garbage collect it
	CRONInstance = nil

	//create a new cron
	logit.Info.Println("creating cron instance...")
	CRONInstance = cron.New()

	var cronexp string
	for i := 0; i < len(schedules); i++ {
		cronexp = getCron(schedules[i])
		logit.Info.Println("would have loaded schedule..." + cronexp)
		if schedules[i].Enabled == "YES" {
			logit.Info.Println("schedule " + schedules[i].ID + " was enabled so adding it")
			x := DefaultJob{}
			x.request = BackupRequest{}
			x.request.ScheduleID = schedules[i].ID
			x.request.ServerID = schedules[i].ServerID
			x.request.ServerName = schedules[i].ServerName
			x.request.ServerIP = schedules[i].ServerIP
			x.request.ContainerName = schedules[i].ContainerName
			x.request.ProfileName = schedules[i].ProfileName

			CRONInstance.AddJob(cronexp, x)
		} else {
			logit.Info.Println("schedule " + schedules[i].ID + " NOT enabled so dropping it")
		}

	}

	logit.Info.Println("starting new CRONInstance")
	CRONInstance.Start()

	return err
}
//we use AddServer for both updating and inserting based on the ID passed in
func AddServer(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		rest.Error(w, err.Error(), 400)
		return

	}
	defer dbConn.Close()

	err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-server")
	if err != nil {
		logit.Error.Println("AddServer: authorize token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	CreateDate := ""
	server := Server{r.PathParam("ID"), r.PathParam("Name"), r.PathParam("IPAddress"), r.PathParam("DockerBridgeIP"), r.PathParam("PGDataPath"), r.PathParam("ServerClass"), CreateDate}

	server.IPAddress = strings.Replace(server.IPAddress, "_", ".", -1)
	server.DockerBridgeIP = strings.Replace(server.DockerBridgeIP, "_", ".", -1)
	server.PGDataPath = strings.Replace(server.PGDataPath, "_", "/", -1)

	if server.Name == "" {
		logit.Error.Println("AddServer: error server name required")
		rest.Error(w, "server name required", http.StatusBadRequest)
		return
	}
	if server.IPAddress == "" {
		logit.Error.Println("AddServer: error ipaddress required")
		rest.Error(w, "server IPAddress required", http.StatusBadRequest)
		return
	}
	if server.PGDataPath == "" {
		logit.Error.Println("AddServer: error pgdatapath required")
		rest.Error(w, "server PGDataPath required", http.StatusBadRequest)
		return
	}

	dbserver := admindb.Server{server.ID, server.Name, server.IPAddress,
		server.DockerBridgeIP, server.PGDataPath, server.ServerClass, CreateDate, ""}
	if dbserver.ID == "0" {
		strid, err := admindb.InsertServer(dbConn, dbserver)
		newid := strconv.Itoa(strid)
		if err != nil {
			logit.Error.Println("AddServer:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		server.ID = newid
	} else {
		admindb.UpdateServer(dbConn, dbserver)
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&server)
}
func ChangePassword(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("ChangePassword: error in decode" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	err = secimpl.Authorize(dbConn, changePass.Token, "perm-read")
	if err != nil {
		logit.Error.Println("ChangePassword: authorize error " + 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("ChangePassword: compare UserToToken error " + 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("ChangePassword: authorize error " + err.Error())
			rest.Error(w, err.Error(), http.StatusUnauthorized)
			return
		}
	}

	err = secimpl.ChangePassword(dbConn, changePass.Username, changePass.Password)
	if err != nil {
		logit.Error.Println("ChangePassword: error secimpl call" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	status := SimpleStatus{}
	status.Status = "OK"
	w.WriteJson(&status)
}
func AdminStoppg(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("AdminStoppg: authorize error " + 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 admindb.Container
	dbNode, err = admindb.GetContainer(dbConn, ID)
	if err != nil {
		logit.Error.Println("AdminStartpg: " + 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("AdminStoppg:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//give the UI a chance to see the stop
	time.Sleep(3000 * time.Millisecond)

	w.WriteHeader(http.StatusOK)
	status := SimpleStatus{}
	status.Status = "OK"
	w.WriteJson(&status)
}
//this is the func that implements the cron Job interface
func (t DefaultJob) Run() {
	logit.Info.Println("running ScheduleID:" + t.request.ScheduleID)
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
	}
	defer dbConn.Close()

	ProvisionBackupJob(dbConn, &t.request)
}
func AdminStartNode(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("AdminStartNode: validate token error " + 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("AdminStartNode:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	server := admindb.Server{}
	server, err = admindb.GetServer(dbConn, node.ServerID)
	if err != nil {
		logit.Error.Println("AdminStartNode:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	var url = "http://" + server.IPAddress + ":10001"
	var response cpmserverapi.DockerStartResponse
	request := &cpmserverapi.DockerStartRequest{}
	request.ContainerName = node.Name
	response, err = cpmserverapi.DockerStartClient(url, request)
	if err != nil {
		logit.Error.Println("AdminStartNode: error when trying to start container " + err.Error())
	}
	logit.Info.Println(response.Output)

	w.WriteHeader(http.StatusOK)
	status := SimpleStatus{}
	status.Status = "OK"
	w.WriteJson(&status)

}
//we use POST for both updating and inserting based on the ID passed in
func PostCluster(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		rest.Error(w, err.Error(), 400)
		return

	}
	defer dbConn.Close()
	logit.Info.Println("PostCluster: in PostCluster")
	cluster := Cluster{}
	err = r.DecodeJsonPayload(&cluster)
	if err != nil {
		logit.Error.Println("PostCluster: error in decode" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	err = secimpl.Authorize(dbConn, cluster.Token, "perm-cluster")
	if err != nil {
		logit.Error.Println("PostCluster: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	if cluster.Name == "" {
		logit.Error.Println("PostCluster: error in Name")
		rest.Error(w, "cluster name required", http.StatusBadRequest)
		return
	}

	logit.Info.Println("PostCluster: have ID=" + cluster.ID + " Name=" + cluster.Name + " type=" + cluster.ClusterType + " status=" + cluster.Status)
	dbcluster := admindb.Cluster{cluster.ID, cluster.ProjectID, cluster.Name, cluster.ClusterType, cluster.Status, "", cluster.Containers}
	if cluster.ID == "" {
		strid, err := admindb.InsertCluster(dbConn, dbcluster)
		newid := strconv.Itoa(strid)
		if err != nil {
			logit.Error.Println("PostCluster:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		cluster.ID = newid
	} else {
		logit.Info.Println("PostCluster: about to call UpdateCluster")
		err2 := admindb.UpdateCluster(dbConn, dbcluster)
		if err2 != nil {
			logit.Error.Println("PostCluster: error in UpdateCluster " + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}

	w.WriteJson(&cluster)
}
func UpdateProject(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		rest.Error(w, err.Error(), 400)
		return

	}
	defer dbConn.Close()

	logit.Info.Println("UpdateProject: in UpdateProject")
	project := Project{}
	err = r.DecodeJsonPayload(&project)
	if err != nil {
		logit.Error.Println("UpdateProject: error in decode" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	logit.Info.Println("UpdateProject: ID=" + project.ID)
	logit.Info.Println("UpdateProject: Name=" + project.Name)
	logit.Info.Println("UpdateProject: Desc=" + project.Desc)
	logit.Info.Println("UpdateProject: token=" + project.Token)

	err = secimpl.Authorize(dbConn, project.Token, "perm-container")
	if err != nil {
		logit.Error.Println("UpdateProject: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	dbproject := admindb.Project{
		ID:         project.ID,
		Name:       project.Name,
		Desc:       project.Desc,
		UpdateDate: project.UpdateDate,
		Containers: project.Containers,
		Clusters:   project.Clusters}

	err = admindb.UpdateProject(dbConn, dbproject)
	if err != nil {
		logit.Error.Println("UpdateProject: error secimpl call" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusOK)
	status := SimpleStatus{}
	status.Status = "OK"
	w.WriteJson(&status)
}
func RulesUpdate(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("RulesUpdate: error in decode" + err.Error())
		rest.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	err = secimpl.Authorize(dbConn, rule.Token, "perm-container")
	if err != nil {
		logit.Error.Println("RulesUpdate: authorize error " + 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("RulesUpdate: error " + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	status := SimpleStatus{}
	status.Status = "OK"
	w.WriteHeader(http.StatusOK)
	w.WriteJson(&status)
}
func GetAllNodesForCluster(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("GetAllForCluster: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ClusterID := r.PathParam("ClusterID")
	if ClusterID == "" {
		logit.Error.Println("GetAllNodesForCluster: node ClusterID required")
		rest.Error(w, "node ClusterID required", http.StatusBadRequest)
		return
	}

	results, err := admindb.GetAllContainersForCluster(dbConn, ClusterID)
	if err != nil {
		logit.Error.Println("GetAllNodesForCluster:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
	}
	nodes := make([]ClusterNode, len(results))
	i := 0
	for i = range results {
		nodes[i].ID = results[i].ID
		nodes[i].Name = results[i].Name
		nodes[i].ClusterID = results[i].ClusterID
		nodes[i].ServerID = results[i].ServerID
		nodes[i].Role = results[i].Role
		nodes[i].Image = results[i].Image
		nodes[i].CreateDate = results[i].CreateDate
		nodes[i].ProjectID = results[i].ProjectID
		nodes[i].ProjectName = results[i].ProjectName
		nodes[i].ServerName = results[i].ServerName
		nodes[i].ClusterName = results[i].ClusterName
		//nodes[i].Status = "UNKNOWN"
		i++
	}

	w.WriteJson(&nodes)

}
func BadgerGenerate(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + 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("BadgerGenerate: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	ID := r.PathParam("ID")
	if ID == "" {
		rest.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	container, err := admindb.GetContainer(dbConn, ID)
	if err != nil {
		logit.Error.Println("BadgerGenerate:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	var host = container.Name
	if KubeEnv {
		host = container.Name + "-db"
	}

	//send the container a pg_controldata command
	var cdout cpmcontainerapi.BadgerGenerateResponse
	cdout, err = cpmcontainerapi.BadgerGenerateClient(host)
	if err != nil {
		logit.Error.Println("BadgerGenerate:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	logit.Info.Println(cdout.Output)

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&cdout)
}
func GetBackupNodes(w rest.ResponseWriter, r *rest.Request) {
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		rest.Error(w, err.Error(), 400)
		return

	}

	err = secimpl.Authorize(dbConn, r.PathParam("Token"), "perm-read")
	if err != nil {
		logit.Error.Println("GetAllNodes: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	results, err2 := admindb.GetAllContainers(dbConn)
	if err2 != nil {
		logit.Error.Println("GetAllNodes: " + err2.Error())
		rest.Error(w, err2.Error(), 400)
	}
	i := 0
	//nodes := make([]ClusterNode, found)
	nodes := []ClusterNode{}
	for i = range results {
		if results[i].Role == "unassigned" ||
			results[i].Role == "master" {
			n := ClusterNode{}
			n.ID = results[i].ID
			n.Name = results[i].Name
			n.ClusterID = results[i].ClusterID
			n.ServerID = results[i].ServerID
			n.Role = results[i].Role
			n.Image = results[i].Image
			n.CreateDate = results[i].CreateDate
			n.ProjectName = results[i].ProjectName
			n.ServerName = results[i].ServerName
			n.Status = "UNKNOWN"
			nodes = append(nodes, n)
		}
		i++
	}

	w.WriteJson(&nodes)

}
//called by backup jobs as they execute
func (t *Command) AddStatus(status *BackupStatus, reply *Command) error {

	logit.Info.Println("AddStatus called")
	dbConn, err := util.GetConnection(CLUSTERADMIN_DB)
	if err != nil {
		logit.Error.Println("BackupNow: error " + err.Error())
		return err

	}
	defer dbConn.Close()
	var id string
	id, err = AddStatus(dbConn, *status)
	if err != nil {
		logit.Error.Println("AddStatus error " + err.Error())
	}
	reply.Output = id
	return err
}