Search in sources :

Example 1 with HostStatus

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

the class DeploymentGroupResource method getDeploymentGroupStatus.

@GET
@Path("/{name}/status")
@Produces(APPLICATION_JSON)
@Timed
@ExceptionMetered
public Response getDeploymentGroupStatus(@PathParam("name") @Valid final String name) {
    try {
        final DeploymentGroup deploymentGroup = model.getDeploymentGroup(name);
        final DeploymentGroupStatus deploymentGroupStatus = model.getDeploymentGroupStatus(name);
        final List<String> hosts = model.getDeploymentGroupHosts(name);
        final List<DeploymentGroupStatusResponse.HostStatus> result = Lists.newArrayList();
        for (final String host : hosts) {
            final HostStatus hostStatus = model.getHostStatus(host);
            JobId deployedJobId = null;
            TaskStatus.State state = null;
            if (hostStatus != null && hostStatus.getStatus().equals(HostStatus.Status.UP)) {
                for (final Map.Entry<JobId, Deployment> entry : hostStatus.getJobs().entrySet()) {
                    if (name.equals(entry.getValue().getDeploymentGroupName())) {
                        deployedJobId = entry.getKey();
                        final TaskStatus taskStatus = hostStatus.getStatuses().get(deployedJobId);
                        if (taskStatus != null) {
                            state = taskStatus.getState();
                        }
                        break;
                    }
                }
                result.add(new DeploymentGroupStatusResponse.HostStatus(host, deployedJobId, state));
            }
        }
        final DeploymentGroupStatusResponse.Status status;
        if (deploymentGroupStatus == null) {
            status = DeploymentGroupStatusResponse.Status.IDLE;
        } else if (deploymentGroupStatus.getState() == DeploymentGroupStatus.State.FAILED) {
            status = DeploymentGroupStatusResponse.Status.FAILED;
        } else if (deploymentGroupStatus.getState() == DeploymentGroupStatus.State.ROLLING_OUT) {
            status = DeploymentGroupStatusResponse.Status.ROLLING_OUT;
        } else {
            status = DeploymentGroupStatusResponse.Status.ACTIVE;
        }
        final String error = deploymentGroupStatus == null ? "" : deploymentGroupStatus.getError();
        return Response.ok(new DeploymentGroupStatusResponse(deploymentGroup, status, error, result, deploymentGroupStatus)).build();
    } catch (final DeploymentGroupDoesNotExistException e) {
        return Response.status(Response.Status.NOT_FOUND).build();
    }
}
Also used : Deployment(com.spotify.helios.common.descriptors.Deployment) DeploymentGroupStatus(com.spotify.helios.common.descriptors.DeploymentGroupStatus) DeploymentGroupDoesNotExistException(com.spotify.helios.master.DeploymentGroupDoesNotExistException) TaskStatus(com.spotify.helios.common.descriptors.TaskStatus) DeploymentGroupStatusResponse(com.spotify.helios.common.protocol.DeploymentGroupStatusResponse) HostStatus(com.spotify.helios.common.descriptors.HostStatus) Map(java.util.Map) DeploymentGroup(com.spotify.helios.common.descriptors.DeploymentGroup) JobId(com.spotify.helios.common.descriptors.JobId) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) Timed(com.codahale.metrics.annotation.Timed) GET(javax.ws.rs.GET) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Example 2 with HostStatus

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

the class HostListCommand method run.

