Search in sources :

Example 6 with RolloutTask

use of com.spotify.helios.common.descriptors.RolloutTask in project helios by spotify.

the class ZooKeeperMasterModel method rollingUpdateStep.

@Override
public void rollingUpdateStep() {
    final ZooKeeperClient client = provider.get("rollingUpdateStep");
    final Map<String, VersionedValue<DeploymentGroupTasks>> tasksMap = getDeploymentGroupTasks(client);
    for (final Map.Entry<String, VersionedValue<DeploymentGroupTasks>> entry : tasksMap.entrySet()) {
        final String deploymentGroupName = entry.getKey();
        final VersionedValue<DeploymentGroupTasks> versionedTasks = entry.getValue();
        final DeploymentGroupTasks tasks = versionedTasks.value();
        final int taskIndex = tasks.getTaskIndex();
        log.info("rolling-update step on deployment-group {}. Doing taskIndex {} of {}: {}. ", deploymentGroupName, taskIndex, tasks.getRolloutTasks().size(), tasks.getRolloutTasks().get(taskIndex));
        try {
            final RollingUpdateOpFactory opFactory = new RollingUpdateOpFactory(tasks, DEPLOYMENT_GROUP_EVENT_FACTORY);
            final RolloutTask task = tasks.getRolloutTasks().get(taskIndex);
            final RollingUpdateOp op = processRollingUpdateTask(client, opFactory, task, tasks.getDeploymentGroup());
            if (!op.operations().isEmpty()) {
                final List<ZooKeeperOperation> ops = Lists.newArrayList();
                ops.add(check(Paths.statusDeploymentGroupTasks(deploymentGroupName), versionedTasks.version()));
                ops.addAll(op.operations());
                log.info("rolling-update step on deployment-group: name={}, zookeeper operations={}", deploymentGroupName, ops);
                try {
                    client.transaction(ops);
                    emitEvents(deploymentGroupEventTopic, op.events());
                } catch (BadVersionException e) {
                    // some other master beat us in processing this rolling update step. not exceptional.
                    // ideally we would check the path in the exception, but curator doesn't provide a path
                    // for exceptions thrown as part of a transaction.
                    log.info("rolling-update step on deployment-group was processed by another master" + ": name={}, zookeeper operations={}", deploymentGroupName, ops);
                } catch (KeeperException e) {
                    log.error("rolling-update on deployment-group {} failed", deploymentGroupName, e);
                }
            }
        } catch (final Exception e) {
            log.error("error processing rolling update step for {}", deploymentGroupName, e);
        }
    }
}
Also used : VersionedValue(com.spotify.helios.servicescommon.VersionedValue) ZooKeeperOperation(com.spotify.helios.servicescommon.coordination.ZooKeeperOperation) DeploymentGroupTasks(com.spotify.helios.common.descriptors.DeploymentGroupTasks) RolloutTask(com.spotify.helios.common.descriptors.RolloutTask) BadVersionException(org.apache.zookeeper.KeeperException.BadVersionException) 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) RollingUpdateOpFactory(com.spotify.helios.rollingupdate.RollingUpdateOpFactory) RollingUpdateOp(com.spotify.helios.rollingupdate.RollingUpdateOp) ZooKeeperClient(com.spotify.helios.servicescommon.coordination.ZooKeeperClient) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) Collections.emptyMap(java.util.Collections.emptyMap) KeeperException(org.apache.zookeeper.KeeperException)

Example 7 with RolloutTask

use of com.spotify.helios.common.descriptors.RolloutTask in project helios by spotify.

the class RollingUpdateOpFactory method start.

