Skip to content

Commit

Permalink
Use ServiceLockData to read service status host info
Browse files Browse the repository at this point in the history
  • Loading branch information
Ed Coleman committed May 25, 2024
1 parent df46a27 commit 13531bc
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,6 @@ private StatusSummary getServerHostStatus(final ZooReader zooReader, String base

sld.getServices().forEach(sd -> {
if (serviceType == sd.getService()) {
LOG.warn("LD: {}", sd);
LOG.warn("GROUP: {}", sd.getGroup());

groupNames.add(sd.getGroup());
hostsByGroups.computeIfAbsent(sd.getGroup(), set -> new TreeSet<>())
.add(sd.getAddress());
Expand Down Expand Up @@ -222,7 +219,7 @@ private StatusSummary getStatusSummary(ServiceStatusReport.ReportKey displayName
byGroup.computeIfAbsent(sd.getGroup(), set -> new TreeSet<>()).add(sd.getAddress());
});
});
return new StatusSummary(displayNames, Set.of(), byGroup, result.getErrorCount());
return new StatusSummary(displayNames, byGroup.keySet(), byGroup, result.getErrorCount());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
*/
package org.apache.accumulo.server.util.serviceStatus;

import static org.apache.accumulo.core.lock.ServiceLockData.ServiceDescriptor.DEFAULT_GROUP_NAME;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -83,19 +86,25 @@ public String report(final StringBuilder sb) {
.reduce(Integer::sum).orElse(0);
sb.append("ZooKeeper read errors: ").append(zkErrors).append("\n");

fmtServiceStatus(sb, ReportKey.MANAGER, summaries.get(ReportKey.MANAGER), noHosts);
fmtServiceStatus(sb, ReportKey.MONITOR, summaries.get(ReportKey.MONITOR), noHosts);
fmtServiceStatus(sb, ReportKey.GC, summaries.get(ReportKey.GC), noHosts);
fmtServiceStatus(sb, ReportKey.T_SERVER, summaries.get(ReportKey.T_SERVER), noHosts);
fmtResourceGroups(sb, ReportKey.MANAGER, summaries.get(ReportKey.MANAGER), noHosts);
fmtResourceGroups(sb, ReportKey.MONITOR, summaries.get(ReportKey.MONITOR), noHosts);
fmtResourceGroups(sb, ReportKey.GC, summaries.get(ReportKey.GC), noHosts);
fmtResourceGroups(sb, ReportKey.T_SERVER, summaries.get(ReportKey.T_SERVER), noHosts);
fmtResourceGroups(sb, ReportKey.S_SERVER, summaries.get(ReportKey.S_SERVER), noHosts);
fmtServiceStatus(sb, ReportKey.COORDINATOR, summaries.get(ReportKey.COORDINATOR), noHosts);
fmtResourceGroups(sb, ReportKey.COORDINATOR, summaries.get(ReportKey.COORDINATOR), noHosts);
fmtResourceGroups(sb, ReportKey.COMPACTOR, summaries.get(ReportKey.COMPACTOR), noHosts);

sb.append("\n");
LOG.trace("fmtStatus - with hosts: {}", summaries);
return sb.toString();
}

/**
* This method can be used instead of
* {@link #fmtResourceGroups(StringBuilder, ReportKey, StatusSummary, boolean)} if there are
* services that do not make sense to group by a resource group. With the data in ServiceLock, all
* services has at least the default group.
*/
private void fmtServiceStatus(final StringBuilder sb, final ReportKey displayNames,
final StatusSummary summary, boolean noHosts) {
if (summary == null) {
Expand All @@ -109,9 +118,10 @@ private void fmtServiceStatus(final StringBuilder sb, final ReportKey displayNam
if (noHosts) {
return;
}
sb.append(I2).append("resource group: (default)").append("\n");
if (summary.getServiceCount() > 0) {
var hosts = summary.getServiceByGroups();
hosts.values().forEach(s -> s.forEach(h -> sb.append(I2).append(h).append("\n")));
hosts.values().forEach(s -> s.forEach(h -> sb.append(I4).append(h).append("\n")));
}
}

Expand All @@ -130,6 +140,12 @@ private void fmtResourceGroups(final StringBuilder sb, final ReportKey reportKey
sb.append(reportKey).append(": unavailable").append("\n");
return;
}
// only default group is present, omit grouping from report
if (!summary.getResourceGroups().isEmpty()
&& summary.getResourceGroups().equals(Set.of(DEFAULT_GROUP_NAME))) {
fmtServiceStatus(sb, reportKey, summary, noHosts);
return;
}

fmtCounts(sb, summary);

Expand All @@ -139,6 +155,7 @@ private void fmtResourceGroups(final StringBuilder sb, final ReportKey reportKey
}

if (!summary.getResourceGroups().isEmpty()) {

sb.append(I2).append("resource groups:\n");
summary.getResourceGroups().forEach(g -> sb.append(I4).append(g).append("\n"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.accumulo.core.Constants.ZGC_LOCK;
import static org.apache.accumulo.server.util.ServiceStatusCmd.NO_GROUP_TAG;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
Expand Down Expand Up @@ -88,7 +87,7 @@ void testManagerHosts() throws Exception {
String lock2Data =
"{\"descriptors\":[{\"uuid\":\"6effb690-c29c-4e0b-92ff-f6b308385a42\",\"service\":\"MANAGER\",\"address\":\"localhost:9992\",\"group\":\"default\"}]}";
String lock3Data =
"{\"descriptors\":[{\"uuid\":\"6effb690-c29c-4e0b-92ff-f6b308385a42\",\"service\":\"MANAGER\",\"address\":\"hostA:9999\",\"group\":\"default\"}]}";
"{\"descriptors\":[{\"uuid\":\"6effb690-c29c-4e0b-92ff-f6b308385a42\",\"service\":\"MANAGER\",\"address\":\"hostA:9999\",\"group\":\"manager1\"}]}";

String lockPath = zRoot + Constants.ZMANAGER_LOCK;
expect(zooReader.getChildren(eq(lockPath))).andReturn(List.of(lock1Name, lock2Name, lock3Name))
Expand All @@ -110,11 +109,11 @@ void testManagerHosts() throws Exception {

// expect sorted by name
Map<String,Set<String>> hostByGroup = new TreeMap<>();
hostByGroup.put("default",
new TreeSet<>(List.of("hostA:9999", "localhost:9991", "localhost:9992")));
hostByGroup.put("default", new TreeSet<>(List.of("localhost:9991", "localhost:9992")));
hostByGroup.put("manager1", new TreeSet<>(List.of("hostA:9999")));

StatusSummary expected =
new StatusSummary(ServiceStatusReport.ReportKey.MANAGER, Set.of(), hostByGroup, 0);
StatusSummary expected = new StatusSummary(ServiceStatusReport.ReportKey.MANAGER,
new TreeSet<>(List.of("default", "manager1")), hostByGroup, 0);

assertEquals(expected.hashCode(), status.hashCode());
assertEquals(expected.getDisplayName(), status.getDisplayName());
Expand Down Expand Up @@ -154,8 +153,8 @@ void testMonitorHosts() throws Exception {
Map<String,Set<String>> hostByGroup = new TreeMap<>();
hostByGroup.put("default", new TreeSet<>(List.of("hostA", "hostB")));

StatusSummary expected =
new StatusSummary(ServiceStatusReport.ReportKey.MONITOR, Set.of(), hostByGroup, 0);
StatusSummary expected = new StatusSummary(ServiceStatusReport.ReportKey.MONITOR,
new TreeSet<>(List.of("default")), hostByGroup, 0);

assertEquals(expected.hashCode(), status.hashCode());
assertEquals(expected.getDisplayName(), status.getDisplayName());
Expand Down Expand Up @@ -262,41 +261,51 @@ void testScanServerHosts() throws Exception {
String lock3Name = "zlock#" + uuid3 + "#0000000033";
String lock4Name = "zlock#" + uuid3 + "#0000000044";

// UUID uuidLock = UUID.randomUUID();

String host1 = "host1:8080";
String host2 = "host2:9090";
String host3 = "host3:9091";
String host4 = "host4:9091";

String lockData1 =
"{\"descriptors\":[{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"TABLET_SCAN\",\"address\":\"" + host1 + "\",\"group\":\"default\"},{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"CLIENT\",\"address\":\"" + host1 + "\",\"group\":\"default\"}]}";
"{\"descriptors\":[{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"TABLET_SCAN\",\"address\":\""
+ host1
+ "\",\"group\":\"sg1\"},{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"CLIENT\",\"address\":\""
+ host1 + "\",\"group\":\"sg1\"}]}";
String lockData2 =
"{\"descriptors\":[{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"TABLET_SCAN\",\"address\":\"" + host2 + "\",\"group\":\"default\"},{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"CLIENT\",\"address\":\"" + host2 + "\",\"group\":\"default\"}]}";
"{\"descriptors\":[{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"TABLET_SCAN\",\"address\":\""
+ host2
+ "\",\"group\":\"default\"},{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"CLIENT\",\"address\":\""
+ host2 + "\",\"group\":\"default\"}]}";
String lockData3 =
"{\"descriptors\":[{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"TABLET_SCAN\",\"address\":\"" + host3 + "\",\"group\":\"sg1\"},{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"CLIENT\",\"address\":\"" + host3 + "\",\"group\":\"sg1\"}]}";
"{\"descriptors\":[{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"TABLET_SCAN\",\"address\":\""
+ host3
+ "\",\"group\":\"sg1\"},{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"CLIENT\",\"address\":\""
+ host3 + "\",\"group\":\"sg1\"}]}";
String lockData4 =
"{\"descriptors\":[{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"TABLET_SCAN\",\"address\":\"" + host4 + "\",\"group\":\"sg1\"},{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"CLIENT\",\"address\":\"" + host4 + "\",\"group\":\"sg1\"}]}";
"{\"descriptors\":[{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"TABLET_SCAN\",\"address\":\""
+ host4
+ "\",\"group\":\"default\"},{\"uuid\":\"f408fed7-ce93-40d2-8e60-63e8a3daf416\",\"service\":\"CLIENT\",\"address\":\""
+ host4 + "\",\"group\":\"default\"}]}";

String lockPath = zRoot + Constants.ZSSERVERS;
expect(zooReader.getChildren(eq(lockPath))).andReturn(List.of(host1, host2, host3, host4))
.anyTimes();

expect(zooReader.getChildren(eq(lockPath + "/" + host1))).andReturn(List.of(lock1Name)).once();
expect(zooReader.getData(eq(lockPath + "/" + host1 + "/" + lock1Name)))
.andReturn((UUID.randomUUID() + ",rg1").getBytes(UTF_8)).once();
.andReturn(lockData1.getBytes(UTF_8)).once();

expect(zooReader.getChildren(eq(lockPath + "/" + host2))).andReturn(List.of(lock2Name)).once();
expect(zooReader.getData(eq(lockPath + "/" + host2 + "/" + lock2Name)))
.andReturn((UUID.randomUUID() + ",default").getBytes(UTF_8)).once();
.andReturn(lockData2.getBytes(UTF_8)).once();

expect(zooReader.getChildren(eq(lockPath + "/" + host3))).andReturn(List.of(lock3Name)).once();
expect(zooReader.getData(eq(lockPath + "/" + host3 + "/" + lock3Name)))
.andReturn((UUID.randomUUID() + ",rg1").getBytes(UTF_8)).once();
.andReturn(lockData3.getBytes(UTF_8)).once();

expect(zooReader.getChildren(eq(lockPath + "/" + host4))).andReturn(List.of(lock4Name)).once();
expect(zooReader.getData(eq(lockPath + "/" + host4 + "/" + lock4Name)))
.andReturn((UUID.randomUUID() + ",default").getBytes(UTF_8)).once();
.andReturn(lockData4.getBytes(UTF_8)).once();

replay(zooReader);

Expand All @@ -306,10 +315,10 @@ void testScanServerHosts() throws Exception {

Map<String,Set<String>> hostByGroup = new TreeMap<>();
hostByGroup.put("default", new TreeSet<>(List.of("host2:9090", "host4:9091")));
hostByGroup.put("rg1", new TreeSet<>(List.of("host1:8080", "host3:9091")));
hostByGroup.put("sg1", new TreeSet<>(List.of("host1:8080", "host3:9091")));

StatusSummary expected = new StatusSummary(ServiceStatusReport.ReportKey.S_SERVER,
Set.of("default", "rg1"), hostByGroup, 0);
Set.of("default", "sg1"), hostByGroup, 0);

assertEquals(expected, status);

Expand All @@ -325,14 +334,24 @@ void testCoordinatorHosts() throws Exception {
String host2 = "hostB:9090";
String host3 = "host1:9091";

String lockData1 =
"{\"descriptors\":[{\"uuid\":\"1d55f7a5-090d-48fc-a3ea-f1a66e984a21\",\"service\":\"COORDINATOR\",\"address\":\""
+ host1 + "\",\"group\":\"default\"}]}\n";
String lockData2 =
"{\"descriptors\":[{\"uuid\":\"1d55f7a5-090d-48fc-a3ea-f1a66e984a21\",\"service\":\"COORDINATOR\",\"address\":\""
+ host2 + "\",\"group\":\"coord1\"}]}\n";
String lockData3 =
"{\"descriptors\":[{\"uuid\":\"1d55f7a5-090d-48fc-a3ea-f1a66e984a21\",\"service\":\"COORDINATOR\",\"address\":\""
+ host3 + "\",\"group\":\"coord2\"}]}\n";

String lockPath = zRoot + Constants.ZCOORDINATOR_LOCK;
expect(zooReader.getChildren(eq(lockPath))).andReturn(List.of(lock1Name, lock2Name, lock3Name))
.anyTimes();
expect(zooReader.getData(eq(lockPath + "/" + lock1Name))).andReturn(host1.getBytes(UTF_8))
expect(zooReader.getData(eq(lockPath + "/" + lock1Name))).andReturn(lockData1.getBytes(UTF_8))
.anyTimes();
expect(zooReader.getData(eq(lockPath + "/" + lock2Name))).andReturn(host2.getBytes(UTF_8))
expect(zooReader.getData(eq(lockPath + "/" + lock2Name))).andReturn(lockData2.getBytes(UTF_8))
.anyTimes();
expect(zooReader.getData(eq(lockPath + "/" + lock3Name))).andReturn(host3.getBytes(UTF_8))
expect(zooReader.getData(eq(lockPath + "/" + lock3Name))).andReturn(lockData3.getBytes(UTF_8))
.anyTimes();

replay(zooReader);
Expand All @@ -344,12 +363,13 @@ void testCoordinatorHosts() throws Exception {
assertEquals(3, status.getServiceCount());

// expect sorted by name
Set<String> hosts = new TreeSet<>(List.of(host1, host2, host3));
Map<String,Set<String>> hostByGroup = new TreeMap<>();
hostByGroup.put(NO_GROUP_TAG, hosts);
hostByGroup.put("default", new TreeSet<>(List.of(host1)));
hostByGroup.put("coord1", new TreeSet<>(List.of(host2)));
hostByGroup.put("coord2", new TreeSet<>(List.of(host3)));

StatusSummary expected =
new StatusSummary(ServiceStatusReport.ReportKey.COORDINATOR, Set.of(), hostByGroup, 0);
StatusSummary expected = new StatusSummary(ServiceStatusReport.ReportKey.COORDINATOR,
new TreeSet<>(List.of("coord1", "default", "coord2")), hostByGroup, 0);

assertEquals(expected.hashCode(), status.hashCode());
assertEquals(expected.getDisplayName(), status.getDisplayName());
Expand Down Expand Up @@ -390,24 +410,33 @@ public void testGcHosts() throws Exception {
String host1 = "host1:8080";
String host2 = "host2:9090";

String lockData1 =
"{\"descriptors\":[{\"uuid\":\"5c901352-b027-4f78-8ee1-05ae163fbb0e\",\"service\":\"GC\",\"address\":\""
+ host2 + "\",\"group\":\"default\"}]}";
String lockData2 =
"{\"descriptors\":[{\"uuid\":\"5c901352-b027-4f78-8ee1-05ae163fbb0e\",\"service\":\"GC\",\"address\":\""
+ host1 + "\",\"group\":\"gc1\"}]}";

expect(zooReader.getChildren(eq(lockPath))).andReturn(List.of(lock1Name, lock2Name)).once();
expect(zooReader.getData(eq(lockPath + "/" + lock1Name)))
.andReturn(("GC_CLIENT=" + host1).getBytes(UTF_8)).once();
expect(zooReader.getData(eq(lockPath + "/" + lock2Name)))
.andReturn(("GC_CLIENT=" + host2).getBytes(UTF_8)).once();
expect(zooReader.getData(eq(lockPath + "/" + lock1Name))).andReturn(lockData1.getBytes(UTF_8))
.once();
expect(zooReader.getData(eq(lockPath + "/" + lock2Name))).andReturn(lockData2.getBytes(UTF_8))
.once();

replay(zooReader);

ServiceStatusCmd cmd = new ServiceStatusCmd();
StatusSummary status = cmd.getGcStatus(zooReader, zRoot);
LOG.info("gc server counts: {}", status);
assertEquals(0, status.getResourceGroups().size());
assertEquals(2, status.getResourceGroups().size());
assertEquals(2, status.getServiceCount());
assertEquals(0, status.getErrorCount());
assertEquals(1, status.getServiceByGroups().size());
assertEquals(2, status.getServiceByGroups().get(NO_GROUP_TAG).size());
assertEquals(new TreeSet<>(List.of(host1, host2)),
status.getServiceByGroups().get(NO_GROUP_TAG));
assertEquals(2, status.getServiceByGroups().size());
assertEquals(1, status.getServiceByGroups().get("default").size());
assertEquals(1, status.getServiceByGroups().get("gc1").size());
assertEquals(new TreeSet<>(List.of("default", "gc1")), status.getResourceGroups());
assertEquals(new TreeSet<>(List.of(host1)), status.getServiceByGroups().get("gc1"));
assertEquals(new TreeSet<>(List.of(host2)), status.getServiceByGroups().get("default"));
}

/**
Expand All @@ -417,33 +446,47 @@ public void testGcHosts() throws Exception {
@Test
void zkNodeDeletedTest() throws Exception {
String lock1Name = "zlock#" + UUID.randomUUID() + "#0000000001";
String lock2Name = "zlock#" + UUID.randomUUID() + "#0000000022";
String lock3Name = "zlock#" + UUID.randomUUID() + "#0000000099";
String host2 = "hostZ:8080";
String host3 = "hostA:8080";
String lock2Name = "zlock#" + UUID.randomUUID() + "#0000000002";
String lock3Name = "zlock#" + UUID.randomUUID() + "#0000000003";

String host2 = "localhost:9992";
String host3 = "hostA:9999";

String lock1data =
"{\"descriptors\":[{\"uuid\":\"6effb690-c29c-4e0b-92ff-f6b308385a42\",\"service\":\"MANAGER\",\"address\":\"localhost:9991\",\"group\":\"default\"}]}";
String lock2Data =
"{\"descriptors\":[{\"uuid\":\"6effb690-c29c-4e0b-92ff-f6b308385a42\",\"service\":\"MANAGER\",\"address\":\""
+ host2 + "\",\"group\":\"default\"}]}";
String lock3Data =
"{\"descriptors\":[{\"uuid\":\"6effb690-c29c-4e0b-92ff-f6b308385a42\",\"service\":\"MANAGER\",\"address\":\""
+ host3 + "\",\"group\":\"manager1\"}]}";

String lockPath = zRoot + Constants.ZMANAGER_LOCK;
expect(zooReader.getChildren(eq(lockPath))).andReturn(List.of(lock1Name, lock2Name, lock3Name))
.anyTimes();
// expect(zooReader.getData(eq(lockPath + "/" + lock1Name)))
// .andThrow(new KeeperException.NoNodeException("no node forced exception")).once();
expect(zooReader.getData(eq(lockPath + "/" + lock1Name)))
.andThrow(new KeeperException.NoNodeException("no node forced exception")).anyTimes();
expect(zooReader.getData(eq(lockPath + "/" + lock2Name))).andReturn(host2.getBytes(UTF_8))
.andThrow(new KeeperException.NoNodeException("no node forced exception")).once();
expect(zooReader.getData(eq(lockPath + "/" + lock2Name))).andReturn(lock2Data.getBytes(UTF_8))
.anyTimes();
expect(zooReader.getData(eq(lockPath + "/" + lock3Name))).andReturn(host3.getBytes(UTF_8))
expect(zooReader.getData(eq(lockPath + "/" + lock3Name))).andReturn(lock3Data.getBytes(UTF_8))
.anyTimes();

replay(zooReader);

ServiceStatusCmd cmd = new ServiceStatusCmd();
StatusSummary status = cmd.getManagerStatus(zooReader, zRoot);
LOG.info("manager status data: {}", status);

assertEquals(1, status.getServiceByGroups().size());
assertEquals(2, status.getServiceByGroups().get(NO_GROUP_TAG).size());
assertEquals(2, status.getServiceByGroups().size());
assertEquals(1, status.getServiceByGroups().get("default").size());
assertEquals(1, status.getServiceByGroups().get("manager1").size());
assertEquals(1, status.getErrorCount());

// host 1 missing - no node exception
Set<String> sortedHosts = new TreeSet<>(List.of(host3, host2));
assertEquals(sortedHosts, status.getServiceByGroups().get(NO_GROUP_TAG));
assertEquals(new TreeSet<>(List.of(host2)), status.getServiceByGroups().get("default"));
assertEquals(new TreeSet<>(List.of(host3)), status.getServiceByGroups().get("manager1"));
}

@Test
Expand Down
Loading

0 comments on commit 13531bc

Please sign in to comment.