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 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 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)
}
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)

}
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 MonitorStatements(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("MonitorStatements: 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("MonitorStatements:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

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

	//fetch cpmtest user credentials
	var nodeuser admindb.ContainerUser
	nodeuser, err = admindb.GetContainerUser(dbConn, container.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")

	dbConn2, err := util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, nodeuser.Passwd)
	defer dbConn2.Close()

	//get the list of databases
	databases := make([]string, 0)
	var rows *sql.Rows

	rows, err = dbConn2.Query(
		"SELECT datname from pg_database where datname not in ('template1', 'template0') order by datname")
	if err != nil {
		logit.Error.Println("MonitorStatements:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	var datname string
	for rows.Next() {
		if err = rows.Scan(
			&datname,
		); err != nil {
			logit.Error.Println("MonitorContainerSettings:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		databases = append(databases, datname)
	}
	if err = rows.Err(); err != nil {
		logit.Error.Println("MonitorStatements:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	rows.Close()

	statements := make([]PostgresStatement, 0)

	for i := range databases {
		//get a database connection to a specific database
		dbConn3, err := util.GetMonitoringConnection(host, databases[i], pgport.Value, CPMTEST_USER, nodeuser.Passwd)
		defer dbConn3.Close()

		rows, err = dbConn3.Query(
			"SELECT query, calls, total_time, rows, to_char(coalesce(100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0), -1), '999D99') AS hit_percent FROM pg_stat_statements ORDER BY total_time DESC LIMIT 5")
		if err != nil {
			logit.Error.Println("MonitorStatements:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		defer rows.Close()
		for rows.Next() {
			stat := PostgresStatement{}
			stat.Database = databases[i]
			if err = rows.Scan(
				&stat.Query,
				&stat.Calls,
				&stat.TotalTime,
				&stat.Rows,
				&stat.HitPercent,
			); err != nil {
				logit.Error.Println("MonitorContainerSettings:" + err.Error())
				rest.Error(w, err.Error(), http.StatusBadRequest)
				return
			}
			statements = append(statements, stat)
		}
		if err = rows.Err(); err != nil {
			logit.Error.Println("MonitorStatements:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&statements)
}
func MonitorContainerSettings(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("MonitorContainerSettings: 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("MonitorContainerGetInfo:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

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

	//fetch cpmtest user credentials
	var nodeuser admindb.ContainerUser
	nodeuser, err = admindb.GetContainerUser(dbConn, node.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	logit.Info.Println("cpmtest password is " + nodeuser.Passwd)

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")

	dbConn2, err := util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, nodeuser.Passwd)
	defer dbConn2.Close()

	settings := make([]PostgresSetting, 0)
	var rows *sql.Rows

	rows, err = dbConn2.Query("select name, current_setting(name), source from pg_settings where source not in ('default','override')")
	if err != nil {
		logit.Error.Println("MonitorContainerSettings:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	defer rows.Close()
	for rows.Next() {
		setting := PostgresSetting{}
		if err = rows.Scan(
			&setting.Name,
			&setting.CurrentSetting,
			&setting.Source,
		); err != nil {
			logit.Error.Println("MonitorContainerSettings:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		settings = append(settings, setting)
	}
	if err = rows.Err(); err != nil {
		logit.Error.Println("MonitorContainerSettings:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&settings)
}
func ContainerInfoStatrepl(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("ContainerStatrepl: 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("ContainerStatrepl:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

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

	//fetch cpmtest user credentials
	var nodeuser admindb.ContainerUser
	nodeuser, err = admindb.GetContainerUser(dbConn, node.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")

	dbConn2, err := util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, nodeuser.Passwd)
	defer dbConn2.Close()

	stats := make([]Statrepl, 0)
	var rows *sql.Rows

	rows, err = dbConn2.Query("SELECT pid , usesysid , usename , application_name , client_addr , coalesce(client_hostname, ' ') , client_port , to_char(backend_start, 'YYYY-MM-DD HH24:MI-SS') as backend_start , state , sent_location , write_location , flush_location , replay_location , sync_priority , sync_state from pg_stat_replication")
	if err != nil {
		logit.Error.Println("ContainerStatrepl:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	defer rows.Close()
	for rows.Next() {
		stat := Statrepl{}
		if err = rows.Scan(
			&stat.Pid,
			&stat.Usesysid,
			&stat.Usename,
			&stat.AppName,
			&stat.ClientAddr,
			&stat.ClientHostname,
			&stat.ClientPort,
			&stat.BackendStart,
			&stat.State,
			&stat.SentLocation,
			&stat.WriteLocation,
			&stat.FlushLocation,
			&stat.ReplayLocation,
			&stat.SyncPriority,
			&stat.SyncState,
		); err != nil {
			logit.Error.Println("ContainerStatrepl:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		stats = append(stats, stat)
	}
	if err = rows.Err(); err != nil {
		logit.Error.Println("ContainerStatrepl:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&stats)
}
func ContainerInfoBgwriter(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("ContainerBgwriter: 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("ContainerBgwriter:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

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

	//get password
	var nodeuser admindb.ContainerUser
	nodeuser, err = admindb.GetContainerUser(dbConn, node.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println("ContainerBgwriter:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")

	var dbConn2 *sql.DB
	dbConn2, err = util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, nodeuser.Passwd)
	defer dbConn2.Close()

	info := Bgwriter{}
	err = dbConn2.QueryRow("SELECT to_char(now(), 'mm/dd/yy HH12:MI:SS') now, to_char(block_size::numeric * buffers_alloc / (1024 * 1024 * seconds), 'FM999999999999D9999') AS alloc_mbps, to_char(block_size::numeric * buffers_checkpoint / (1024 * 1024 * seconds), 'FM999999999999D9999') AS checkpoint_mbps, to_char(block_size::numeric * buffers_clean / (1024 * 1024 * seconds), 'FM999999999999D9999') AS clean_mbps, to_char(block_size::numeric * buffers_backend/ (1024 * 1024 * seconds), 'FM999999999999D9999') AS backend_mbps, to_char(block_size::numeric * (buffers_checkpoint + buffers_clean + buffers_backend) / (1024 * 1024 * seconds), 'FM999999999999D9999') AS write_mbps FROM ( SELECT now() AS sample,now() - stats_reset AS uptime,EXTRACT(EPOCH FROM now()) - extract(EPOCH FROM stats_reset) AS seconds, b.*,p.setting::integer AS block_size FROM pg_stat_bgwriter b,pg_settings p WHERE p.name='block_size') bgw").Scan(&info.Now, &info.AllocMbps, &info.CheckpointMbps, &info.CleanMbps, &info.BackendMbps, &info.WriteMbps)
	switch {
	case err == sql.ErrNoRows:
		logit.Error.Println("ContainerBgwriter:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	case err != nil:
		logit.Error.Println("ContainerBgwriter:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&info)
}
func ContainerInfoStatdatabase(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("ContainerStatdatabase: 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("ContainerStatdatabase:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

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

	//get password
	var nodeuser admindb.ContainerUser
	nodeuser, err = admindb.GetContainerUser(dbConn, node.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")

	dbConn2, err := util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, nodeuser.Passwd)
	defer dbConn2.Close()

	stats := make([]Statdatabase, 0)
	var rows *sql.Rows

	rows, err = dbConn2.Query("SELECT datname, blks_read::text, tup_returned::text, tup_fetched::text, tup_inserted::text, tup_updated::text, tup_deleted::text, coalesce(to_char(stats_reset, 'YYYY-MM-DD HH24:MI:SS'), ' ') as stats_reset from pg_stat_database")
	if err != nil {
		logit.Error.Println("ContainerStatdatabase:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	defer rows.Close()
	for rows.Next() {
		stat := Statdatabase{}
		if err = rows.Scan(
			&stat.Datname,
			&stat.BlksRead,
			&stat.TupReturned,
			&stat.TupFetched,
			&stat.TupInserted,
			&stat.TupUpdated,
			&stat.TupDeleted,
			&stat.StatsReset,
		); err != nil {
			logit.Error.Println("ContainerStatdatabase:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		stats = append(stats, stat)
	}
	if err = rows.Err(); err != nil {
		logit.Error.Println("ContainerStatdatabase:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&stats)
}
func AdminFailover(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("AdminFailover: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}
	ID := r.PathParam("ID")
	if ID == "" {
		logit.Error.Println("AdminFailover: 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 admindb.Container
	dbNode, err = admindb.GetContainer(dbConn, ID)
	if err != nil {
		logit.Error.Println("AdminFailover:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	cluster, err := admindb.GetCluster(dbConn, dbNode.ClusterID)
	if err != nil {
		logit.Error.Println("AdminFailover:" + 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("AdminFailover: 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 := admindb.Container{}
	oldMaster, err = admindb.GetContainerMaster(dbConn, dbNode.ClusterID)
	if err != nil {
		logit.Error.Println("AdminFailover:" + 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("AdminFailover:" + 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("AdminFailover:" + 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("AdminFailover: " + err.Error() + stopPGResp.Output)
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	err = configureCluster(dbConn, cluster, false)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

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

	return
}
func GetNode(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("GetNode: validate token error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

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

	results, err2 := admindb.GetContainer(dbConn, ID)

	if results.ID == "" {
		rest.NotFound(w, r)
		return
	}
	if err2 != nil {
		logit.Error.Println("GetNode: " + err2.Error())
		rest.Error(w, err2.Error(), http.StatusBadRequest)
		return
	}

	var currentStatus = "UNKNOWN"

	//go get the docker server IPAddress
	/**
	server := admindb.Server{}
	server, err = admindb.GetServer(dbConn, results.ServerID)
	if err != nil {
		logit.Error.Println("GetNode: " + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	*/
	var domain string
	domain, err = admindb.GetDomain(dbConn)
	if err != nil {
		logit.Error.Println("GetNode: " + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	/**
	request := &cpmserverapi.DockerInspectRequest{}
	request.ContainerName = results.Name
	var url = "http://" + server.IPAddress + ":10001"
	_, err = cpmserverapi.DockerInspectClient(url, request)
	if err != nil {
		logit.Error.Println("GetNode: " + err.Error())
		currentStatus = CONTAINER_NOT_FOUND
	}
	*/

	//if currentStatus != "CONTAINER NOT FOUND" {
	//ping the db on that node to get current status
	var pinghost = results.Name
	logit.Info.Println("pinging db on " + pinghost + "." + domain)
	currentStatus, err = GetPGStatus2(dbConn, results.Name, pinghost)
	if err != nil {
		logit.Error.Println("GetNode:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	logit.Info.Println("pinging db finished")
	//}

	node := ClusterNode{results.ID, results.ClusterID, results.ServerID,
		results.Name, results.Role, results.Image, results.CreateDate, currentStatus, results.ProjectID, results.ProjectName, results.ServerName, results.ClusterName}

	w.WriteJson(node)
}
func performConfigUpdate(dbConn *sql.DB, ContainerID string) error {
	logit.Info.Println("performConfigUpdate....")

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

	container, err := admindb.GetContainer(dbConn, ContainerID)
	if err != nil {
		logit.Error.Println("GetNode: " + err.Error())
		return err
	}

	var currentStatus string
	currentStatus, err = GetPGStatus2(dbConn, container.Name, container.Name)
	if err != nil {
		logit.Error.Println("GetNode:" + err.Error())
		return err
	}

	if currentStatus != "RUNNING" {
		logit.Info.Println("performConfigUpdate....starting postgres")
		if container.Role == "pgpool" {
			var spgresp cpmcontainerapi.StartPgpoolResponse
			spgresp, err = cpmcontainerapi.StartPgpoolClient(container.Name)
			logit.Info.Println("AdminStartpg:" + spgresp.Output)
		} else {
			var srep cpmcontainerapi.StartPGResponse
			srep, err = cpmcontainerapi.StartPGClient(container.Name)
			logit.Info.Println("AdminStartpg:" + srep.Output)
		}

		if err != nil {
			logit.Error.Println("AdminStartpg:" + err.Error())
			return err
		}

		//give the UI a chance to see the start
		time.Sleep(5000 * time.Millisecond)

	}

	//make template changes here
	logit.Info.Println("performConfigUpdate....making template changes")
	templateChange(dbConn, container.Name, cars, container.Role)

	//restart postgres

	logit.Info.Println("performConfigUpdate....stopping postgres")
	if container.Role == "pgpool" {
		var stoppoolResp cpmcontainerapi.StopPgpoolResponse
		stoppoolResp, err = cpmcontainerapi.StopPgpoolClient(container.Name)
		logit.Info.Println("AdminStoppg:" + stoppoolResp.Output)
	} else {
		var stoppgResp cpmcontainerapi.StopPGResponse
		stoppgResp, err = cpmcontainerapi.StopPGClient(container.Name)
		logit.Info.Println("AdminStoppg:" + stoppgResp.Output)
	}
	if err != nil {
		logit.Error.Println("AdminStoppg:" + err.Error())
		return err
	}

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

	logit.Info.Println("performConfigUpdate....starting postgres")
	if container.Role == "pgpool" {
		var spgresp cpmcontainerapi.StartPgpoolResponse
		spgresp, err = cpmcontainerapi.StartPgpoolClient(container.Name)
		logit.Info.Println("AdminStartpg:" + spgresp.Output)
	} else {
		var srep cpmcontainerapi.StartPGResponse
		srep, err = cpmcontainerapi.StartPGClient(container.Name)
		logit.Info.Println("AdminStartpg:" + srep.Output)
	}

	if err != nil {
		logit.Error.Println("AdminStartpg:" + err.Error())
		return err
	}

	return err

}
func UpdateContainerUser(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()

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

	err = secimpl.Authorize(dbConn, postMsg.Token, "perm-user")
	if err != nil {
		logit.Error.Println("UpdateContainerUser: validate token error " + 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 admindb.Container
	node, err = admindb.GetContainer(dbConn, postMsg.ID)
	if err != nil {
		logit.Error.Println("AddContainUser: "******"" {
	} else {
		//update the password
	}

	//get connection to container's database
	var host = node.Name
	if KubeEnv {
		host = node.Name + "-db"
	}

	//fetch cpmtest user credentials
	var cpmuser admindb.ContainerUser
	cpmuser, err = admindb.GetContainerUser(dbConn, node.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")
	var dbConn2 *sql.DB

	dbConn2, err = util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, cpmuser.Passwd)
	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("UpdateContainerUser:"******"" {
		//update user's password
		dbuser := admindb.ContainerUser{}
		dbuser.Containername = node.Name
		dbuser.Passwd = postMsg.Passwd
		dbuser.Rolname = postMsg.Rolname

		err = admindb.UpdateContainerUser(dbConn, dbuser)
		if err != nil {
			logit.Error.Println("UpdateContainerUser: "******"OK"
	w.WriteJson(&status)
}
func GetAllUsersForContainer(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("GetAllUsersForContainer: 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
	}

	//get container info
	var node admindb.Container
	node, err = admindb.GetContainer(dbConn, ID)
	if err != nil {
		logit.Error.Println("GetAllUsersForContainer: " + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//get connection to container's database
	var host = node.Name
	if KubeEnv {
		host = node.Name + "-db"
	}

	//fetch cpmtest user credentials
	var nodeuser admindb.ContainerUser
	nodeuser, err = admindb.GetContainerUser(dbConn, node.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	logit.Info.Println("cpmtest password is " + nodeuser.Passwd)

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")
	var dbConn2 *sql.DB
	dbConn2, err = util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, nodeuser.Passwd)
	defer dbConn2.Close()

	users := make([]admindb.ContainerUser, 0)

	//query results
	var rows *sql.Rows

	rows, err = dbConn2.Query("select rolname::text, rolsuper::text, rolinherit::text, rolcreaterole::text, rolcreatedb::text, rolcatupdate::text, rolcanlogin::text, rolreplication::text from pg_roles order by rolname")
	if err != nil {
		logit.Error.Println("GetAllUsersForContainer:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	defer rows.Close()

	for rows.Next() {
		user := admindb.ContainerUser{}
		if err = rows.Scan(
			&user.Rolname,
			&user.Rolsuper,
			&user.Rolinherit,
			&user.Rolcreaterole,
			&user.Rolcreatedb,
			&user.Rolcatupdate,
			&user.Rolcanlogin,
			&user.Rolreplication,
		); err != nil {
			logit.Error.Println("GetAllUsersForContainer:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		user.Containername = node.Name
		user.ContainerID = node.ID
		users = append(users, user)
	}
	if err = rows.Err(); err != nil {
		logit.Error.Println("GetAllUsersForContainer:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.WriteJson(&users)

}
func GetContainerUser(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("GetContainerUser: validate token error " + 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 container info
	node, err := admindb.GetContainer(dbConn, ContainerID)
	if err != nil {
		logit.Error.Println("AddContainUser: "******"-db"
	}

	//fetch  user credentials
	var nodeuser admindb.ContainerUser
	nodeuser, err = admindb.GetContainerUser(dbConn, node.Name, Rolname)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//fetch cpmtest user credentials
	var cpmuser admindb.ContainerUser
	cpmuser, err = admindb.GetContainerUser(dbConn, node.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")

	dbConn2, err := util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, cpmuser.Passwd)
	defer dbConn2.Close()

	query := "select rolname::text, rolsuper::text, rolinherit::text, rolcreaterole::text, rolcreatedb::text, rolcatupdate::text, rolcanlogin::text, rolreplication::text from pg_roles where rolname = '" + Rolname + "' order by rolname"

	logit.Info.Println(query)

	err = dbConn2.QueryRow(query).Scan(
		&nodeuser.Rolname,
		&nodeuser.Rolsuper,
		&nodeuser.Rolinherit,
		&nodeuser.Rolcreaterole,
		&nodeuser.Rolcreatedb,
		&nodeuser.Rolcatupdate,
		&nodeuser.Rolcanlogin,
		&nodeuser.Rolreplication)
	if err != nil {
		logit.Error.Println("GetContainerUser:" + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	w.WriteJson(&nodeuser)

}
func DeleteContainerUser(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-backup")
	if err != nil {
		logit.Error.Println("DeleteContainerUser: validate token error " + 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("AddContainUser: "******"DeleteContainerUser: "******"-db"
	}

	//fetch cpmtest user credentials
	var cpmuser admindb.ContainerUser
	cpmuser, err = admindb.GetContainerUser(dbConn, node.Name, CPMTEST_USER)
	if err != nil {
		logit.Error.Println(err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//get port
	var pgport admindb.Setting
	pgport, err = admindb.GetSetting(dbConn, "PG-PORT")

	dbConn2, err := util.GetMonitoringConnection(host, CPMTEST_DB, pgport.Value, CPMTEST_USER, cpmuser.Passwd)
	defer dbConn2.Close()

	query := "drop role " + rolname

	logit.Info.Println(query)

	_, err = dbConn2.Query(query)
	if err != nil {
		logit.Error.Println("DeleteContainerUser:"******"OK"
	w.WriteJson(&status)

}
func EventJoinCluster(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("EventJoinCluster: authorize error " + err.Error())
		rest.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	IDList := r.PathParam("IDList")
	if IDList == "" {
		logit.Error.Println("EventJoinCluster: error 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("EventJoinCluster: error 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("EventJoinCluster: error 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 := admindb.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("EventJoinCluster:" + 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_IMAGE {
				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("EventJoinCluster:" + 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("EventJoinCluster:" + 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("EventJoinCluster:" + err.Error())
			rest.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
	}

	w.WriteHeader(http.StatusOK)
	status := 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("BackupNow: error " + 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("DeleteNode: validate token error " + 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 admindb.Container
	dbNode, err = admindb.GetContainer(dbConn, ID)
	if err != nil {
		logit.Error.Println("DeleteNode: " + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	//go get the docker server IPAddress
	server := admindb.Server{}
	server, err = admindb.GetServer(dbConn, dbNode.ServerID)
	if err != nil {
		logit.Error.Println("DeleteNode: " + err.Error())
		rest.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	var url = "http://" + server.IPAddress + ":10001"

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

	logit.Info.Println("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

	request := &cpmserverapi.DockerRemoveRequest{}
	request.ContainerName = dbNode.Name
	_, err = cpmserverapi.DockerRemoveClient(url, request)
	if err != nil {
		logit.Error.Println("DeleteNode: error when trying to remove container " + err.Error())
	}

	//send the server a deletevolume command
	request2 := &cpmserverapi.DiskDeleteRequest{}
	request2.Path = server.PGDataPath + "/" + dbNode.Name
	_, err = cpmserverapi.DiskDeleteClient(url, request2)
	if err != nil {
		fmt.Println(err.Error())
	}

	//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 := SimpleStatus{}
	status.Status = "OK"
	w.WriteJson(&status)
}