public RollingUpdateOp start(final DeploymentGroup deploymentGroup, final ZooKeeperClient client) throws KeeperException {
    client.ensurePath(Paths.statusDeploymentGroupTasks());
    final List<ZooKeeperOperation> ops = Lists.newArrayList();
    final List<Map<String, Object>> events = Lists.newArrayList();
    final List<RolloutTask> rolloutTasks = tasks.getRolloutTasks();
    events.add(eventFactory.rollingUpdateStarted(deploymentGroup));
    final Stat tasksStat = client.exists(Paths.statusDeploymentGroupTasks(deploymentGroup.getName()));
    if (tasksStat == null) {
        // Create the tasks path if it doesn't already exist. The following operations (delete or set)
        // assume the node already exists. If the tasks path is created/deleted before the transaction
        // is committed it will fail. This will on occasion generate a user-visible error but is
        // better than having inconsistent state.
        ops.add(create(Paths.statusDeploymentGroupTasks(deploymentGroup.getName())));
    }
    final DeploymentGroupStatus status;
    if (rolloutTasks.isEmpty()) {
        status = DeploymentGroupStatus.newBuilder().setState(DONE).build();
        ops.add(delete(Paths.statusDeploymentGroupTasks(deploymentGroup.getName())));
        events.add(eventFactory.rollingUpdateDone(deploymentGroup));
    } else {
        final DeploymentGroupTasks tasks = DeploymentGroupTasks.newBuilder().setRolloutTasks(rolloutTasks).setTaskIndex(0).setDeploymentGroup(deploymentGroup).build();
        status = DeploymentGroupStatus.newBuilder().setState(ROLLING_OUT).build();
        ops.add(set(Paths.statusDeploymentGroupTasks(deploymentGroup.getName()), tasks));
    }
    // NOTE: If the DG was removed this set() cause the transaction to fail, because removing
    // the DG removes this node. It's *important* that there's an operation that causes the
    // transaction to fail if the DG was removed or we'll end up with inconsistent state.
    ops.add(set(Paths.statusDeploymentGroup(deploymentGroup.getName()), status));
    return new RollingUpdateOp(ImmutableList.copyOf(ops), ImmutableList.copyOf(events));
}
Also used : Stat(org.apache.zookeeper.data.Stat) ZooKeeperOperation(com.spotify.helios.servicescommon.coordination.ZooKeeperOperation) DeploymentGroupTasks(com.spotify.helios.common.descriptors.DeploymentGroupTasks) RolloutTask(com.spotify.helios.common.descriptors.RolloutTask) DeploymentGroupStatus(com.spotify.helios.common.descriptors.DeploymentGroupStatus) Map(java.util.Map)

Example 8 with RolloutTask

use of com.spotify.helios.common.descriptors.RolloutTask in project helios by spotify.

the class RollingUpdateOpFactory method nextTask.

public RollingUpdateOp nextTask(final List<ZooKeeperOperation> operations) {
    final List<ZooKeeperOperation> ops = Lists.newArrayList(operations);
    final List<Map<String, Object>> events = Lists.newArrayList();
    final RolloutTask task = tasks.getRolloutTasks().get(tasks.getTaskIndex());
    // Update the task index, delete tasks if done
    if (tasks.getTaskIndex() + 1 == tasks.getRolloutTasks().size()) {
        final DeploymentGroupStatus status = DeploymentGroupStatus.newBuilder().setState(DONE).build();
        // We are done -> delete tasks & update status
        ops.add(delete(Paths.statusDeploymentGroupTasks(deploymentGroup.getName())));
        ops.add(set(Paths.statusDeploymentGroup(deploymentGroup.getName()), status));
        // Emit an event signalling that we're DONE!
        events.add(eventFactory.rollingUpdateDone(deploymentGroup));
    } else {
        ops.add(set(Paths.statusDeploymentGroupTasks(deploymentGroup.getName()), tasks.toBuilder().setTaskIndex(tasks.getTaskIndex() + 1).build()));
        // the task was effectively a no-op.
        if (!operations.isEmpty()) {
            events.add(eventFactory.rollingUpdateTaskSucceeded(deploymentGroup, task));
        }
    }
    return new RollingUpdateOp(ImmutableList.copyOf(ops), ImmutableList.copyOf(events));
}
Also used : ZooKeeperOperation(com.spotify.helios.servicescommon.coordination.ZooKeeperOperation) RolloutTask(com.spotify.helios.common.descriptors.RolloutTask) DeploymentGroupStatus(com.spotify.helios.common.descriptors.DeploymentGroupStatus) Map(java.util.Map)

