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 }
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 }
// 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 }
// 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 }
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 }
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 }
func (c *cbCluster) QueryNodeNames() ([]string, errors.Error) { queryNodeNames := []string{} // Get a handle of the go-couchbase connection: cbConn, ok := c.configStore.(*cbConfigStore) if !ok { return nil, errors.NewAdminConnectionError(nil, c.ConfigurationStoreId()) } poolServices, err := cbConn.getPoolServices(c.ClusterName) if err != nil { return queryNodeNames, err } // If the go-couchbase pool services rev matches the cluster's rev, return cluster's query node names: if poolServices.Rev == c.poolSrvRev { return c.queryNodeNames, nil } // If the rev numbers do not match, update the cluster's rev and query node data: queryNodeNames = []string{} queryNodes := make(map[string]int) for _, ns := range poolServices.NodesExt { n1qlPort := ns.Services["n1ql"] hostname := ns.Hostname if n1qlPort == 0 { // no n1ql service in this node continue } // TODO: check ns.ThisNode also if hostname == "" { hostname, _ = getHostnameFromURI(c.configStore.URL()) } queryNodeNames = append(queryNodeNames, hostname) queryNodes[hostname] = n1qlPort } c.Lock() defer c.Unlock() c.queryNodeNames = queryNodeNames c.queryNodes = queryNodes c.poolSrvRev = poolServices.Rev return c.queryNodeNames, nil }
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 }