import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.Reader;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import org.argeo.api.cms.CmsConstants;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsState;
-import org.argeo.api.uuid.UuidFactory;
+import org.argeo.api.uuid.NodeIdSupplier;
+import org.argeo.api.uuid.UuidBinaryUtils;
import org.argeo.cms.CmsDeployProperty;
import org.argeo.cms.auth.ident.IdentClient;
+import org.argeo.cms.util.DigestUtils;
import org.argeo.cms.util.FsUtils;
import org.argeo.cms.util.OS;
/**
* Implementation of a {@link CmsState}, initialising the required services.
*/
-public class CmsStateImpl implements CmsState {
+public class CmsStateImpl implements CmsState, NodeIdSupplier {
private final static CmsLog log = CmsLog.getLog(CmsStateImpl.class);
// REFERENCES
private UUID uuid;
// private final boolean cleanState;
private String hostname;
+ private InetAddress inetAddress;
- private UuidFactory uuidFactory;
+// private UuidFactory uuidFactory;
private final Map<CmsDeployProperty, String> deployPropertyDefaults;
if (log.isTraceEnabled())
log.trace("CMS State started");
- this.uuid = uuidFactory.timeUUID();
+ String frameworkUuid = KernelUtils.getFrameworkProp(KernelUtils.OSGI_FRAMEWORK_UUID);
+ this.uuid = frameworkUuid != null ? UUID.fromString(frameworkUuid) : UUID.randomUUID();
// hostname
this.hostname = getDeployProperty(CmsDeployProperty.HOST);
final String LOCALHOST_IP = "::1";
ForkJoinTask<String> hostnameFJT = ForkJoinPool.commonPool().submit(() -> {
try {
- String hostname = InetAddress.getLocalHost().getHostName();
+ this.inetAddress = InetAddress.getLocalHost();
+ String hostname = this.inetAddress.getHostName();
return hostname;
} catch (UnknownHostException e) {
throw new IllegalStateException("Cannot get local hostname", e);
this.hostname = LOCALHOST_IP;
log.warn("Could not get local hostname, using " + this.hostname);
}
+ } else {
+ InetAddress[] addresses = InetAddress.getAllByName(this.hostname);
+ InetAddress selectedAddr = null;
+ addresses: for (InetAddress addr : addresses) {
+ if (selectedAddr == null)
+ selectedAddr = addr;
+ if (selectedAddr instanceof Inet6Address)
+ break addresses;
+ }
+ this.inetAddress = selectedAddr;
}
availableSince = System.currentTimeMillis();
}
}
}
- log.debug("## CMS starting... (" + uuid + ")\n" + sb + "\n");
+ log.debug("## CMS starting on " + hostname + " ... (" + uuid + ")\n" + sb + "\n");
}
if (log.isTraceEnabled()) {
} catch (RuntimeException | IOException e) {
log.error("## FATAL: CMS state failed", e);
+ throw new IllegalStateException(e);
}
}
log.debug("CMS stopping... (" + this.uuid + ")");
long duration = ((System.currentTimeMillis() - availableSince) / 1000) / 60;
- log.info("## ARGEO CMS STOPPED after " + (duration / 60) + "h " + (duration % 60) + "min uptime ##");
+ log.info("## ARGEO CMS " + uuid + " STOPPED after " + (duration / 60) + "h " + (duration % 60)
+ + "min uptime ##");
}
private void firstInit() throws IOException {
return availableSince;
}
+ /*
+ * NodeID supplier
+ */
+
+ @Override
+ public Long get() {
+ return NodeIdSupplier.toNodeIdBase(getIpBytes());
+ }
+
+ /** Returns an SHA1 digest of one of the IP addresses. */
+ protected byte[] getIpBytes() {
+// Enumeration<NetworkInterface> netInterfaces = null;
+// try {
+// netInterfaces = NetworkInterface.getNetworkInterfaces();
+// } catch (SocketException e) {
+// throw new IllegalStateException(e);
+// }
+//
+// InetAddress selectedIpv6 = null;
+// InetAddress selectedIpv4 = null;
+// if (netInterfaces != null) {
+// netInterfaces: while (netInterfaces.hasMoreElements()) {
+// NetworkInterface netInterface = netInterfaces.nextElement();
+// byte[] hardwareAddress = null;
+// try {
+// hardwareAddress = netInterface.getHardwareAddress();
+// if (hardwareAddress != null) {
+// // first IPv6
+// addr: for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) {
+// InetAddress ip = addr.getAddress();
+// if (ip instanceof Inet6Address) {
+// Inet6Address ipv6 = (Inet6Address) ip;
+// if (ipv6.isAnyLocalAddress() || ipv6.isLinkLocalAddress() || ipv6.isLoopbackAddress())
+// continue addr;
+// selectedIpv6 = ipv6;
+// break netInterfaces;
+// }
+//
+// }
+// // then IPv4
+// addr: for (InterfaceAddress addr : netInterface.getInterfaceAddresses()) {
+// InetAddress ip = addr.getAddress();
+// if (ip instanceof Inet4Address) {
+// Inet4Address ipv4 = (Inet4Address) ip;
+// if (ipv4.isAnyLocalAddress() || ipv4.isLinkLocalAddress() || ipv4.isLoopbackAddress())
+// continue addr;
+// selectedIpv4 = ipv4;
+// // we keep searching for IPv6
+// }
+//
+// }
+// }
+// } catch (SocketException e) {
+// throw new IllegalStateException(e);
+// }
+// }
+// }
+// InetAddress selectedIp = selectedIpv6 != null ? selectedIpv6 : selectedIpv4;
+ if (this.inetAddress.isLoopbackAddress()) {
+ log.warn("No IP address found, using a random node id for UUID generation");
+ return NodeIdSupplier.randomNodeId();
+ }
+ InetAddress selectedIp = this.inetAddress;
+ byte[] digest = DigestUtils.sha1(selectedIp.getAddress());
+ log.debug("Use IP " + selectedIp + " hashed as " + UuidBinaryUtils.toHexString(digest) + " as node id");
+ byte[] nodeId = NodeIdSupplier.toNodeIdBytes(digest, 0);
+ // marks that this is not based on MAC address
+ NodeIdSupplier.forceToNoMacAddress(nodeId, 0);
+ return nodeId;
+ }
+
/*
* ACCESSORS
*/
return uuid;
}
- public void setUuidFactory(UuidFactory uuidFactory) {
- this.uuidFactory = uuidFactory;
- }
+// public void setUuidFactory(UuidFactory uuidFactory) {
+// this.uuidFactory = uuidFactory;
+// }
public String getHostname() {
return hostname;
// TODO make passphrase more configurable
return new IdentClient(remoteAddr);
}
+
}