diff options
Diffstat (limited to 'framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java')
-rw-r--r-- | framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java new file mode 100644 index 00000000..9f6c4130 --- /dev/null +++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java @@ -0,0 +1,221 @@ +package org.onosproject.store.cluster.impl; + +import static com.google.common.base.Preconditions.checkNotNull; +import static java.net.NetworkInterface.getNetworkInterfaces; +import static org.slf4j.LoggerFactory.getLogger; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Service; +import org.onlab.packet.IpAddress; +import org.onosproject.cluster.ClusterMetadata; +import org.onosproject.cluster.ClusterMetadataEvent; +import org.onosproject.cluster.ClusterMetadataStore; +import org.onosproject.cluster.ClusterMetadataStoreDelegate; +import org.onosproject.cluster.ControllerNode; +import org.onosproject.cluster.DefaultControllerNode; +import org.onosproject.cluster.NodeId; +import org.onosproject.cluster.Partition; +import org.onosproject.store.AbstractStore; +import org.onosproject.store.service.Versioned; +import org.slf4j.Logger; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.google.common.base.Throwables; +import com.google.common.collect.Lists; +import com.google.common.io.Files; + +/** + * ClusterMetadataStore backed by a local file. + */ +@Component(immediate = true, enabled = true) +@Service +public class StaticClusterMetadataStore + extends AbstractStore<ClusterMetadataEvent, ClusterMetadataStoreDelegate> + implements ClusterMetadataStore { + + private final Logger log = getLogger(getClass()); + private static final String CLUSTER_METADATA_FILE = "../config/cluster.json"; + private static final int DEFAULT_ONOS_PORT = 9876; + private final File metadataFile = new File(CLUSTER_METADATA_FILE); + private AtomicReference<ClusterMetadata> metadata = new AtomicReference<>(); + private ObjectMapper mapper; + private long version; + + @Activate + public void activate() { + mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule(); + module.addSerializer(NodeId.class, new NodeIdSerializer()); + module.addDeserializer(NodeId.class, new NodeIdDeserializer()); + module.addSerializer(ControllerNode.class, new ControllerNodeSerializer()); + module.addDeserializer(ControllerNode.class, new ControllerNodeDeserializer()); + mapper.registerModule(module); + File metadataFile = new File(CLUSTER_METADATA_FILE); + if (metadataFile.exists()) { + try { + metadata.set(mapper.readValue(metadataFile, ClusterMetadata.class)); + version = metadataFile.lastModified(); + } catch (IOException e) { + Throwables.propagate(e); + } + } else { + String localIp = getSiteLocalAddress(); + ControllerNode localNode = + new DefaultControllerNode(new NodeId(localIp), IpAddress.valueOf(localIp), DEFAULT_ONOS_PORT); + metadata.set(ClusterMetadata.builder() + .withName("default") + .withControllerNodes(Arrays.asList(localNode)) + .withPartitions(Lists.newArrayList(new Partition("p1", Lists.newArrayList(localNode.id())))) + .build()); + version = System.currentTimeMillis(); + } + log.info("Started"); + } + + @Deactivate + public void deactivate() { + log.info("Stopped"); + } + + @Override + public void setDelegate(ClusterMetadataStoreDelegate delegate) { + checkNotNull(delegate, "Delegate cannot be null"); + this.delegate = delegate; + } + + @Override + public void unsetDelegate(ClusterMetadataStoreDelegate delegate) { + this.delegate = null; + } + + @Override + public boolean hasDelegate() { + return this.delegate != null; + } + + @Override + public Versioned<ClusterMetadata> getClusterMetadata() { + return new Versioned<>(metadata.get(), version); + } + + @Override + public void setClusterMetadata(ClusterMetadata metadata) { + checkNotNull(metadata); + try { + Files.createParentDirs(metadataFile); + mapper.writeValue(metadataFile, metadata); + this.metadata.set(metadata); + } catch (IOException e) { + Throwables.propagate(e); + } + } + + @Override + public void setActiveReplica(String partitionId, NodeId nodeId) { + throw new UnsupportedOperationException(); + } + + @Override + public void unsetActiveReplica(String partitionId, NodeId nodeId) { + throw new UnsupportedOperationException(); + } + + @Override + public Collection<NodeId> getActiveReplicas(String partitionId) { + return metadata.get().getPartitions() + .stream() + .filter(r -> r.getName().equals(partitionId)) + .findFirst() + .map(r -> r.getMembers()) + .orElse(null); + } + + private static class ControllerNodeSerializer extends JsonSerializer<ControllerNode> { + @Override + public void serialize(ControllerNode node, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeStringField("id", node.id().toString()); + jgen.writeStringField("ip", node.ip().toString()); + jgen.writeNumberField("port", node.tcpPort()); + jgen.writeEndObject(); + } + } + + private static class ControllerNodeDeserializer extends JsonDeserializer<ControllerNode> { + @Override + public ControllerNode deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + JsonNode node = jp.getCodec().readTree(jp); + NodeId nodeId = new NodeId(node.get("id").textValue()); + IpAddress ip = IpAddress.valueOf(node.get("ip").textValue()); + int port = node.get("port").asInt(); + return new DefaultControllerNode(nodeId, ip, port); + } + } + + private static class NodeIdSerializer extends JsonSerializer<NodeId> { + @Override + public void serialize(NodeId nodeId, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + jgen.writeString(nodeId.toString()); + } + } + + private class NodeIdDeserializer extends JsonDeserializer<NodeId> { + @Override + public NodeId deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + JsonNode node = jp.getCodec().readTree(jp); + return new NodeId(node.asText()); + } + } + + + private static String getSiteLocalAddress() { + Function<NetworkInterface, IpAddress> ipLookup = nif -> { + for (InetAddress address : Collections.list(nif.getInetAddresses())) { + if (address.isSiteLocalAddress()) { + return IpAddress.valueOf(address); + } + } + return null; + }; + try { + IpAddress ip = ipLookup.apply(NetworkInterface.getByName("eth0")); + if (ip != null) { + return ip.toString(); + } + for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) { + ip = ipLookup.apply(nif); + if (ip != null) { + return ip.toString(); + } + } + } catch (Exception e) { + throw new IllegalStateException("Unable to get network interfaces", e); + } + return IpAddress.valueOf(InetAddress.getLoopbackAddress()).toString(); + } +}
\ No newline at end of file |