Search in sources :

Example 36 with ZooKeeperClient

use of com.spotify.helios.servicescommon.coordination.ZooKeeperClient in project helios by spotify.

the class ZooKeeperMasterModel method updateDeployment.

/**
 * Used to update the existing deployment of a job.
 */
@Override
public void updateDeployment(final String host, final Deployment deployment, final String token) throws HostNotFoundException, JobNotDeployedException, TokenVerificationException {
    log.info("updating deployment {}: {}", deployment, host);
    final ZooKeeperClient client = provider.get("updateDeployment");
    final JobId jobId = deployment.getJobId();
    final Job job = getJob(client, jobId);
    final Deployment existingDeployment = getDeployment(host, jobId);
    if (job == null) {
        throw new JobNotDeployedException(host, jobId);
    }
    verifyToken(token, job);
    assertHostExists(client, host);
    assertTaskExists(client, host, deployment.getJobId());
    final String path = Paths.configHostJob(host, jobId);
    final Task task = new Task(job, deployment.getGoal(), existingDeployment.getDeployerUser(), existingDeployment.getDeployerMaster(), existingDeployment.getDeploymentGroupName());
    try {
        client.setData(path, task.toJsonBytes());
    } catch (Exception e) {
        throw new HeliosRuntimeException("updating deployment " + deployment + " on host " + host + " failed", e);
    }
}
Also used : Task(com.spotify.helios.common.descriptors.Task) RolloutTask(com.spotify.helios.common.descriptors.RolloutTask) ZooKeeperClient(com.spotify.helios.servicescommon.coordination.ZooKeeperClient) HeliosRuntimeException(com.spotify.helios.common.HeliosRuntimeException) Deployment(com.spotify.helios.common.descriptors.Deployment) Job(com.spotify.helios.common.descriptors.Job) JobId(com.spotify.helios.common.descriptors.JobId) HeliosRuntimeException(com.spotify.helios.common.HeliosRuntimeException) JsonParseException(com.fasterxml.jackson.core.JsonParseException) NotEmptyException(org.apache.zookeeper.KeeperException.NotEmptyException) JsonMappingException(com.fasterxml.jackson.databind.JsonMappingException) BadVersionException(org.apache.zookeeper.KeeperException.BadVersionException) KeeperException(org.apache.zookeeper.KeeperException) IOException(java.io.IOException) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) NodeExistsException(org.apache.zookeeper.KeeperException.NodeExistsException)

Example 37 with ZooKeeperClient

use of com.spotify.helios.servicescommon.coordination.ZooKeeperClient in project helios by spotify.

the class ZooKeeperMasterModel method stopDeploymentGroup.

