예제 #1
0
// setup continuous replication between all pods in couchdb cluster
// first it will cancel any replication for all pods
// then it will reinit circle continuous replication between all pods
// requirement -> replicas > 1 !!
// @param cluster - CouchdbCluster struct - cluster where setup replication
func (cluster *CouchdbCluster) SetupReplication(databases []string) error {
	DebugLog("couchdb_control: setup: _replication: Replication setup for all PODS, dbs to replicate:")
	DebugLog(databases)
	// check fi all pods are ready and in running state
	err := cluster.CheckAllCouchdbPods()
	if err != nil {
		ErrorLog("couchdb_control: setup_replication: check all pods error")
		return err
	}
	// create couchdb admin credentials
	credentials := couch.NewCredentials(cluster.Username, cluster.Password)
	// get all pods
	podSvcList, err := cluster.GetAllPodServices()
	if err != nil {
		ErrorLog("couchdb_control: setup_replication: check all pods error")
		return err
	}
	podSvcs := *podSvcList
	DebugLog("couchdb_control: setup_replication: interate throught all pod services")
	// iterate through all pods
	for i := 0; i < len(podSvcs); i++ {
		// index of next pod
		j := (i + 1) % len(podSvcs)
		DebugLog("couchdb_control: setup replication: pod: " + podSvcs[i].Name + "," + podSvcs[i].Spec.ClusterIP)

		// primary - replicate FROM
		server1 := couch.NewServer("http://"+podSvcs[i].Spec.ClusterIP+":"+COUCHDB_PORT_STRING, credentials)
		// check server1
		if err := CheckServer(server1, MAX_RETRIES, RETRY_WAIT_TIME); err != nil {
			// failed to connect to server after all retries, fail replication
			ErrorLog("couchdb_control: setupReplication: failed to connect to server1, pod:" + podSvcs[i].Name)
			ErrorLog(err)
			return err
		}
		// secondary - replicate TO
		server2 := couch.NewServer("http://"+podSvcs[j].Spec.ClusterIP+":"+COUCHDB_PORT_STRING, credentials)
		if err := CheckServer(server2, MAX_RETRIES, RETRY_WAIT_TIME); err != nil {
			// failed to connect to server after all retries, fail replication
			ErrorLog("couchdb_control: setupReplication: failed to connect to server2, pod:" + podSvcs[j].Name)
			ErrorLog(err)
			return err
		}

		// set replication between two pods for all listed databases
		for _, db := range databases {
			// db1 server1
			db1 := server1.Database(db)
			db1.Create()
			// db1  server2
			db2 := server2.Database(db)
			db2.Create()

			// REPLICATION CHOOSE ONLY ONE
			// 1) using _replicate
			// 2) using _replicator

			// replication struct, use headless service name for replication target
			replicator := CouchdbReplicator{Id: "replicate_" + db,
				Continuous: true, Source: db1.URL(),
				Target: "http://" + cluster.Username + ":" + cluster.Password + "@" + podSvcs[j].Spec.ClusterIP + ":" + COUCHDB_PORT_STRING + "/" + db}

			// 1)
			// continuous replication , saves to "_replicate"
			// limits:  anything in _replication is lost when db is restarted

			// DELETE old replication, if any found
			// cannot by done without saving information or without server restart
			// restart server1 and wait until its online, should be fast
			//couch.Do(server1.URL()+"/_restart", METHOD_POST, server1.Cred(), nil, nil)
			//CheckServer(server1, MAX_RETRIES, RETRY_WAIT_TIME)
			// setup replication
			//couch.Do(server1.URL()+"/_replicate", METHOD_POST, server1.Cred(), &replicator, nil)

			// 2)
			// continuous replication via "_replicator"
			// this replication survive restarts but fails replicate database "_users"

			if db == "_users" {
				// there is a bug with _replicator and db _users, we cannot replicate this DB
				continue
			}
			// delete old replication, if any found
			// get old replicator record
			oldReplicator := CouchdbReplicator{}
			couch.Do(server1.URL()+"/_replicator/"+"replicate_"+db, METHOD_GET, server1.Cred(), nil, &oldReplicator)
			//DebugLog(oldReplicator.Rev)
			// if valid replicator record found, delete it
			if oldReplicator.Rev != "" {
				server1.Database("_replicator").Delete("replicate_"+db, oldReplicator.Rev)
			}

			// setup new replication in _replicator db
			couch.Do(server1.URL()+"/_replicator", METHOD_POST, server1.Cred(), &replicator, nil)
		}
	}
	//DebugLog("finished replication configuration")

	// no errors
	return nil
}
예제 #2
0
func server() *couch.Server {
	return couch.NewServer(testHost, testCred)
}