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, Iterables.toString(availableEntities));
      ImmutableListMultimap<String, Entity> hostnameToEntity =
          Multimaps.index(availableEntities, new HostnameTransformer());

      Map<String, String> octetToName = Maps.newHashMap();
      BiMap<String, String> ipToARecord = HashBiMap.create();
      Multimap<String, String> aRecordToCnames = MultimapBuilder.hashKeys().hashSetValues().build();
      Multimap<String, String> ipToAllNames = MultimapBuilder.hashKeys().hashSetValues().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;
        } else if (ipToARecord.inverse().containsKey(domainName)) {
          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);
            if (!octetToName.containsKey(octet)) octetToName.put(octet, domainName);
          }
        } 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 List<String> scanSlaves(JsonArray slaves) throws UnknownHostException {
    List<String> slaveIds = MutableList.<String>of();
    for (int i = 0; i < slaves.size(); i++) {
      JsonObject slave = slaves.get(i).getAsJsonObject();
      boolean active = slave.get("active").getAsBoolean();
      String id = slave.get("id").getAsString();
      String hostname = slave.get("hostname").getAsString();
      Double registered = slave.get("registered_time").getAsDouble();
      Group group = sensors().get(MESOS_SLAVES);

      Optional<Entity> entity =
          Iterables.tryFind(
              group.getMembers(),
              Predicates.compose(
                  Predicates.equalTo(id), EntityFunctions.attribute(MesosSlave.MESOS_SLAVE_ID)));
      if (entity.isPresent()) {
        Entity found = entity.get();
        found.sensors().set(MesosSlave.SLAVE_ACTIVE, active);
        if (!active) {
          Lifecycle state = found.sensors().get(Attributes.SERVICE_STATE_ACTUAL);
          if (Lifecycle.ON_FIRE.equals(state) || Lifecycle.STARTING.equals(state)) {
            continue;
          } else if (Lifecycle.STOPPING.equals(state) || Lifecycle.STOPPED.equals(state)) {
            group.removeMember(found);
            group.removeChild(found);
            Entities.unmanage(found);
          } else {
            ServiceStateLogic.setExpectedState(found, Lifecycle.STOPPING);
          }
        }
      } else if (active) {
        LocationSpec<SshMachineLocation> spec =
            LocationSpec.create(SshMachineLocation.class)
                .configure(SshMachineLocation.SSH_HOST, hostname)
                .configure("address", InetAddress.getByName(hostname))
                .displayName(hostname);
        if (config().get(MESOS_SLAVE_ACCESSIBLE)) {
          spec.configure(CloudLocationConfig.WAIT_FOR_SSHABLE, "true")
              .configure(SshMachineLocation.DETECT_MACHINE_DETAILS, true)
              .configure(SshMachineLocation.SSH_PORT, config().get(MesosSlave.SLAVE_SSH_PORT))
              .configure(LocationConfigKeys.USER, config().get(MesosSlave.SLAVE_SSH_USER))
              .configure(LocationConfigKeys.PASSWORD, config().get(MesosSlave.SLAVE_SSH_PASSWORD))
              .configure(SshTool.PROP_PASSWORD, config().get(MesosSlave.SLAVE_SSH_PASSWORD))
              .configure(SshTool.PROP_PORT, config().get(MesosSlave.SLAVE_SSH_PORT))
              .configure(
                  LocationConfigKeys.PRIVATE_KEY_DATA,
                  config().get(MesosSlave.SLAVE_SSH_PRIVATE_KEY_DATA))
              .configure(
                  LocationConfigKeys.PRIVATE_KEY_FILE,
                  config().get(MesosSlave.SLAVE_SSH_PRIVATE_KEY_FILE));
        } else {
          spec.configure(CloudLocationConfig.WAIT_FOR_SSHABLE, "false")
              .configure(SshMachineLocation.DETECT_MACHINE_DETAILS, false);
        }
        SshMachineLocation machine =
            getManagementContext().getLocationManager().createLocation(spec);

        // Setup port forwarding
        MarathonPortForwarder portForwarder = new MarathonPortForwarder();
        portForwarder.setManagementContext(getManagementContext());

        EntitySpec<MesosSlave> slaveSpec =
            EntitySpec.create(MesosSlave.class)
                .configure(MesosSlave.MESOS_SLAVE_ID, id)
                .configure(MesosSlave.REGISTERED_AT, registered.longValue())
                .configure(MesosSlave.MESOS_CLUSTER, this)
                .displayName("Mesos Slave (" + hostname + ")");
        MesosSlave added = sensors().get(MESOS_SLAVES).addMemberChild(slaveSpec);
        added.sensors().set(MesosSlave.SLAVE_ACTIVE, active);
        added.sensors().set(MesosSlave.HOSTNAME, hostname);
        added.sensors().set(MesosSlave.ADDRESS, hostname);

        added.start(ImmutableList.of(machine));
        portForwarder.init(hostname, this);

        // Setup subnet tier
        SubnetTier subnetTier =
            added.addChild(
                EntitySpec.create(SubnetTier.class)
                    .configure(SubnetTier.PORT_FORWARDER, portForwarder)
                    .configure(SubnetTier.SUBNET_CIDR, Cidr.UNIVERSAL));
        Entities.start(subnetTier, ImmutableList.of(machine));
        added.sensors().set(MesosSlave.SUBNET_TIER, subnetTier);
      }

      if (active) slaveIds.add(id);
    }
    return slaveIds;
  }