Example 9 with RolloutTask

use of com.spotify.helios.common.descriptors.RolloutTask in project helios by spotify.

the class ZooKeeperMasterModel method getInitRollingUpdateOps.

private RollingUpdateOp getInitRollingUpdateOps(final DeploymentGroup deploymentGroup, final List<String> updateHosts, final List<String> undeployHosts, final ZooKeeperClient zooKeeperClient) throws KeeperException {
    final List<RolloutTask> rolloutTasks = new ArrayList<>();
    // give precedence to the updateHosts list so we don't end up in a state where we updated a host
    // and then removed the job from it (because of buggy logic in the calling method)
    final List<String> updateHostsCopy = new ArrayList<>(updateHosts);
    final List<String> undeployHostsCopy = new ArrayList<>(undeployHosts);
    undeployHostsCopy.removeAll(updateHostsCopy);
    // we only care about hosts that are UP
    final List<String> upHostsToUndeploy = undeployHostsCopy.stream().filter(host -> checkHostUp(zooKeeperClient, host)).collect(Collectors.toList());
    final List<String> upHostsToDeploy = updateHostsCopy.stream().filter(host -> checkHostUp(zooKeeperClient, host)).collect(Collectors.toList());
    rolloutTasks.addAll(RollingUndeployPlanner.of(deploymentGroup).plan(upHostsToUndeploy));
    rolloutTasks.addAll(RollingUpdatePlanner.of(deploymentGroup).plan(upHostsToDeploy));
    log.info("generated rolloutTasks for deployment-group name={} " + "updateHosts={} undeployHosts={}: {}", deploymentGroup.getName(), updateHosts, undeployHosts, rolloutTasks);
    final DeploymentGroupTasks tasks = DeploymentGroupTasks.newBuilder().setRolloutTasks(rolloutTasks).setTaskIndex(0).setDeploymentGroup(deploymentGroup).build();
    return new RollingUpdateOpFactory(tasks, DEPLOYMENT_GROUP_EVENT_FACTORY).start(deploymentGroup, zooKeeperClient);
}
Also used : Descriptor.parse(com.spotify.helios.common.descriptors.Descriptor.parse) HeliosRuntimeException(com.spotify.helios.common.HeliosRuntimeException) ZooKeeperClient(com.spotify.helios.servicescommon.coordination.ZooKeeperClient) LoggerFactory(org.slf4j.LoggerFactory) Stat(org.apache.zookeeper.data.Stat) ThrottleState(com.spotify.helios.common.descriptors.ThrottleState) FAILED(com.spotify.helios.common.descriptors.DeploymentGroupStatus.State.FAILED) ZooKeeperOperations.create(com.spotify.helios.servicescommon.coordination.ZooKeeperOperations.create) Collections.singletonList(java.util.Collections.singletonList) Optional.fromNullable(com.google.common.base.Optional.fromNullable) Json(com.spotify.helios.common.Json) RolloutOptions(com.spotify.helios.common.descriptors.RolloutOptions) RollingUndeployPlanner(com.spotify.helios.rollingupdate.RollingUndeployPlanner) ZooKeeperOperations.set(com.spotify.helios.servicescommon.coordination.ZooKeeperOperations.set) VersionedValue(com.spotify.helios.servicescommon.VersionedValue) Map(java.util.Map) Deployment(com.spotify.helios.common.descriptors.Deployment) TypeReference(com.fasterxml.jackson.core.type.TypeReference) JsonParseException(com.fasterxml.jackson.core.JsonParseException) HostInfo(com.spotify.helios.common.descriptors.HostInfo) Function(com.google.common.base.Function) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Collections.emptyList(java.util.Collections.emptyList) DeploymentGroup(com.spotify.helios.common.descriptors.DeploymentGroup) EventSender(com.spotify.helios.servicescommon.EventSender) Set(java.util.Set) PortMapping(com.spotify.helios.common.descriptors.PortMapping) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) RollingUpdateOp(com.spotify.helios.rollingupdate.RollingUpdateOp) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Objects(java.util.Objects) Nullable(org.jetbrains.annotations.Nullable) HOSTS_CHANGED(com.spotify.helios.common.descriptors.DeploymentGroup.RollingUpdateReason.HOSTS_CHANGED) TaskStatusEvent(com.spotify.helios.common.descriptors.TaskStatusEvent) List(java.util.List) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) NotEmptyException(org.apache.zookeeper.KeeperException.NotEmptyException) MANUAL(com.spotify.helios.common.descriptors.DeploymentGroup.RollingUpdateReason.MANUAL) UP(com.spotify.helios.common.descriptors.HostStatus.Status.UP) JsonMappingException(com.fasterxml.jackson.databind.JsonMappingException) RollingUpdateOpFactory(com.spotify.helios.rollingupdate.RollingUpdateOpFactory) Lists.reverse(com.google.common.collect.Lists.reverse) RollingUpdatePlanner(com.spotify.helios.rollingupdate.RollingUpdatePlanner) ZooKeeperOperations.delete(com.spotify.helios.servicescommon.coordination.ZooKeeperOperations.delete) Joiner(com.google.common.base.Joiner) JobId(com.spotify.helios.common.descriptors.JobId) RollingUpdateError(com.spotify.helios.rollingupdate.RollingUpdateError) Goal(com.spotify.helios.common.descriptors.Goal) Strings.isNullOrEmpty(com.google.common.base.Strings.isNullOrEmpty) Paths(com.spotify.helios.servicescommon.coordination.Paths) ZooKeeperRegistrarUtil(com.spotify.helios.servicescommon.ZooKeeperRegistrarUtil) ArrayList(java.util.ArrayList) ROLLING_OUT(com.spotify.helios.common.descriptors.DeploymentGroupStatus.State.ROLLING_OUT) Strings(com.google.common.base.Strings) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) DeploymentGroupTasks(com.spotify.helios.common.descriptors.DeploymentGroupTasks) HostStatus(com.spotify.helios.common.descriptors.HostStatus) DOWN(com.spotify.helios.common.descriptors.HostStatus.Status.DOWN) OpResult(org.apache.zookeeper.OpResult) Task(com.spotify.helios.common.descriptors.Task) TaskStatus(com.spotify.helios.common.descriptors.TaskStatus) BadVersionException(org.apache.zookeeper.KeeperException.BadVersionException) Collections.emptyMap(java.util.Collections.emptyMap) Logger(org.slf4j.Logger) Job(com.spotify.helios.common.descriptors.Job) KeeperException(org.apache.zookeeper.KeeperException) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) MoreObjects(com.google.common.base.MoreObjects) Throwables(com.google.common.base.Throwables) IOException(java.io.IOException) ZooKeeperOperation(com.spotify.helios.servicescommon.coordination.ZooKeeperOperation) Maps(com.google.common.collect.Maps) DeploymentGroupEventFactory(com.spotify.helios.rollingupdate.DeploymentGroupEventFactory) RolloutTask(com.spotify.helios.common.descriptors.RolloutTask) Node(com.spotify.helios.servicescommon.coordination.Node) Ordering(com.google.common.collect.Ordering) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) JobStatus(com.spotify.helios.common.descriptors.JobStatus) ZooKeeperClientProvider(com.spotify.helios.servicescommon.coordination.ZooKeeperClientProvider) DeploymentGroupStatus(com.spotify.helios.common.descriptors.DeploymentGroupStatus) ZooKeeperOperations.check(com.spotify.helios.servicescommon.coordination.ZooKeeperOperations.check) Preconditions(com.google.common.base.Preconditions) AgentInfo(com.spotify.helios.common.descriptors.AgentInfo) Comparator(java.util.Comparator) NodeExistsException(org.apache.zookeeper.KeeperException.NodeExistsException) Collections(java.util.Collections) Lists.newArrayList(com.google.common.collect.Lists.newArrayList) ArrayList(java.util.ArrayList) DeploymentGroupTasks(com.spotify.helios.common.descriptors.DeploymentGroupTasks) RolloutTask(com.spotify.helios.common.descriptors.RolloutTask) RollingUpdateOpFactory(com.spotify.helios.rollingupdate.RollingUpdateOpFactory)

