예제 #1
0
func (z *zkCluster) GetQueryNodes() ([]clustering.QueryNode, errors.Error) {
	impl, ok := getConfigStoreImplementation(z)
	if !ok {
		return nil, errors.NewAdminConnectionError(nil, z.ConfigurationStoreId())
	}
	qryNodes := []clustering.QueryNode{}
	nodes, _, err := impl.conn.Children("/" + z.Name())
	if err != nil {
		return nil, errors.NewAdminGetClusterError(err, z.Name())
	}
	for _, name := range nodes {
		nodePath := "/" + z.Name() + "/" + name
		data, _, err := impl.conn.Get(nodePath)
		if err != nil {
			return nil, errors.NewAdminGetNodeError(err, nodePath)
		}
		queryNode := &zkQueryNodeConfig{}
		err = json.Unmarshal(data, queryNode)
		if err != nil {
			return nil, errors.NewAdminDecodingError(err)
		}
		qryNodes = append(qryNodes, queryNode)
	}
	return qryNodes, nil
}
예제 #2
0
func (this *cbCluster) QueryNodeNames() ([]string, errors.Error) {
	queryNodeNames := []string{}
	// Get a handle of the go-couchbase connection:
	cbConn, ok := this.configStore.(*cbConfigStore)
	if !ok {
		return nil, errors.NewAdminConnectionError(nil, this.ConfigurationStoreId())
	}

	pool, poolServices, err := cbConn.getPoolServices(this.ClusterName)
	if err != nil {
		return queryNodeNames, err
	}

	// If pool services rev matches the cluster's rev, return cluster's query node names:
	if poolServices.Rev == this.poolSrvRev {
		return this.queryNodeNames, nil
	}

	// If pool services and cluster rev do not match, update the cluster's rev and query node data:
	queryNodeNames = []string{}
	queryNodes := map[string]services{}
	for _, nodeServices := range poolServices.NodesExt {
		var queryServices services
		for name, protocol := range n1qlProtocols {
			if nodeServices.Services[name] != 0 {
				if queryServices == nil {
					queryServices = services{}
				}
				queryServices[protocol] = nodeServices.Services[name]
			}
		}

		if len(queryServices) == 0 { // no n1ql service at this node
			continue
		}

		hostname := nodeServices.Hostname
		if nodeServices.ThisNode {
			for _, node := range pool.Nodes {
				if node.ThisNode {
					tokens := strings.Split(node.Hostname, ":")
					hostname = tokens[0]
					break
				}
			}
		}
		queryNodeNames = append(queryNodeNames, hostname)
		queryNodes[hostname] = queryServices
	}

	this.Lock()
	defer this.Unlock()
	this.queryNodeNames = queryNodeNames
	this.queryNodes = queryNodes
	this.poolSrvRev = poolServices.Rev
	return this.queryNodeNames, nil
}
예제 #3
0
func (z *zkCluster) RemoveQueryNodeByName(name string) (clustering.QueryNode, errors.Error) {
	impl, ok := getConfigStoreImplementation(z)
	if !ok {
		return nil, errors.NewAdminConnectionError(nil, z.ConfigurationStoreId())
	}
	err := impl.conn.Delete("/"+z.Name()+"/"+name, 0)
	if err != nil {
		return nil, errors.NewAdminRemoveNodeError(err, "/"+z.Name()+"/"+name)
	}
	return nil, nil
}
예제 #4
0
// create a cbConfigStore given the path to a couchbase instance
func NewConfigstore(path string) (clustering.ConfigurationStore, errors.Error) {
	if strings.HasPrefix(path, _PREFIX) {
		path = path[len(_PREFIX):]
	}
	c, err := couchbase.Connect(path)
	if err != nil {
		return nil, errors.NewAdminConnectionError(err, path)
	}
	return &cbConfigStore{
		adminUrl: path,
		cbConn:   &c,
	}, nil
}
예제 #5
0
// create a zkConfigStore given the path to a zookeeper instance
func NewConfigstore(path string) (clustering.ConfigurationStore, errors.Error) {
	if strings.HasPrefix(path, _PREFIX) {
		path = path[len(_PREFIX):]
	}
	zks := strings.Split(path, ",")
	conn, _, err := zk.Connect(zks, time.Second)
	if err != nil {
		return nil, errors.NewAdminConnectionError(err, path)
	}
	return &zkConfigStore{
		conn: conn,
		url:  path,
	}, nil
}
예제 #6
0
func (z *zkCluster) QueryNodeNames() ([]string, errors.Error) {
	queryNodeNames := []string{}
	impl, ok := getConfigStoreImplementation(z)
	if !ok {
		return nil, errors.NewAdminConnectionError(nil, z.ConfigurationStoreId())
	}
	nodes, _, err := impl.conn.Children("/" + z.ClusterName)
	if err != nil {
		return nil, errors.NewAdminGetClusterError(err, z.ClusterName)
	}
	for _, name := range nodes {
		queryNodeNames = append(queryNodeNames, name)
	}
	return queryNodeNames, nil
}
예제 #7
0
func (z *zkCluster) QueryNodeByName(name string) (clustering.QueryNode, errors.Error) {
	impl, ok := getConfigStoreImplementation(z)
	if !ok {
		return nil, errors.NewAdminConnectionError(nil, z.ConfigurationStoreId())
	}
	nodePath := "/" + z.ClusterName + "/" + name
	data, _, err := impl.conn.Get(nodePath)
	if err != nil {
		return nil, errors.NewAdminGetNodeError(err, nodePath)
	}
	var queryNode zkQueryNodeConfig
	err = json.Unmarshal(data, &queryNode)
	if err != nil {
		return nil, errors.NewAdminDecodingError(err)
	}
	return &queryNode, nil
}
예제 #8
0
func (z *zkCluster) AddQueryNode(n clustering.QueryNode) (clustering.QueryNode, errors.Error) {
	impl, ok := getConfigStoreImplementation(z)
	if !ok {
		return nil, errors.NewAdminConnectionError(nil, z.ConfigurationStoreId())
	}
	// Check that query node has compatible backend connections:
	if n.Standalone().Datastore().URL() != z.DatastoreURI {
		return nil, errors.NewWarning(fmt.Sprintf("Failed to add Query Node %v: incompatible datastore with cluster %s", n, z.DatastoreURI))
	}
	if n.Standalone().ConfigurationStore().URL() != z.ConfigstoreURI {
		return nil, errors.NewWarning(fmt.Sprintf("Failed to add Query Node %v: incompatible configstore with cluster %s", n, z.ConfigstoreURI))
	}
	// Check that query node is version compatible with the cluster:
	if !z.Version().Compatible(n.Standalone().Version()) {
		return nil, errors.NewWarning(fmt.Sprintf("Failed to add Query Node %v: not version compatible with cluster (%v)", n, z.Version()))
	}
	qryNodeImpl, ok := n.(*zkQueryNodeConfig)
	if !ok {
		return nil, errors.NewWarning(fmt.Sprintf("Failed to add Query Node %v: cannot set cluster reference", n))
	}
	// The query node can be accepted into the cluster - set its cluster reference and name and unset its Standalone:
	qryNodeImpl.ClusterRef = z
	qryNodeImpl.ClusterName = z.Name()
	qryNodeImpl.StandaloneRef = nil
	// Add entry for query node: ephemeral node
	flags := int32(zk.FlagEphemeral)
	acl := zk.WorldACL(zk.PermAll) // TODO: credentials - expose in the API
	key := "/" + z.Name() + "/" + n.Name()
	value, err := json.Marshal(n)
	if err != nil {
		return nil, errors.NewAdminEncodingError(err)
	}
	_, err = impl.conn.Create(key, value, flags, acl)
	if err != nil {
		return nil, errors.NewAdminAddNodeError(err, "/"+z.Name()+"/"+n.Name())
	}
	return n, nil
}