diff options
Diffstat (limited to 'framework/src/onos/core/api/src/main/java/org/onosproject/cluster')
10 files changed, 504 insertions, 50 deletions
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java index 5f2b5fff..47944874 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java @@ -30,9 +30,8 @@ public interface ClusterAdminService { * instance. * * @param nodes set of nodes that form the cluster - * @param ipPrefix IP address prefix, e.g. 10.0.1.* */ - void formCluster(Set<ControllerNode> nodes, String ipPrefix); + void formCluster(Set<ControllerNode> nodes); /** * Adds a new controller node to the cluster. diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java deleted file mode 100644 index 1ee78b15..00000000 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.cluster; - -import java.util.Set; - -/** - * Service for obtaining the static definition of a controller cluster. - */ -public interface ClusterDefinitionService { - - /** - * Returns the local controller node. - * @return local controller node - */ - ControllerNode localNode(); - - /** - * Returns the set of seed nodes that should be used for discovering other members - * of the cluster. - * @return set of seed controller nodes - */ - Set<ControllerNode> seedNodes(); - - /** - * Forms cluster configuration based on the specified set of node - * information. Assumes subsequent restart for the new configuration to - * take hold. - * - * @param nodes set of nodes that form the cluster - * @param ipPrefix IP address prefix, e.g. 10.0.1.* - */ - void formCluster(Set<ControllerNode> nodes, String ipPrefix); -}
\ No newline at end of file diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java new file mode 100644 index 00000000..e1eacfee --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java @@ -0,0 +1,185 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cluster; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Verify.verifyNotNull; +import static com.google.common.base.Verify.verify; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +/** + * Cluster metadata. + * <p> + * Metadata specifies the attributes that define a ONOS cluster and comprises the collection + * of {@link org.onosproject.cluster.ControllerNode nodes} and the collection of data + * {@link org.onosproject.cluster.Partition partitions}. + */ +public final class ClusterMetadata { + + private String name; + private Set<ControllerNode> nodes; + private Set<Partition> partitions; + + /** + * Returns a new cluster metadata builder. + * @return The cluster metadata builder. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Returns the name of the cluster. + * + * @return cluster name + */ + public String getName() { + return this.name; + } + + /** + * Returns the collection of {@link org.onosproject.cluster.ControllerNode nodes} that make up the cluster. + * @return cluster nodes + */ + public Collection<ControllerNode> getNodes() { + return this.nodes; + } + + /** + * Returns the collection of data {@link org.onosproject.cluster.Partition partitions} that make up the cluster. + * @return collection of partitions. + */ + public Collection<Partition> getPartitions() { + return this.partitions; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(ClusterMetadata.class) + .add("name", name) + .add("nodes", nodes) + .add("partitions", partitions) + .toString(); + } + + @Override + public int hashCode() { + return Arrays.deepHashCode(new Object[] {name, nodes, partitions}); + } + + /* + * Provide a deep quality check of the meta data (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object object) { + + if (!ClusterMetadata.class.isInstance(object)) { + return false; + } + ClusterMetadata that = (ClusterMetadata) object; + + if (!this.name.equals(that.name) || this.nodes.size() != that.nodes.size() + || this.partitions.size() != that.partitions.size()) { + return false; + } + + return Sets.symmetricDifference(this.nodes, that.nodes).isEmpty() + && Sets.symmetricDifference(this.partitions, that.partitions).isEmpty(); + } + + /** + * Builder for a {@link ClusterMetadata} instance. + */ + public static class Builder { + + private final ClusterMetadata metadata; + + public Builder() { + metadata = new ClusterMetadata(); + } + + /** + * Sets the cluster name, returning the cluster metadata builder for method chaining. + * @param name cluster name + * @return this cluster metadata builder + */ + public Builder withName(String name) { + metadata.name = checkNotNull(name); + return this; + } + + /** + * Sets the collection of cluster nodes, returning the cluster metadata builder for method chaining. + * @param controllerNodes collection of cluster nodes + * @return this cluster metadata builder + */ + public Builder withControllerNodes(Collection<ControllerNode> controllerNodes) { + metadata.nodes = ImmutableSet.copyOf(checkNotNull(controllerNodes)); + return this; + } + + /** + * Sets the collection of data partitions, returning the cluster metadata builder for method chaining. + * @param partitions collection of partitions + * @return this cluster metadata builder + */ + public Builder withPartitions(Collection<Partition> partitions) { + metadata.partitions = ImmutableSet.copyOf(checkNotNull(partitions)); + return this; + } + + /** + * Builds the cluster metadata. + * @return cluster metadata + * @throws com.google.common.base.VerifyException VerifyException if the metadata is misconfigured + */ + public ClusterMetadata build() { + verifyMetadata(); + return metadata; + } + + /** + * Validates the constructed metadata for semantic correctness. + * @throws VerifyException if the metadata is misconfigured. + */ + private void verifyMetadata() { + verifyNotNull(metadata.getName(), "Cluster name must be specified"); + verifyNotNull(metadata.getNodes(), "Cluster nodes must be specified"); + verifyNotNull(metadata.getPartitions(), "Cluster partitions must be specified"); + verify(!metadata.getNodes().isEmpty(), "Cluster nodes must not be empty"); + verify(!metadata.getPartitions().isEmpty(), "Cluster nodes must not be empty"); + + // verify that partitions are constituted from valid cluster nodes. + boolean validPartitions = Collections2.transform(metadata.getNodes(), ControllerNode::id) + .containsAll(metadata.getPartitions() + .stream() + .flatMap(r -> r.getMembers().stream()) + .collect(Collectors.toSet())); + verify(validPartitions, "Partition locations must be valid cluster nodes"); + } + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java new file mode 100644 index 00000000..a0f461c4 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java @@ -0,0 +1,56 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cluster; + +import org.onosproject.event.AbstractEvent; + +/** + * Describes a cluster metadata event. + */ +public class ClusterMetadataEvent extends AbstractEvent<ClusterMetadataEvent.Type, ClusterMetadata> { + + /** + * Type of cluster metadata events. + */ + public enum Type { + /** + * Signifies that the cluster metadata has changed. + */ + METADATA_CHANGED, + } + + /** + * Creates an event of a given type and for the specified metadata and the + * current time. + * + * @param type cluster metadata event type + * @param metadata cluster metadata subject + */ + public ClusterMetadataEvent(Type type, ClusterMetadata metadata) { + super(type, metadata); + } + + /** + * Creates an event of a given type and for the specified metadata and time. + * + * @param type cluster metadata event type + * @param metadata cluster metadata subject + * @param time occurrence time + */ + public ClusterMetadataEvent(Type type, ClusterMetadata metadata, long time) { + super(type, metadata, time); + } +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java new file mode 100644 index 00000000..fdfaeed0 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cluster; + +import org.onosproject.event.EventListener; + +/** + * Entity capable of receiving cluster metadata related events. + */ +public interface ClusterMetadataEventListener extends EventListener<ClusterMetadataEvent> { +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java new file mode 100644 index 00000000..25a6df63 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cluster; + +/** + * Service for obtaining metadata information about the cluster. + */ +public interface ClusterMetadataService { + + /** + * Returns the current cluster metadata. + * @return cluster metadata + */ + ClusterMetadata getClusterMetadata(); + + /** + * Updates the cluster metadata. + * @param metadata new metadata + */ + void setClusterMetadata(ClusterMetadata metadata); + + /** + * Returns the local controller node representing this instance. + * @return local controller node + */ + ControllerNode getLocalNode(); +} diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java new file mode 100644 index 00000000..7e83b5b5 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java @@ -0,0 +1,77 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cluster; + +import java.util.Collection; + +import org.onosproject.store.Store; +import org.onosproject.store.service.Versioned; + +/** + * Manages persistence of cluster metadata; not intended for direct use. + */ +public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, ClusterMetadataStoreDelegate> { + + /** + * Returns the cluster metadata. + * <p> + * The returned metadata is versioned to aid determining if a metadata instance is more recent than another. + * @return cluster metadata + */ + Versioned<ClusterMetadata> getClusterMetadata(); + + /** + * Updates the cluster metadata. + * @param metadata new metadata value + */ + void setClusterMetadata(ClusterMetadata metadata); + + // TODO: The below methods should move to a separate store interface that is responsible for + // tracking cluster partition operational state. + + /** + * Sets a controller node as an active member of a partition. + * <p> + * Active members are those replicas that are up to speed with the rest of the system and are + * usually capable of participating in the replica state management activities in accordance with + * the data consistency and replication protocol in use. + * @param partitionId partition identifier + * @param nodeId id of controller node + */ + void setActiveReplica(String partitionId, NodeId nodeId); + + /** + * Removes a controller node as an active member for a partition. + * <p> + * Active members are those replicas that are up to speed with the rest of the system and are + * usually capable of participating in the replica state management activities in accordance with + * the data consistency and replication protocol in use. + * @param partitionId partition identifier + * @param nodeId id of controller node + */ + void unsetActiveReplica(String partitionId, NodeId nodeId); + + /** + * Returns the collection of controller nodes that are the active replicas for a partition. + * <p> + * Active members are those replicas that are up to speed with the rest of the system and are + * usually capable of participating in the replica state management activities in accordance with + * the data consistency and replication protocol in use. + * @param partitionId partition identifier + * @return identifiers of controller nodes that are the active replicas + */ + Collection<NodeId> getActiveReplicas(String partitionId); +}
\ No newline at end of file diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java new file mode 100644 index 00000000..b56b7a24 --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cluster; + +import org.onosproject.store.StoreDelegate; + +/** + * Cluster metadata store delegate abstraction. + */ +public interface ClusterMetadataStoreDelegate extends StoreDelegate<ClusterMetadataEvent> { +}
\ No newline at end of file diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java index 68b490f2..6cfb42c7 100644 --- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java @@ -20,7 +20,7 @@ import java.util.Objects; /** * Controller cluster identity. */ -public class NodeId { +public class NodeId implements Comparable<NodeId> { private final String id; @@ -55,4 +55,9 @@ public class NodeId { return id; } + @Override + public int compareTo(NodeId that) { + return this.id.compareTo(that.id); + } + } diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java new file mode 100644 index 00000000..1eca4aeb --- /dev/null +++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java @@ -0,0 +1,91 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cluster; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * A data partition. + * <p> + * Partition represents a slice of the data space and is made up of a collection + * of {@link org.onosproject.cluster.ControllerNode nodes} + * that all maintain copies of this data. + */ +public class Partition { + + private final String name; + private final Set<NodeId> members; + + private Partition() { + name = null; + members = null; + } + + public Partition(String name, Collection<NodeId> members) { + this.name = checkNotNull(name); + this.members = ImmutableSet.copyOf(checkNotNull(members)); + } + + /** + * Returns the partition name. + * <p> + * Each partition is identified by a unique name. + * @return partition name + */ + public String getName() { + return this.name; + } + + /** + * Returns the collection of controller node identifiers that make up this partition. + * @return collection of controller node identifiers + */ + public Collection<NodeId> getMembers() { + return this.members; + } + + @Override + public int hashCode() { + return Arrays.deepHashCode(new Object[] {name, members}); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + + if (other == null || !Partition.class.isInstance(other)) { + return false; + } + + Partition that = (Partition) other; + + if (!this.name.equals(that.name) || (this.members == null && that.members != null) + || (this.members != null && that.members == null) || this.members.size() != that.members.size()) { + return false; + } + + return Sets.symmetricDifference(this.members, that.members).isEmpty(); + } +}
\ No newline at end of file |