Github user grkvlt commented on a diff in the pull request:
https://github.com/apache/incubator-brooklyn/pull/263#discussion_r19304560
--- Diff:
software/network/src/main/java/brooklyn/entity/network/bind/BindDnsServerImpl.java
---
@@ -143,124 +167,133 @@ protected void preStart() {
String reverseLookupDomain =
Joiner.on('.').join(Iterables.skip(Lists.reverse(Lists.newArrayList(Splitter.on('.').split(reverse))),
1)) + ".in-addr.arpa";
setAttribute(REVERSE_LOOKUP_DOMAIN, reverseLookupDomain);
- Map<?, ?> flags = MutableMap.builder()
- .build();
- policy = addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
+ addPolicy(PolicySpec.create(MemberTrackingPolicy.class)
.displayName("Address tracker")
.configure("sensorsToTrack",
ImmutableSet.of(getConfig(HOSTNAME_SENSOR)))
- .configure("group", entities));
+ .configure("group", getEntities()));
+ }
- // For any entities that have already come up
- for (Entity member : entities.getMembers()) {
- if
(Strings.isNonBlank(member.getAttribute(getConfig(HOSTNAME_SENSOR))))
added(member); // Ignore, unless hostname set
- }
+ @Override
+ public void postStart() {
+ update();
}
public static class MemberTrackingPolicy extends
AbstractMembershipTrackingPolicy {
@Override
protected void onEntityChange(Entity member) {
- // TODO Should we guard to only call if service_up and if
hostname set?
- ((BindDnsServerImpl)entity).added(member);
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("State of {} on change: {}", member,
member.getAttribute(Attributes.SERVICE_STATE_ACTUAL).name());
+ }
+ ((BindDnsServerImpl) entity).update();
}
@Override
protected void onEntityAdded(Entity member) {
- if
(Strings.isNonBlank(member.getAttribute(getConfig(HOSTNAME_SENSOR)))) {
- ((BindDnsServerImpl)entity).added(member); // Ignore,
unless hostname set
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("State of {} on added: {}", member,
member.getAttribute(Attributes.SERVICE_STATE_ACTUAL).name());
}
- }
- @Override
- protected void onEntityRemoved(Entity member) {
- ((BindDnsServerImpl)entity).removed(member);
+ ((BindDnsServerImpl) entity).configureResolver(member);
}
}
- @Override
- public void postStart() {
- update();
+ private class HasHostnameAndValidLifecycle implements
Predicate<Entity> {
+ @Override
+ public boolean apply(Entity input) {
+ switch (input.getAttribute(Attributes.SERVICE_STATE_ACTUAL)) {
+ case STOPPED:
+ case STOPPING:
+ case DESTROYED:
+ return false;
+ }
+ return input.getAttribute(getConfig(HOSTNAME_SENSOR)) != null;
+ }
}
- public void added(Entity member) {
- synchronized (mutex) {
- Optional<Location> location =
Iterables.tryFind(member.getLocations(),
Predicates.instanceOf(SshMachineLocation.class));
- String hostname =
member.getAttribute(getConfig(HOSTNAME_SENSOR));
- if (location.isPresent() && Strings.isNonBlank(hostname)) {
- SshMachineLocation machine = (SshMachineLocation)
location.get();
- String address = machine.getAddress().getHostAddress();
- if (!entityLocations.containsKey(machine)) {
- entityLocations.put(machine, member);
- addressMappings.putIfAbsent(address, hostname);
+ public void update() {
+ Lifecycle serverState =
getAttribute(Attributes.SERVICE_STATE_ACTUAL);
+ if (Lifecycle.STOPPED.equals(serverState) ||
Lifecycle.STOPPING.equals(serverState)
+ || Lifecycle.DESTROYED.equals(serverState) ||
!getAttribute(Attributes.SERVICE_UP)) {
+ LOG.debug("Skipped update of {} when service state is {} and
running is {}",
+ new Object[]{this,
getAttribute(Attributes.SERVICE_STATE_ACTUAL), getAttribute(SERVICE_UP)});
+ return;
+ }
+ synchronized (this) {
+ Iterable<Entity> availableEntities =
FluentIterable.from(getEntities().getMembers())
+ .filter(new HasHostnameAndValidLifecycle());
+ LOG.debug("{} updating with entities: {}", this, Joiner.on(",
").join(availableEntities));
+ ImmutableListMultimap<String, Entity> hostnameToEntity =
Multimaps.index(availableEntities,
+ EntityFunctions.attribute(getConfig(HOSTNAME_SENSOR)));
+ Map<String, String> octetToName = Maps.newHashMap();
+ BiMap<String, String> ipToARecord = HashBiMap.create();
+ Multimap<String, String> aRecordToCnames =
MultimapBuilder.hashKeys().arrayListValues().build();
+ Multimap<String, String> ipToAllNames =
MultimapBuilder.hashKeys().arrayListValues().build();
+
+ for (Map.Entry<String, Entity> e : hostnameToEntity.entries())
{
+ String domainName = e.getKey();
+ Maybe<SshMachineLocation> location =
Machines.findUniqueSshMachineLocation(e.getValue().getLocations());
+ if (!location.isPresent()) {
+ LOG.debug("Member {} of {} does not have an SSH
location so will not be configured", e.getValue(), this);
+ continue;
+ }
+ String address =
location.get().getAddress().getHostAddress();
+ ipToAllNames.put(address, domainName);
+ if (!ipToARecord.containsKey(address)) {
+ ipToARecord.put(address, domainName);
if (getReverseLookupNetwork().contains(new
Cidr(address + "/32"))) {
String octet =
Iterables.get(Splitter.on('.').split(address), 3);
- reverseMappings.putIfAbsent(hostname, octet);
- }
- if (getAttribute(Startable.SERVICE_UP)) {
- update();
+ if (!octetToName.containsKey(octet))
octetToName.put(octet, domainName);
}
- configure(machine);
- LOG.info("{} added at location {} with name {}", new
Object[] { member, machine, hostname });
+ } else {
+ aRecordToCnames.put(ipToARecord.get(address),
domainName);
}
}
- }
+ setAttribute(A_RECORDS,
ImmutableMap.copyOf(ipToARecord.inverse()));
+ setAttribute(PTR_RECORDS, ImmutableMap.copyOf(octetToName));
+ setAttribute(CNAME_RECORDS,
Multimaps.unmodifiableMultimap(aRecordToCnames));
+ setAttribute(ADDRESS_MAPPINGS,
Multimaps.unmodifiableMultimap(ipToAllNames));
+
+ // Update Bind configuration files and restart the service
+ getDriver().updateBindConfiguration();
+ }
}
- public void removed(Entity member) {
- synchronized (mutex) {
- Location location = findLocation(member);
- if (location != null) {
- entityLocations.remove(location, member);
- if (!entityLocations.containsKey(location)) {
-
addressMappings.remove(((MachineLocation)location).getAddress().getHostAddress());
- }
+ protected void configureResolver(Entity entity) {
+ Maybe<SshMachineLocation> machine =
Machines.findUniqueSshMachineLocation(entity.getLocations());
+ if (machine.isPresent()) {
+ if (getConfig(REPLACE_RESOLV_CONF)) {
+ machine.get().copyTo(new
StringReader(getConfig(RESOLV_CONF_TEMPLATE)), "/etc/resolv.conf");
+ } else {
+ appendTemplate(getConfig(INTERFACE_CONFIG_TEMPLATE),
"/etc/sysconfig/network-scripts/ifcfg-eth0", machine.get());
+ machine.get().execScript("reload network",
ImmutableList.of(BashCommands.sudo("service network reload")));
}
- update();
+ LOG.info("configured resolver on {}", machine);
+ } else {
+ LOG.debug("{} can't configure resolver at {}: no
SshMachineLocation", this, entity);
}
}
- private Location findLocation(Entity member) {
- // don't use member.getLocations(), because when being stopped the
location might not be set
- if (entityLocations.containsValue(member)) {
- for (Map.Entry<Location, Entity> entry :
entityLocations.entries()) {
- if (member.equals(entry.getValue())) {
- return entry.getKey();
- }
- }
- }
- return null;
+ protected void appendTemplate(String template, String destination,
SshMachineLocation machine) {
+ String content = ((BindDnsServerSshDriver)
getDriver()).processTemplate(template);
+ String temp = "/tmp/template-" + Strings.makeRandomId(6);
+ machine.copyTo(new ByteArrayInputStream(content.getBytes()), temp);
+ machine.execScript("updating file", ImmutableList.of(
+ BashCommands.sudo(String.format("tee -a %s < %s",
destination, temp)),
+ String.format("rm -f %s", temp)));
}
- public void update() {
- Optional<Location> location = Iterables.tryFind(getLocations(),
Predicates.instanceOf(SshMachineLocation.class));
- SshMachineLocation machine = (SshMachineLocation) location.get();
- copyTemplate(getConfig(NAMED_CONF_TEMPLATE), "/etc/named.conf",
machine);
- copyTemplate(getConfig(DOMAIN_ZONE_FILE_TEMPLATE),
"/var/named/domain.zone", machine);
- copyTemplate(getConfig(REVERSE_ZONE_FILE_TEMPLATE),
"/var/named/reverse.zone", machine);
- machine.execScript("restart bind",
ImmutableList.of(BashCommands.sudo("service named restart")));
- LOG.info("updated named configuration and zone file for '{}' on
{}", getDomainName(), this);
+ public Map<String, String> getAddressRecords() {
+ return getAttribute(A_RECORDS);
}
- public void configure(SshMachineLocation machine) {
- if (getConfig(REPLACE_RESOLV_CONF)) {
- copyTemplate(getConfig(RESOLV_CONF_TEMPLATE),
"/etc/resolv.conf", machine);
- } else {
- appendTemplate(getConfig(INTERFACE_CONFIG_TEMPLATE),
"/etc/sysconfig/network-scripts/ifcfg-eth0", machine);
- machine.execScript("reload network",
ImmutableList.of(BashCommands.sudo("service network reload")));
- }
- LOG.info("configured resolver on {}", machine);
+ public Multimap<String, String> getCanonicalNameRecords() {
+ return getAttribute(CNAME_RECORDS);
}
- public void copyTemplate(String template, String destination,
SshMachineLocation machine) {
- String content = ((BindDnsServerSshDriver)
getDriver()).processTemplate(template);
- String temp = "/tmp/template-" + Strings.makeRandomId(6);
- machine.copyTo(new ByteArrayInputStream(content.getBytes()), temp);
- machine.execScript("copying file",
ImmutableList.of(BashCommands.sudo(String.format("mv %s %s", temp,
destination))));
+ public Map<String, Collection<String>> getCnamesForTemplates() {
+ return getAttribute(CNAME_RECORDS).asMap();
}
- public void appendTemplate(String template, String destination,
SshMachineLocation machine) {
--- End diff --
The `appendTemplate` method might be kept, but in the parent, since it
seems useful?
---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---