package io.fathom.cloud.cluster;
import java.io.File;
import java.io.IOException;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fathomdb.utils.Hex;
import com.google.common.collect.Lists;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
public class MachineSignature {
private static final Logger log = LoggerFactory.getLogger(MachineSignature.class);
// We try to generate a key that will be the same even if multiple
// concurrent processes on the machine generate the same key
public String generateKey() {
List<String> material = Lists.newArrayList();
Enumeration<NetworkInterface> networkInterfaces;
try {
networkInterfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException e) {
throw new IllegalStateException("Error listing network interfaces", e);
}
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
try {
byte[] hardwareAddress = networkInterface.getHardwareAddress();
if (hardwareAddress != null) {
material.add("mac:" + networkInterface.getName() + ":" + Hex.toHex(hardwareAddress));
} else {
log.warn("No hardware address for {}", networkInterface.getName());
}
} catch (SocketException e) {
throw new IllegalStateException("Unable to get hardware address for: " + networkInterface.getName(), e);
}
// List<InterfaceAddress> interfaceAddresses = networkInterface
// .getInterfaceAddresses();
// for (InterfaceAddress interfaceAddress : interfaceAddresses) {
// material.add("mac:" + interfaceAddress.)
// }
}
String hostname = LocalMachineInfo.getHostname();
hostname = hostname.trim();
material.add("hostname:" + hostname);
// TODO: Any more for the mix??
File cpuinfoFile = new File("/proc/cpuinfo");
if (cpuinfoFile.exists()) {
material.add(computeFileHash(cpuinfoFile));
} else {
log.info("/proc/cpuinfo file not found; won't include in machine signature");
}
Collections.sort(material);
Hasher hasher = Hashing.md5().newHasher();
for (String s : material) {
hasher.putString(s);
hasher.putByte((byte) 0);
}
return hostname + "_" + hasher.hash().toString();
}
private String computeFileHash(File path) {
try {
byte[] contents = Files.toByteArray(path);
String hash = Hashing.md5().hashBytes(contents).toString();
return "filehash:" + path + ":" + hash;
} catch (IOException e) {
throw new IllegalStateException("Unable to read file " + path, e);
}
}
}