Example 10 with RolloutTask

use of com.spotify.helios.common.descriptors.RolloutTask in project helios by spotify.

the class RollingUpdateOpFactory method error.

public RollingUpdateOp error(final String msg, final String host, final RollingUpdateError errorCode, final Map<String, Object> metadata) {
    final List<ZooKeeperOperation> operations = Lists.newArrayList();
    final String errMsg = isNullOrEmpty(host) ? msg : host + ": " + msg;
    final DeploymentGroupStatus status = DeploymentGroupStatus.newBuilder().setState(FAILED).setError(errMsg).build();
    // Delete tasks, set state to FAILED
    operations.add(delete(Paths.statusDeploymentGroupTasks(deploymentGroup.getName())));
    operations.add(set(Paths.statusDeploymentGroup(deploymentGroup.getName()), status));
    final RolloutTask task = tasks.getRolloutTasks().get(tasks.getTaskIndex());
    // Emit a FAILED event and a failed task event
    final List<Map<String, Object>> events = Lists.newArrayList();
    final Map<String, Object> taskEv = eventFactory.rollingUpdateTaskFailed(deploymentGroup, task, errMsg, errorCode, metadata);
    events.add(taskEv);
    events.add(eventFactory.rollingUpdateFailed(deploymentGroup, taskEv));
    return new RollingUpdateOp(ImmutableList.copyOf(operations), ImmutableList.copyOf(events));
}
Also used : ZooKeeperOperation(com.spotify.helios.servicescommon.coordination.ZooKeeperOperation) DeploymentGroupStatus(com.spotify.helios.common.descriptors.DeploymentGroupStatus) RolloutTask(com.spotify.helios.common.descriptors.RolloutTask) Map(java.util.Map)