@Override
int run(final Namespace options, final HeliosClient client, final PrintStream out, final boolean json, final BufferedReader stdin) throws ExecutionException, InterruptedException {
    final String pattern = options.getString(patternArg.getDest());
    final List<String> selectorArgValue = options.getList(hostSelectorsArg.getDest());
    final Set<String> selectors = ImmutableSet.copyOf(selectorArgValue);
    final List<String> hosts;
    if (pattern.isEmpty() && selectors.isEmpty()) {
        hosts = client.listHosts().get();
    } else if (!pattern.isEmpty() && selectors.isEmpty()) {
        hosts = client.listHosts(pattern).get();
    } else if (pattern.isEmpty() && !selectors.isEmpty()) {
        hosts = client.listHosts(selectors).get();
    } else {
        hosts = client.listHosts(pattern, selectors).get();
    }
    final Map<String, String> queryParams = Maps.newHashMap();
    final String statusFilter = options.getString(statusArg.getDest());
    if (!isNullOrEmpty(statusFilter)) {
        try {
            HostStatus.Status.valueOf(statusFilter);
            queryParams.put("status", statusFilter);
        } catch (IllegalArgumentException ignored) {
            throw new IllegalArgumentException("Invalid status. Valid statuses are: " + statusChoicesString);
        }
    }
    final boolean full = options.getBoolean(fullArg.getDest());
    final boolean quiet = options.getBoolean(quietArg.getDest());
    if (hosts.isEmpty()) {
        if (json) {
            out.println("{ }");
        } else if (!quiet && !isNullOrEmpty(pattern)) {
            out.printf("host pattern %s matched no hosts%n", pattern);
        }
        return 1;
    }
    if (quiet) {
        final List<String> sortedHosts = natural().sortedCopy(hosts);
        if (json) {
            out.println(Json.asPrettyStringUnchecked(sortedHosts));
        } else {
            for (final String host : sortedHosts) {
                out.println(formatHostname(full, host));
            }
        }
    } else {
        final Map<String, HostStatus> statuses = new TreeMap<>(client.hostStatuses(hosts, queryParams).get());
        if (json) {
            out.println(Json.asPrettyStringUnchecked(statuses));
        } else {
            final Table table = table(out);
            table.row("HOST", "STATUS", "DEPLOYED", "RUNNING", "CPUS", "MEM", "LOAD AVG", "MEM USAGE", "OS", "HELIOS", "DOCKER", "LABELS");
            for (final Map.Entry<String, HostStatus> e : statuses.entrySet()) {
                final String host = e.getKey();
                final HostStatus s = e.getValue();
                if (s == null) {
                    continue;
                }
                final Set<TaskStatus> runningDeployedJobs = Sets.newHashSet();
                for (final JobId jobId : s.getJobs().keySet()) {
                    final TaskStatus taskStatus = s.getStatuses().get(jobId);
                    if (taskStatus == null) {
                        continue;
                    }
                    if (taskStatus.getState() == TaskStatus.State.RUNNING) {
                        runningDeployedJobs.add(taskStatus);
                    }
                }
                final HostInfo hi = s.getHostInfo();
                final String memUsage;
                final String cpus;
                final String mem;
                final String loadAvg;
                final String os;
                final String docker;
                if (hi != null) {
                    final long free = hi.getMemoryFreeBytes();
                    final long total = hi.getMemoryTotalBytes();
                    memUsage = format("%.2f", (float) (total - free) / total);
                    cpus = String.valueOf(hi.getCpus());
                    mem = hi.getMemoryTotalBytes() / (1024 * 1024 * 1024) + " gb";
                    loadAvg = format("%.2f", hi.getLoadAvg());
                    os = hi.getOsName() + " " + hi.getOsVersion();
                    final DockerVersion dv = hi.getDockerVersion();
                    docker = (dv != null) ? format("%s (%s)", dv.getVersion(), dv.getApiVersion()) : "";
                } else {
                    memUsage = cpus = mem = loadAvg = os = docker = "";
                }
                final String version;
                if (s.getAgentInfo() != null) {
                    version = Optional.fromNullable(s.getAgentInfo().getVersion()).or("");
                } else {
                    version = "";
                }
                String status = s.getStatus() == UP ? "Up" : "Down";
                if (s.getAgentInfo() != null) {
                    final long startTime = s.getAgentInfo().getStartTime();
                    final long upTime = s.getAgentInfo().getUptime();
                    if (s.getStatus() == UP) {
                        status += " " + humanDuration(currentTimeMillis() - startTime);
                    } else {
                        status += " " + humanDuration(currentTimeMillis() - startTime - upTime);
                    }
                }
                final String hostLabels = Joiner.on(", ").withKeyValueSeparator("=").join(s.getLabels());
                table.row(formatHostname(full, host), status, s.getJobs().size(), runningDeployedJobs.size(), cpus, mem, loadAvg, memUsage, os, version, docker, hostLabels);
            }
            table.print();
        }
    }
    return 0;
}
Also used : Table(com.spotify.helios.cli.Table) TreeMap(java.util.TreeMap) TaskStatus(com.spotify.helios.common.descriptors.TaskStatus) DockerVersion(com.spotify.helios.common.descriptors.DockerVersion) HostStatus(com.spotify.helios.common.descriptors.HostStatus) Map(java.util.Map) TreeMap(java.util.TreeMap) HostInfo(com.spotify.helios.common.descriptors.HostInfo) JobId(com.spotify.helios.common.descriptors.JobId)

