use of com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec in project vespa by vespa-engine.
the class NodeAgentImplTest method readyNodeLeadsToNoAction.
@Test
public void readyNodeLeadsToNoAction() {
final long restartGeneration = 1;
final long rebootGeneration = 0;
final ContainerNodeSpec nodeSpec = nodeSpecBuilder.nodeState(Node.State.ready).wantedRestartGeneration(restartGeneration).currentRestartGeneration(restartGeneration).wantedRebootGeneration(rebootGeneration).build();
NodeAgentImpl nodeAgent = makeNodeAgent(null, false);
when(nodeRepository.getContainerNodeSpec(hostName)).thenReturn(Optional.of(nodeSpec));
nodeAgent.converge();
nodeAgent.converge();
nodeAgent.converge();
// Should only be called once, when we initialize
verify(dockerOperations, times(1)).getContainer(eq(containerName));
verify(dockerOperations, never()).removeContainer(any(), any());
verify(dockerOperations, never()).createContainer(eq(containerName), eq(nodeSpec));
verify(dockerOperations, never()).startContainer(eq(containerName), eq(nodeSpec));
verify(orchestrator, never()).resume(any(String.class));
verify(nodeRepository, never()).updateNodeAttributes(eq(hostName), any());
}
use of com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec in project vespa by vespa-engine.
the class NodeAgentImplTest method absentContainerCausesStart.
@Test
public void absentContainerCausesStart() throws Exception {
final long restartGeneration = 1;
final long rebootGeneration = 0;
final ContainerNodeSpec nodeSpec = nodeSpecBuilder.wantedDockerImage(dockerImage).nodeState(Node.State.active).wantedVespaVersion(vespaVersion).wantedRestartGeneration(restartGeneration).currentRestartGeneration(restartGeneration).wantedRebootGeneration(rebootGeneration).build();
NodeAgentImpl nodeAgent = makeNodeAgent(null, false);
when(nodeRepository.getContainerNodeSpec(hostName)).thenReturn(Optional.of(nodeSpec));
when(pathResolver.getApplicationStoragePathForNodeAdmin()).thenReturn(Files.createTempDirectory("foo"));
when(pathResolver.getApplicationStoragePathForHost()).thenReturn(Files.createTempDirectory("bar"));
when(dockerOperations.pullImageAsyncIfNeeded(eq(dockerImage))).thenReturn(false);
when(storageMaintainer.getDiskUsageFor(eq(containerName))).thenReturn(Optional.of(201326592000L));
nodeAgent.converge();
verify(dockerOperations, never()).removeContainer(any(), any());
verify(orchestrator, never()).suspend(any(String.class));
final InOrder inOrder = inOrder(dockerOperations, orchestrator, nodeRepository, aclMaintainer);
inOrder.verify(dockerOperations, times(1)).pullImageAsyncIfNeeded(eq(dockerImage));
inOrder.verify(dockerOperations, times(1)).createContainer(eq(containerName), eq(nodeSpec));
inOrder.verify(dockerOperations, times(1)).startContainer(eq(containerName), eq(nodeSpec));
inOrder.verify(aclMaintainer, times(1)).run();
inOrder.verify(dockerOperations, times(1)).resumeNode(eq(containerName));
inOrder.verify(nodeRepository).updateNodeAttributes(hostName, new NodeAttributes().withRestartGeneration(restartGeneration).withRebootGeneration(rebootGeneration).withDockerImage(dockerImage).withVespaVersion(vespaVersion));
inOrder.verify(orchestrator).resume(hostName);
}
use of com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec in project vespa by vespa-engine.
the class NodeAgentImplTest method testGetRelevantMetrics.
@Test
@SuppressWarnings("unchecked")
public void testGetRelevantMetrics() throws Exception {
final ObjectMapper objectMapper = new ObjectMapper();
ClassLoader classLoader = getClass().getClassLoader();
File statsFile = new File(classLoader.getResource("docker.stats.json").getFile());
Map<String, Map<String, Object>> dockerStats = objectMapper.readValue(statsFile, Map.class);
Map<String, Object> networks = dockerStats.get("networks");
Map<String, Object> precpu_stats = dockerStats.get("precpu_stats");
Map<String, Object> cpu_stats = dockerStats.get("cpu_stats");
Map<String, Object> memory_stats = dockerStats.get("memory_stats");
Map<String, Object> blkio_stats = dockerStats.get("blkio_stats");
Docker.ContainerStats stats1 = new ContainerStatsImpl(networks, precpu_stats, memory_stats, blkio_stats);
Docker.ContainerStats stats2 = new ContainerStatsImpl(networks, cpu_stats, memory_stats, blkio_stats);
ContainerNodeSpec.Owner owner = new ContainerNodeSpec.Owner("tester", "testapp", "testinstance");
ContainerNodeSpec.Membership membership = new ContainerNodeSpec.Membership("clustType", "clustId", "grp", 3, false);
final ContainerNodeSpec nodeSpec = nodeSpecBuilder.wantedDockerImage(dockerImage).currentDockerImage(dockerImage).nodeState(Node.State.active).vespaVersion(vespaVersion).owner(owner).membership(membership).minMainMemoryAvailableGb(2).allowedToBeDown(true).build();
NodeAgentImpl nodeAgent = makeNodeAgent(dockerImage, true);
when(nodeRepository.getContainerNodeSpec(eq(hostName))).thenReturn(Optional.of(nodeSpec));
when(storageMaintainer.getDiskUsageFor(eq(containerName))).thenReturn(Optional.of(39625000000L));
when(dockerOperations.getContainerStats(eq(containerName))).thenReturn(Optional.of(stats1)).thenReturn(Optional.of(stats2));
when(pathResolver.getApplicationStoragePathForHost()).thenReturn(Files.createTempDirectory("bar"));
// Run the converge loop once to initialize lastNodeSpec
nodeAgent.converge();
// Update metrics once to init and lastCpuMetric
nodeAgent.updateContainerNodeMetrics();
clock.advance(Duration.ofSeconds(1234));
Path pathToExpectedMetrics = Paths.get(classLoader.getResource("expected.container.system.metrics.txt").getPath());
String expectedMetrics = new String(Files.readAllBytes(pathToExpectedMetrics)).replaceAll("\\s", "").replaceAll("\\n", "");
String[] expectedCommand = { "vespa-rpc-invoke", "-t", "2", "tcp/localhost:19091", "setExtraMetrics", expectedMetrics };
doAnswer(invocation -> {
ContainerName calledContainerName = (ContainerName) invocation.getArguments()[0];
long calledTimeout = (long) invocation.getArguments()[1];
String[] calledCommand = new String[invocation.getArguments().length - 2];
System.arraycopy(invocation.getArguments(), 2, calledCommand, 0, calledCommand.length);
calledCommand[calledCommand.length - 1] = calledCommand[calledCommand.length - 1].replaceAll("\"timestamp\":\\d+", "\"timestamp\":0");
assertEquals(containerName, calledContainerName);
assertEquals(5L, calledTimeout);
assertArrayEquals(expectedCommand, calledCommand);
return null;
}).when(dockerOperations).executeCommandInContainerAsRoot(any(), any(), anyVararg());
nodeAgent.updateContainerNodeMetrics();
}
use of com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec in project vespa by vespa-engine.
the class NodeAgentImplTest method verifyRemoveOldFilesIfDiskFull.
@Test
public void verifyRemoveOldFilesIfDiskFull() {
final long restartGeneration = 1;
final long rebootGeneration = 0;
final ContainerNodeSpec nodeSpec = nodeSpecBuilder.wantedDockerImage(dockerImage).currentDockerImage(dockerImage).nodeState(Node.State.active).wantedVespaVersion(vespaVersion).vespaVersion(vespaVersion).wantedRestartGeneration(restartGeneration).currentRestartGeneration(restartGeneration).wantedRebootGeneration(rebootGeneration).build();
NodeAgentImpl nodeAgent = makeNodeAgent(dockerImage, true);
when(nodeRepository.getContainerNodeSpec(hostName)).thenReturn(Optional.of(nodeSpec));
when(storageMaintainer.getDiskUsageFor(eq(containerName))).thenReturn(Optional.of(217432719360L));
nodeAgent.converge();
verify(storageMaintainer, times(1)).removeOldFilesFromNode(eq(containerName));
}
use of com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec in project vespa by vespa-engine.
the class MultiDockerTest method test.
@Test
public void test() throws InterruptedException {
try (DockerTester dockerTester = new DockerTester()) {
addAndWaitForNode(dockerTester, "host1.test.yahoo.com", new DockerImage("image1"));
ContainerNodeSpec containerNodeSpec2 = addAndWaitForNode(dockerTester, "host2.test.yahoo.com", new DockerImage("image2"));
dockerTester.addContainerNodeSpec(new ContainerNodeSpec.Builder(containerNodeSpec2).nodeState(Node.State.dirty).minCpuCores(1).minMainMemoryAvailableGb(1).minDiskAvailableGb(1).build());
// Wait until it is marked ready
while (dockerTester.nodeRepositoryMock.getContainerNodeSpec(containerNodeSpec2.hostname).filter(nodeSpec -> nodeSpec.nodeState != Node.State.ready).isPresent()) {
Thread.sleep(10);
}
addAndWaitForNode(dockerTester, "host3.test.yahoo.com", new DockerImage("image1"));
dockerTester.callOrderVerifier.assertInOrder("createContainerCommand with DockerImage { imageId=image1 }, HostName: host1.test.yahoo.com, ContainerName { name=host1 }", "executeInContainerAsRoot with ContainerName { name=host1 }, args: [" + DockerTester.NODE_PROGRAM + ", resume]", "createContainerCommand with DockerImage { imageId=image2 }, HostName: host2.test.yahoo.com, ContainerName { name=host2 }", "executeInContainerAsRoot with ContainerName { name=host2 }, args: [" + DockerTester.NODE_PROGRAM + ", resume]", "stopContainer with ContainerName { name=host2 }", "deleteContainer with ContainerName { name=host2 }", "createContainerCommand with DockerImage { imageId=image1 }, HostName: host3.test.yahoo.com, ContainerName { name=host3 }", "executeInContainerAsRoot with ContainerName { name=host3 }, args: [" + DockerTester.NODE_PROGRAM + ", resume]");
dockerTester.callOrderVerifier.assertInOrderWithAssertMessage("Maintainer did not receive call to delete application storage", "deleteContainer with ContainerName { name=host2 }", "DeleteContainerStorage with ContainerName { name=host2 }");
dockerTester.callOrderVerifier.assertInOrder("updateNodeAttributes with HostName: host1.test.yahoo.com, NodeAttributes{restartGeneration=1, rebootGeneration=0, dockerImage=image1, vespaVersion='1.2.3', hardwareDivergence='null'}", "updateNodeAttributes with HostName: host2.test.yahoo.com, NodeAttributes{restartGeneration=1, rebootGeneration=0, dockerImage=image2, vespaVersion='1.2.3', hardwareDivergence='null'}", "markNodeAvailableForNewAllocation with HostName: host2.test.yahoo.com", "updateNodeAttributes with HostName: host3.test.yahoo.com, NodeAttributes{restartGeneration=1, rebootGeneration=0, dockerImage=image1, vespaVersion='1.2.3', hardwareDivergence='null'}");
}
}
Aggregations