Aggregations

RolloutTask (com.spotify.helios.common.descriptors.RolloutTask)16 Test (org.junit.Test)11 DeploymentGroup (com.spotify.helios.common.descriptors.DeploymentGroup)10 ZooKeeperOperation (com.spotify.helios.servicescommon.coordination.ZooKeeperOperation)6 DeploymentGroupTasks (com.spotify.helios.common.descriptors.DeploymentGroupTasks)5 ZooKeeperClient (com.spotify.helios.servicescommon.coordination.ZooKeeperClient)5 Map (java.util.Map)5 DeploymentGroupStatus (com.spotify.helios.common.descriptors.DeploymentGroupStatus)4 JsonParseException (com.fasterxml.jackson.core.JsonParseException)2 JsonMappingException (com.fasterxml.jackson.databind.JsonMappingException)2 ImmutableMap (com.google.common.collect.ImmutableMap)2 HeliosRuntimeException (com.spotify.helios.common.HeliosRuntimeException)2 Job (com.spotify.helios.common.descriptors.Job)2 CreateEmpty (com.spotify.helios.servicescommon.coordination.CreateEmpty)2 SetData (com.spotify.helios.servicescommon.coordination.SetData)2 TypeReference (com.fasterxml.jackson.core.type.TypeReference)1 Function (com.google.common.base.Function)1 Joiner (com.google.common.base.Joiner)1 MoreObjects (com.google.common.base.MoreObjects)1 Optional.fromNullable (com.google.common.base.Optional.fromNullable)1