// addInstance creates a new service state and host instance func addInstance(conn client.Connection, state ss.ServiceState) error { glog.V(2).Infof("Adding instance %+v", state) // check the object if err := state.ValidEntity(); err != nil { glog.Errorf("Could not validate service state %+v: %s", state, err) return err } // CC-1050: we need to trigger the scheduler in case we only have a // partial create. svclock := newStateLock(conn, state.ServiceID) if err := svclock.Lock(); err != nil { glog.Errorf("Could not set lock on service %s: %s", state.ServiceID, err) return err } defer svclock.Unlock() lock := newInstanceLock(conn, state.ID) if err := lock.Lock(); err != nil { glog.Errorf("Could not set lock for service instance %s for service %s on host %s: %s", state.ID, state.ServiceID, state.HostID, err) return err } glog.V(2).Infof("Acquired lock for instance %s", state.ID) defer lock.Unlock() var err error defer func() { if err != nil { conn.Delete(hostpath(state.HostID, state.ID)) conn.Delete(servicepath(state.ServiceID, state.ID)) rmInstanceLock(conn, state.ID) } }() // Create node on the service spath := servicepath(state.ServiceID, state.ID) snode := &ServiceStateNode{ServiceState: &state} if err = conn.Create(spath, snode); err != nil { glog.Errorf("Could not create service state %s for service %s: %s", state.ID, state.ServiceID, err) return err } else if err = conn.Set(spath, snode); err != nil { glog.Errorf("Could not set service state %s for node %+v: %s", state.ID, snode, err) return err } // Create node on the host hpath := hostpath(state.HostID, state.ID) hnode := NewHostState(&state) glog.V(2).Infof("Host node: %+v", hnode) if err = conn.Create(hpath, hnode); err != nil { glog.Errorf("Could not create host state %s for host %s: %s", state.ID, state.HostID, err) return err } else if err = conn.Set(hpath, hnode); err != nil { glog.Errorf("Could not set host state %s for node %+v: %s", state.ID, hnode, err) return err } glog.V(2).Infof("Releasing lock for instance %s", state.ID) return nil }
//Set node to the key in registry. Returns the path of the node in the registry func (r *registryType) setItem(conn client.Connection, key string, nodeID string, node client.Node) (string, error) { if err := r.ensureKey(conn, key); err != nil { return "", err } //TODO: make ephemeral path := r.getPath(key, nodeID) exists, err := zzk.PathExists(conn, path) if err != nil { return "", err } if exists { glog.V(3).Infof("Set to %s: %#v", path, node) epn := EndpointNode{} if err := conn.Get(path, &epn); err != nil { return "", err } node.SetVersion(epn.Version()) if err := conn.Set(path, node); err != nil { return "", err } } else { if addPath, err := r.addItem(conn, key, nodeID, node); err != nil { return "", err } else { path = addPath } glog.V(3).Infof("Add to %s: %#v", path, node) } return path, nil }
func UpdateResourcePool(conn client.Connection, pool *pool.ResourcePool) error { var node PoolNode if err := conn.Get(poolpath(pool.ID), &node); err != nil { return err } node.ResourcePool = pool return conn.Set(poolpath(pool.ID), &node) }
func AddVirtualIP(conn client.Connection, virtualIP *pool.VirtualIP) error { var node VirtualIPNode path := vippath(virtualIP.IP) glog.V(1).Infof("Adding virtual ip to zookeeper: %s", path) if err := conn.Create(path, &node); err != nil { return err } node.VirtualIP = virtualIP return conn.Set(path, &node) }
// StopService schedules a service to stop func StopService(conn client.Connection, serviceID string) error { glog.Infof("Scheduling service %s to stop", serviceID) var node ServiceNode path := servicepath(serviceID) if err := conn.Get(path, &node); err != nil { return err } node.Service.DesiredState = int(service.SVCStop) return conn.Set(path, &node) }
// SendAction sends an action request to a particular host func SendAction(conn client.Connection, action *Action) (string, error) { uuid, err := utils.NewUUID() if err != nil { return "", err } node := actionPath(action.HostID, uuid) if err := conn.Create(node, action); err != nil { return "", err } else if err := conn.Set(node, action); err != nil { return "", err } return uuid, nil }
// UpdateService updates a service node if it exists, otherwise creates it func UpdateService(conn client.Connection, svc *service.Service) error { var node ServiceNode spath := servicepath(svc.ID) // For some reason you can't just create the node with the service data // already set. Trust me, I tried. It was very aggravating. if err := conn.Get(spath, &node); err != nil { if err := conn.Create(spath, &node); err != nil { glog.Errorf("Error trying to create node at %s: %s", spath, err) } } node.Service = svc return conn.Set(spath, &node) }
// UpdateServiceVhost updates a service vhost node if it exists, otherwise creates it func UpdateServiceVhost(conn client.Connection, serviceID, vhostname string) error { glog.V(2).Infof("UpdateServiceVhost serviceID:%s vhostname:%s", serviceID, vhostname) var node ServiceVhostNode spath := servicevhostpath(serviceID, vhostname) // For some reason you can't just create the node with the service data // already set. Trust me, I tried. It was very aggravating. if err := conn.Get(spath, &node); err != nil { if err := conn.Create(spath, &node); err != nil { glog.Errorf("Error trying to create node at %s: %s", spath, err) } } node.ServiceID = serviceID node.Vhost = vhostname glog.V(2).Infof("Adding service vhost at path:%s %+v", spath, node) return conn.Set(spath, &node) }
// updateInstance updates the service state and host instances func updateInstance(conn client.Connection, hostID, stateID string, mutate func(*HostState, *ss.ServiceState)) error { glog.V(2).Infof("Updating instance %s", stateID) // do not lock if parent lock does not exist if exists, err := conn.Exists(path.Join(zkInstanceLock, stateID)); err != nil && err != client.ErrNoNode { glog.Errorf("Could not check for lock on instance %s: %s", stateID, err) return err } else if !exists { glog.Errorf("Lock not found for instance %s", stateID) return ErrLockNotFound } lock := newInstanceLock(conn, stateID) if err := lock.Lock(); err != nil { glog.Errorf("Could not set lock for service instance %s on host %s: %s", stateID, hostID, err) return err } defer lock.Unlock() glog.V(2).Infof("Acquired lock for instance %s", stateID) hpath := hostpath(hostID, stateID) var hsdata HostState if err := conn.Get(hpath, &hsdata); err != nil { glog.Errorf("Could not get instance %s for host %s: %s", stateID, hostID, err) return err } serviceID := hsdata.ServiceID spath := servicepath(serviceID, stateID) var ssnode ServiceStateNode if err := conn.Get(spath, &ssnode); err != nil { glog.Errorf("Could not get instance %s for service %s: %s", stateID, serviceID, err) return err } mutate(&hsdata, ssnode.ServiceState) if err := conn.Set(hpath, &hsdata); err != nil { glog.Errorf("Could not update instance %s for host %s: %s", stateID, hostID, err) return err } if err := conn.Set(spath, &ssnode); err != nil { glog.Errorf("Could not update instance %s for service %s: %s", stateID, serviceID, err) return err } glog.V(2).Infof("Releasing lock for instance %s", stateID) return nil }