@Override
public void stopDeploymentGroup(final String deploymentGroupName) throws DeploymentGroupDoesNotExistException {
    checkNotNull(deploymentGroupName, "name");
    log.info("stop deployment-group: name={}", deploymentGroupName);
    final ZooKeeperClient client = provider.get("stopDeploymentGroup");
    // Delete deployment group tasks (if any) and set DG state to FAILED
    final DeploymentGroupStatus status = DeploymentGroupStatus.newBuilder().setState(FAILED).setError("Stopped by user").build();
    final String statusPath = Paths.statusDeploymentGroup(deploymentGroupName);
    final String tasksPath = Paths.statusDeploymentGroupTasks(deploymentGroupName);
    try {
        client.ensurePath(Paths.statusDeploymentGroupTasks());
        final List<ZooKeeperOperation> operations = Lists.newArrayList();
        // NOTE: This remove operation is racey. If tasks exist and the rollout finishes before the
        // delete() is executed then this will fail. Conversely, if it doesn't exist but is created
        // before the transaction is executed it will also fail. This is annoying for users, but at
        // least means we won't have inconsistent state.
        // 
        // That the set() is first in the list of operations is important because of the
        // kludgy error checking we do below to disambiguate "doesn't exist" failures from the race
        // condition mentioned below.
        operations.add(set(statusPath, status));
        final Stat tasksStat = client.exists(tasksPath);
        if (tasksStat != null) {
            operations.add(delete(tasksPath));
        } else {
            // There doesn't seem to be a "check that node doesn't exist" operation so we
            // do a create and a delete on the same path to emulate it.
            operations.add(create(tasksPath));
            operations.add(delete(tasksPath));
        }
        client.transaction(operations);
    } catch (final NoNodeException e) {
        // Yes, the way you figure out which operation in a transaction failed is retarded.
        if (((OpResult.ErrorResult) e.getResults().get(0)).getErr() == KeeperException.Code.NONODE.intValue()) {
            throw new DeploymentGroupDoesNotExistException(deploymentGroupName);
        } else {
            throw new HeliosRuntimeException("stop deployment-group " + deploymentGroupName + " failed due to a race condition, please retry", e);
        }
    } catch (final KeeperException e) {
        throw new HeliosRuntimeException("stop deployment-group " + deploymentGroupName + " failed", e);
    }
}
Also used : Stat(org.apache.zookeeper.data.Stat) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) ZooKeeperClient(com.spotify.helios.servicescommon.coordination.ZooKeeperClient) ZooKeeperOperation(com.spotify.helios.servicescommon.coordination.ZooKeeperOperation) HeliosRuntimeException(com.spotify.helios.common.HeliosRuntimeException) DeploymentGroupStatus(com.spotify.helios.common.descriptors.DeploymentGroupStatus) KeeperException(org.apache.zookeeper.KeeperException)

Example 38 with ZooKeeperClient

use of com.spotify.helios.servicescommon.coordination.ZooKeeperClient in project helios by spotify.

the class ZooKeeperMasterModel method getJobs.

/**
 * Returns a {@link Map} of {@link JobId} to {@link Job} objects for all of the jobs known.
 */
@Override
public Map<JobId, Job> getJobs() {
    log.debug("getting jobs");
    final String folder = Paths.configJobs();
    final ZooKeeperClient client = provider.get("getJobs");
    try {
        final List<String> ids;
        try {
            ids = client.getChildren(folder);
        } catch (NoNodeException e) {
            return Maps.newHashMap();
        }
        final Map<JobId, Job> descriptors = Maps.newHashMap();
        for (final String id : ids) {
            final JobId jobId = JobId.fromString(id);
            final String path = Paths.configJob(jobId);
            try {
                final byte[] data = client.getData(path);
                final Job descriptor = parse(data, Job.class);
                descriptors.put(descriptor.getId(), descriptor);
            } catch (NoNodeException e) {
                // Ignore, the job was deleted before we had a chance to read it.
                log.debug("Ignoring deleted job {}", jobId);
            }
        }
        return descriptors;
    } catch (KeeperException | IOException e) {
        throw new HeliosRuntimeException("getting jobs failed", e);
    }
}
Also used : NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) ZooKeeperClient(com.spotify.helios.servicescommon.coordination.ZooKeeperClient) HeliosRuntimeException(com.spotify.helios.common.HeliosRuntimeException) IOException(java.io.IOException) Job(com.spotify.helios.common.descriptors.Job) JobId(com.spotify.helios.common.descriptors.JobId) KeeperException(org.apache.zookeeper.KeeperException)

Example 39 with ZooKeeperClient

use of com.spotify.helios.servicescommon.coordination.ZooKeeperClient in project helios by spotify.

the class ZooKeeperMasterModel method addDeploymentGroup.

/**
 * Create a deployment group.
 *
 * <p>If successful, the following ZK nodes will be created:
 * <ul>
 * <li>/config/deployment-groups/[group-name]</li>
 * <li>/status/deployment-groups/[group-name]</li>
 * <li>/status/deployment-groups/[group-name]/hosts</li>
 * </ul>
 * These nodes are guaranteed to exist until the DG is removed.
 *
 * <p>If the operation fails no ZK nodes will be created. If any of the nodes above already exist
 * the operation will fail.
 *
 * @throws DeploymentGroupExistsException If a DG with the same name already exists.
 */