Example 3 with HostStatus

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

the class HostListCommandTest method testSelectorFilter.

@Test
public void testSelectorFilter() throws Exception {
    final String hostname = "foo1.example.com";
    final List<String> hosts = ImmutableList.of(hostname);
    when(client.listHosts(ImmutableSet.of("foo=bar"))).thenReturn(Futures.immediateFuture(hosts));
    final Map<String, HostStatus> statusResponse = ImmutableMap.of(hostname, upStatus);
    when(client.hostStatuses(eq(hosts), anyMapOf(String.class, String.class))).thenReturn(Futures.immediateFuture(statusResponse));
    final int ret = runCommand("--selector", "foo=bar");
    assertEquals(0, ret);
    assertEquals(ImmutableList.of("HOST", hostname + "."), TestUtils.readFirstColumnFromOutput(baos.toString(), false));
}
Also used : HostStatus(com.spotify.helios.common.descriptors.HostStatus) Matchers.containsString(org.hamcrest.Matchers.containsString) Test(org.junit.Test)

Example 4 with HostStatus

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

the class MultiplePortJobTest method test.

@Test
public void test() throws Exception {
    startDefaultMaster();
    // 'Reserve' a 2 port wide range of ports.
    final Range<Integer> portRange = temporaryPorts.localPortRange("agent1", 2);
    // Start an agent using the aforementioned 2 port wide range.
    final AgentMain agent1 = startDefaultAgent(testHost(), "--port-range=" + portRange.lowerEndpoint() + ":" + portRange.upperEndpoint());
    try (final DockerClient dockerClient = getNewDockerClient()) {
        final HeliosClient client = defaultClient();
        awaitHostStatus(client, testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
        // foo is a mapping of 4711 -> A port dynamically allocated by the agent's PortAllocator
        // bar is a mapping of 4712 -> A static port randomly selected by temporaryPorts
        final Map<String, PortMapping> ports1 = ImmutableMap.of("foo", PortMapping.of(4711), "bar", staticMapping1);
        // foo is a mapping of 4711 -> A port dynamically allocated by the agent's PortAllocator
        // bar is a mapping of 4712 -> A static port randomly selected by temporaryPorts
        final Map<String, PortMapping> ports2 = ImmutableMap.of("foo", PortMapping.of(4711), "bar", staticMapping2);
        final JobId jobId1 = createJob(testJobName + 1, testJobVersion, BUSYBOX, IDLE_COMMAND, EMPTY_ENV, ports1);
        assertNotNull(jobId1);
        deployJob(jobId1, testHost());
        final TaskStatus firstTaskStatus1 = awaitJobState(client, testHost(), jobId1, RUNNING, LONG_WAIT_SECONDS, SECONDS);
        final JobId jobId2 = createJob(testJobName + 2, testJobVersion, BUSYBOX, IDLE_COMMAND, EMPTY_ENV, ports2);
        assertNotNull(jobId2);
        deployJob(jobId2, testHost());
        final TaskStatus firstTaskStatus2 = awaitJobState(client, testHost(), jobId2, RUNNING, LONG_WAIT_SECONDS, SECONDS);
        // Verify we allocated dynamic ports from within the specified range.
        assertTrue(portRange.contains(firstTaskStatus1.getPorts().get("foo").getExternalPort()));
        assertTrue(portRange.contains(firstTaskStatus2.getPorts().get("foo").getExternalPort()));
        // Verify we allocated the static ports we asked for.
        assertEquals(staticMapping1, firstTaskStatus1.getPorts().get("bar"));
        assertEquals(staticMapping2, firstTaskStatus2.getPorts().get("bar"));
        // Verify we didn't allocate the same dynamic port to both jobs.
        assertNotEquals(firstTaskStatus1.getPorts().get("foo"), firstTaskStatus2.getPorts().get("foo"));
        // TODO (dano): the supervisor should report the allocated ports at all times
        // Verify that port allocation is kept across container restarts
        dockerClient.killContainer(firstTaskStatus1.getContainerId());
        final TaskStatus restartedTaskStatus1 = Polling.await(LONG_WAIT_SECONDS, SECONDS, new Callable<TaskStatus>() {

            @Override
            public TaskStatus call() throws Exception {
                final HostStatus hostStatus = client.hostStatus(testHost()).get();
                final TaskStatus taskStatus = hostStatus.getStatuses().get(jobId1);
                return (taskStatus != null && taskStatus.getState() == RUNNING && !Objects.equals(taskStatus.getContainerId(), firstTaskStatus1.getContainerId())) ? taskStatus : null;
            }
        });
        assertEquals(firstTaskStatus1.getPorts(), restartedTaskStatus1.getPorts());
        // Verify that port allocation is kept across agent restarts
        agent1.stopAsync().awaitTerminated();
        dockerClient.killContainer(firstTaskStatus2.getContainerId());
        startDefaultAgent(testHost());
        final TaskStatus restartedTaskStatus2 = Polling.await(LONG_WAIT_SECONDS, SECONDS, new Callable<TaskStatus>() {

            @Override
            public TaskStatus call() throws Exception {
                final HostStatus hostStatus = client.hostStatus(testHost()).get();
                final TaskStatus taskStatus = hostStatus.getStatuses().get(jobId2);
                return (taskStatus != null && taskStatus.getState() == RUNNING && !Objects.equals(taskStatus.getContainerId(), firstTaskStatus2.getContainerId())) ? taskStatus : null;
            }
        });
        assertEquals(firstTaskStatus2.getPorts(), restartedTaskStatus2.getPorts());
    }
}
Also used : DockerClient(com.spotify.docker.client.DockerClient) HeliosClient(com.spotify.helios.client.HeliosClient) TaskStatus(com.spotify.helios.common.descriptors.TaskStatus) AgentMain(com.spotify.helios.agent.AgentMain) HostStatus(com.spotify.helios.common.descriptors.HostStatus) PortMapping(com.spotify.helios.common.descriptors.PortMapping) JobId(com.spotify.helios.common.descriptors.JobId) Test(org.junit.Test)

Example 5 with HostStatus

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

the class EnvironmentVariableTest method test.

@Test
public void test() throws Exception {
    startDefaultMaster();
    startDefaultAgent(testHost(), "--env", "SPOTIFY_POD=PODNAME", "SPOTIFY_ROLE=ROLENAME", "BAR=badfood");
    awaitHostStatus(testHost(), UP, LONG_WAIT_SECONDS, SECONDS);
    // Wait for the agent to report environment vars
    Polling.await(LONG_WAIT_SECONDS, SECONDS, new Callable<Object>() {

        @Override
        public Object call() throws Exception {
            final Map<String, HostStatus> status = Json.read(cli("hosts", testHost(), "--json"), new TypeReference<Map<String, HostStatus>>() {
            });
            return status.get(testHost()).getEnvironment();
        }
    });
    try (final DockerClient dockerClient = getNewDockerClient()) {
        final List<String> command = asList("sh", "-c", "echo pod: $SPOTIFY_POD; " + "echo role: $SPOTIFY_ROLE; " + "echo foo: $FOO; " + "echo bar: $BAR");
        // Create job
        final JobId jobId = createJob(testJobName, testJobVersion, BUSYBOX, command, ImmutableMap.of("FOO", "4711", "BAR", "deadbeef"));
        // deploy
        deployJob(jobId, testHost());
        final TaskStatus taskStatus = awaitTaskState(jobId, testHost(), EXITED);
        final LogStream logs = dockerClient.logs(taskStatus.getContainerId(), stdout(), stderr());
        final String log = logs.readFully();
        assertThat(log, containsString("pod: PODNAME"));
        assertThat(log, containsString("role: ROLENAME"));
        assertThat(log, containsString("foo: 4711"));
        // Verify that the the BAR environment variable in the job overrode the agent config
        assertThat(log, containsString("bar: deadbeef"));
        final Map<String, HostStatus> status = Json.read(cli("hosts", testHost(), "--json"), new TypeReference<Map<String, HostStatus>>() {
        });
        assertEquals(ImmutableMap.of("SPOTIFY_POD", "PODNAME", "SPOTIFY_ROLE", "ROLENAME", "BAR", "badfood"), status.get(testHost()).getEnvironment());
        assertEquals(ImmutableMap.of("SPOTIFY_POD", "PODNAME", "SPOTIFY_ROLE", "ROLENAME", "BAR", "deadbeef", "FOO", "4711"), status.get(testHost()).getStatuses().get(jobId).getEnv());
    }
}
Also used : DockerClient(com.spotify.docker.client.DockerClient) Matchers.containsString(org.hamcrest.Matchers.containsString) LogStream(com.spotify.docker.client.LogStream) TaskStatus(com.spotify.helios.common.descriptors.TaskStatus) HostStatus(com.spotify.helios.common.descriptors.HostStatus) TypeReference(com.fasterxml.jackson.core.type.TypeReference) ImmutableMap(com.google.common.collect.ImmutableMap) Map(java.util.Map) JobId(com.spotify.helios.common.descriptors.JobId) Test(org.junit.Test)

Aggregations

HostStatus (com.spotify.helios.common.descriptors.HostStatus)28 Test (org.junit.Test)17 JobId (com.spotify.helios.common.descriptors.JobId)13 TaskStatus (com.spotify.helios.common.descriptors.TaskStatus)10 HeliosClient (com.spotify.helios.client.HeliosClient)9 Map (java.util.Map)8 Job (com.spotify.helios.common.descriptors.Job)6 Deployment (com.spotify.helios.common.descriptors.Deployment)5 Matchers.containsString (org.hamcrest.Matchers.containsString)5 DockerClient (com.spotify.docker.client.DockerClient)4 JobUndeployResponse (com.spotify.helios.common.protocol.JobUndeployResponse)4 ExecutionException (java.util.concurrent.ExecutionException)4 AgentMain (com.spotify.helios.agent.AgentMain)3 DeploymentGroup (com.spotify.helios.common.descriptors.DeploymentGroup)3 CreateJobResponse (com.spotify.helios.common.protocol.CreateJobResponse)3 JobDeployResponse (com.spotify.helios.common.protocol.JobDeployResponse)3 TimeoutException (java.util.concurrent.TimeoutException)3 ExceptionMetered (com.codahale.metrics.annotation.ExceptionMetered)2 Timed (com.codahale.metrics.annotation.Timed)2 TypeReference (com.fasterxml.jackson.core.type.TypeReference)2