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); } } }