@Override
public void addDeploymentGroup(final DeploymentGroup deploymentGroup) throws DeploymentGroupExistsException {
    log.info("adding deployment-group: {}", deploymentGroup);
    final ZooKeeperClient client = provider.get("addDeploymentGroup");
    try {
        try {
            client.ensurePath(Paths.configDeploymentGroups());
            client.ensurePath(Paths.statusDeploymentGroups());
            client.transaction(create(Paths.configDeploymentGroup(deploymentGroup.getName()), deploymentGroup), create(Paths.statusDeploymentGroup(deploymentGroup.getName())), create(Paths.statusDeploymentGroupHosts(deploymentGroup.getName()), Json.asBytesUnchecked(emptyList())), create(Paths.statusDeploymentGroupRemovedHosts(deploymentGroup.getName()), Json.asBytesUnchecked(emptyList())));
        } catch (final NodeExistsException e) {
            throw new DeploymentGroupExistsException(deploymentGroup.getName());
        }
    } catch (final KeeperException e) {
        throw new HeliosRuntimeException("adding deployment-group " + deploymentGroup + " failed", e);
    }
}
Also used : ZooKeeperClient(com.spotify.helios.servicescommon.coordination.ZooKeeperClient) NodeExistsException(org.apache.zookeeper.KeeperException.NodeExistsException) HeliosRuntimeException(com.spotify.helios.common.HeliosRuntimeException) KeeperException(org.apache.zookeeper.KeeperException)

Example 40 with ZooKeeperClient

use of com.spotify.helios.servicescommon.coordination.ZooKeeperClient in project helios by spotify.

the class ZooKeeperMasterModel method getDeploymentGroupHosts.

@Override
public List<String> getDeploymentGroupHosts(final String name) throws DeploymentGroupDoesNotExistException {
    log.debug("getting deployment group hosts: {}", name);
    final ZooKeeperClient client = provider.get("getDeploymentGroupHosts");
    final DeploymentGroup deploymentGroup = getDeploymentGroup(client, name);
    if (deploymentGroup == null) {
        throw new DeploymentGroupDoesNotExistException(name);
    }
    return getHosts(client, Paths.statusDeploymentGroupHosts(name));
}
Also used : ZooKeeperClient(com.spotify.helios.servicescommon.coordination.ZooKeeperClient) DeploymentGroup(com.spotify.helios.common.descriptors.DeploymentGroup)

Aggregations

ZooKeeperClient (com.spotify.helios.servicescommon.coordination.ZooKeeperClient)43 HeliosRuntimeException (com.spotify.helios.common.HeliosRuntimeException)20 KeeperException (org.apache.zookeeper.KeeperException)18 NoNodeException (org.apache.zookeeper.KeeperException.NoNodeException)15 DefaultZooKeeperClient (com.spotify.helios.servicescommon.coordination.DefaultZooKeeperClient)13 Job (com.spotify.helios.common.descriptors.Job)12 Test (org.junit.Test)12 DeploymentGroup (com.spotify.helios.common.descriptors.DeploymentGroup)11 ZooKeeperOperation (com.spotify.helios.servicescommon.coordination.ZooKeeperOperation)11 IOException (java.io.IOException)10 RolloutTask (com.spotify.helios.common.descriptors.RolloutTask)8 DeploymentGroupTasks (com.spotify.helios.common.descriptors.DeploymentGroupTasks)6 JobId (com.spotify.helios.common.descriptors.JobId)6 Deployment (com.spotify.helios.common.descriptors.Deployment)5 CuratorFramework (org.apache.curator.framework.CuratorFramework)5 ExponentialBackoffRetry (org.apache.curator.retry.ExponentialBackoffRetry)5 DeploymentGroupStatus (com.spotify.helios.common.descriptors.DeploymentGroupStatus)4 SetData (com.spotify.helios.servicescommon.coordination.SetData)4 RetryPolicy (org.apache.curator.RetryPolicy)4 BadVersionException (org.apache.zookeeper.KeeperException.BadVersionException)4