Package org.platformlayer.ops.networks

Source Code of org.platformlayer.ops.networks.NetworkPoint

package org.platformlayer.ops.networks;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.UUID;

import org.platformlayer.InetAddressChooser;
import org.platformlayer.ops.OpsContext;
import org.platformlayer.ops.OpsException;
import org.platformlayer.ops.OpsTarget;
import org.platformlayer.ops.machines.InetAddressUtils;
import org.platformlayer.ops.packages.AsBlock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Objects;
import com.google.common.collect.Lists;

public class NetworkPoint {
  private static final Logger log = LoggerFactory.getLogger(NetworkPoint.class);

  final String privateNetworkId;
  final InetAddress address;

  // // For now, we assume there's one private network
  // public static final String PRIVATE_NETWORK_ID = "private";

  private NetworkPoint(String privateNetworkId, InetAddress address) {
    this.privateNetworkId = privateNetworkId;
    this.address = address;
  }

  // public static String getMyNetworkKey() {
  // // We assume we're on the private network
  // return PRIVATE_NETWORK_ID;
  // }

  // public static NetworkPoint forSameNetwork(InetAddress address) {
  // return new NetworkPoint(getMyNetworkKey(), address);
  // }

  public static NetworkPoint forSshAddress(InetAddress addr) {
    if (InetAddressUtils.isIpv6(addr)) {
      return new NetworkPoint(null, addr);
    }

    // This isn't technically required, but IPV6 means that we have a flat address space
    throw new IllegalStateException();
  }

  static InetAddress myAddress;

  public static NetworkPoint forMe() throws OpsException {
    if (myAddress == null) {
      List<InetAddress> localAddresses = InetAddressUtils.getLocalAddresses();

      List<InetAddress> valid = Lists.newArrayList();
      for (InetAddress localAddress : localAddresses) {
        if (InetAddressUtils.isIpv4(localAddress)) {
          continue;
        }

        if (localAddress.isLinkLocalAddress()) {
          continue;
        }
        if (localAddress.isLoopbackAddress()) {
          continue;
        }

        valid.add(localAddress);
      }

      InetAddress address = InetAddressChooser.preferIpv6().choose(valid);

      if (!InetAddressUtils.isIpv6(address)) {
        throw new OpsException("We must have an IPV6 address");
      }
      myAddress = address;
    }

    return new NetworkPoint(null, myAddress);
  }

  public static NetworkPoint forTarget(OpsTarget target) {
    return target.getNetworkPoint();
  }

  public static NetworkPoint forPublicInternet() {
    return new NetworkPoint(null, null);
  }

  public static NetworkPoint forAddress(InetAddress address) {
    String privateNetwork = null;
    if (!InetAddressUtils.isPublic(address)) {
      throw new IllegalStateException();
      // log.warn("Assigning fake private-network id for non-public IP");
      // // Assign a unique private network
      // privateNetwork = UUID.randomUUID().toString();
    }
    return new NetworkPoint(privateNetwork, address);
  }

  public static NetworkPoint forPublicHostname(InetAddress address) {
    String privateNetwork = null;
    if (!InetAddressUtils.isPublic(address)) {
      log.warn("Assigning fake private-network id for non-public IP");
      // Assign a unique private network
      privateNetwork = UUID.randomUUID().toString();
    }
    return new NetworkPoint(privateNetwork, address);
  }

  public static NetworkPoint forPublicHostname(String hostname) throws OpsException {
    InetAddress address;
    try {
      address = InetAddress.getByName(hostname);
    } catch (UnknownHostException e) {
      throw new OpsException("Error resolving hostname", e);
    }

    return forPublicHostname(address);
  }

  public static NetworkPoint forTargetInContext() {
    OpsTarget target = OpsContext.get().getInstance(OpsTarget.class);

    return forTarget(target);
  }

  private String getPrivateNetworkId() {
    return privateNetworkId;
  }

  private InetAddress getAddress() {
    return address;
  }

  public boolean isPublicAddress() {
    return this.privateNetworkId == null;
  }

  // private static NetworkPoint forNetwork(String network) {
  // return new NetworkPoint(network, null);
  // }

  @Override
  public String toString() {
    return "NetworkPoint [privateNetworkId=" + privateNetworkId + ", address=" + address.getHostAddress() + "]";
  }

  public List<InetAddress> findAddresses(NetworkPoint src) {
    List<InetAddress> reachables = Lists.newArrayList();

    if (Objects.equal(src.getPrivateNetworkId(), getPrivateNetworkId())) {
      reachables.add(getAddress());
    } else if (isPublicAddress()) {
      reachables.add(getAddress());
    }
    return reachables;
  }

  public static int estimateDistance(NetworkPoint a, NetworkPoint b) {
    if (a.equals(b)) {
      return 0;
    }

    if (a.isPublicAddress() != b.isPublicAddress()) {
      // We need to download from A and then upload to B, so d(A, Me) + d(Me, B)
      // TODO: This is a poor metric. Our metric isn't really rich enough here
      return 8;
    }

    AsBlock asA = AsBlock.find(a.getAddress());
    AsBlock asB = AsBlock.find(b.getAddress());

    if (asA != null && asB != null) {
      if (asA.equals(asB)) {
        return 1;
      }

      if (Objects.equal(asA.getCountry(), asB.getCountry())) {
        return 2;
      }
    }

    return 4;
  }

  public InetAddress findBestAddress(NetworkPoint src, InetAddressChooser chooser) throws OpsException {
    List<InetAddress> addresses = findAddresses(src);
    InetAddress address = chooser.choose(addresses);
    return address;
  }

  public InetAddress getBestAddress(NetworkPoint src, InetAddressChooser chooser) throws OpsException {
    InetAddress address = findBestAddress(src, chooser);

    if (address == null) {
      throw new OpsException("Cannot determine appropriate network address");
    }

    return address;
  }

  public String getBestAddress(NetworkPoint src) throws OpsException {
    InetAddressChooser chooser;
    if (!src.isPublicAddress()) {
      chooser = InetAddressChooser.preferIpv6();
    } else {
      chooser = InetAddressChooser.preferIpv4();
    }

    InetAddress address = getBestAddress(src, chooser);
    if (address == null) {
      return null;
    }
    return address.getHostAddress();
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((address == null) ? 0 : address.hashCode());
    result = prime * result + ((privateNetworkId == null) ? 0 : privateNetworkId.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    NetworkPoint other = (NetworkPoint) obj;
    if (address == null) {
      if (other.address != null) {
        return false;
      }
    } else if (!address.equals(other.address)) {
      return false;
    }
    if (privateNetworkId == null) {
      if (other.privateNetworkId != null) {
        return false;
      }
    } else if (!privateNetworkId.equals(other.privateNetworkId)) {
      return false;
    }
    return true;
  }

}
TOP

Related Classes of org.platformlayer.ops.networks.NetworkPoint

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.