Madan Jampani
Committed by Gerrit Code Review

Using provider pattern for cluster metadata.

Change-Id: I5a572b3df9149be959dde9868a9c594dec26a3e0
...@@ -20,10 +20,10 @@ import java.util.Collection; ...@@ -20,10 +20,10 @@ import java.util.Collection;
20 import java.util.Set; 20 import java.util.Set;
21 import java.util.stream.Collectors; 21 import java.util.stream.Collectors;
22 22
23 -import org.apache.commons.collections.CollectionUtils; 23 +import org.onosproject.net.Provided;
24 +import org.onosproject.net.provider.ProviderId;
24 25
25 import static com.google.common.base.Preconditions.checkNotNull; 26 import static com.google.common.base.Preconditions.checkNotNull;
26 -import static com.google.common.base.Verify.verifyNotNull;
27 import static com.google.common.base.Verify.verify; 27 import static com.google.common.base.Verify.verify;
28 28
29 import com.google.common.base.MoreObjects; 29 import com.google.common.base.MoreObjects;
...@@ -38,21 +38,49 @@ import com.google.common.collect.Sets; ...@@ -38,21 +38,49 @@ import com.google.common.collect.Sets;
38 * of {@link org.onosproject.cluster.ControllerNode nodes} and the collection of data 38 * of {@link org.onosproject.cluster.ControllerNode nodes} and the collection of data
39 * {@link org.onosproject.cluster.Partition partitions}. 39 * {@link org.onosproject.cluster.Partition partitions}.
40 */ 40 */
41 -public final class ClusterMetadata { 41 +public final class ClusterMetadata implements Provided {
42 42
43 // Name to use when the ClusterMetadataService is in transient state 43 // Name to use when the ClusterMetadataService is in transient state
44 public static final String NO_NAME = ""; 44 public static final String NO_NAME = "";
45 45
46 - private String name; 46 + private final ProviderId providerId;
47 - private Set<ControllerNode> nodes; 47 + private final String name;
48 - private Set<Partition> partitions; 48 + private final Set<ControllerNode> nodes;
49 + private final Set<Partition> partitions;
50 +
51 + private ClusterMetadata() {
52 + providerId = null;
53 + name = null;
54 + nodes = null;
55 + partitions = null;
56 + }
57 +
58 + public ClusterMetadata(ProviderId providerId,
59 + String name,
60 + Set<ControllerNode> nodes,
61 + Set<Partition> partitions) {
62 + this.providerId = checkNotNull(providerId);
63 + this.name = checkNotNull(name);
64 + this.nodes = ImmutableSet.copyOf(checkNotNull(nodes));
65 + // verify that partitions are constituted from valid cluster nodes.
66 + boolean validPartitions = Collections2.transform(nodes, ControllerNode::id)
67 + .containsAll(partitions
68 + .stream()
69 + .flatMap(r -> r.getMembers().stream())
70 + .collect(Collectors.toSet()));
71 + verify(validPartitions, "Partition locations must be valid cluster nodes");
72 + this.partitions = ImmutableSet.copyOf(checkNotNull(partitions));
73 + }
49 74
50 - /** 75 + public ClusterMetadata(String name,
51 - * Returns a new cluster metadata builder. 76 + Set<ControllerNode> nodes,
52 - * @return The cluster metadata builder. 77 + Set<Partition> partitions) {
53 - */ 78 + this(new ProviderId("none", "none"), name, nodes, partitions);
54 - public static Builder builder() { 79 + }
55 - return new Builder(); 80 +
81 + @Override
82 + public ProviderId providerId() {
83 + return providerId;
56 } 84 }
57 85
58 /** 86 /**
...@@ -84,6 +112,7 @@ public final class ClusterMetadata { ...@@ -84,6 +112,7 @@ public final class ClusterMetadata {
84 @Override 112 @Override
85 public String toString() { 113 public String toString() {
86 return MoreObjects.toStringHelper(ClusterMetadata.class) 114 return MoreObjects.toStringHelper(ClusterMetadata.class)
115 + .add("providerId", providerId)
87 .add("name", name) 116 .add("name", name)
88 .add("nodes", nodes) 117 .add("nodes", nodes)
89 .add("partitions", partitions) 118 .add("partitions", partitions)
...@@ -92,7 +121,7 @@ public final class ClusterMetadata { ...@@ -92,7 +121,7 @@ public final class ClusterMetadata {
92 121
93 @Override 122 @Override
94 public int hashCode() { 123 public int hashCode() {
95 - return Arrays.deepHashCode(new Object[] {name, nodes, partitions}); 124 + return Arrays.deepHashCode(new Object[] {providerId, name, nodes, partitions});
96 } 125 }
97 126
98 /* 127 /*
...@@ -116,74 +145,4 @@ public final class ClusterMetadata { ...@@ -116,74 +145,4 @@ public final class ClusterMetadata {
116 return Sets.symmetricDifference(this.nodes, that.nodes).isEmpty() 145 return Sets.symmetricDifference(this.nodes, that.nodes).isEmpty()
117 && Sets.symmetricDifference(this.partitions, that.partitions).isEmpty(); 146 && Sets.symmetricDifference(this.partitions, that.partitions).isEmpty();
118 } 147 }
119 -
120 - /**
121 - * Builder for a {@link ClusterMetadata} instance.
122 - */
123 - public static class Builder {
124 -
125 - private final ClusterMetadata metadata;
126 -
127 - public Builder() {
128 - metadata = new ClusterMetadata();
129 - }
130 -
131 - /**
132 - * Sets the cluster name, returning the cluster metadata builder for method chaining.
133 - * @param name cluster name
134 - * @return this cluster metadata builder
135 - */
136 - public Builder withName(String name) {
137 - metadata.name = checkNotNull(name);
138 - return this;
139 - }
140 -
141 - /**
142 - * Sets the collection of cluster nodes, returning the cluster metadata builder for method chaining.
143 - * @param controllerNodes collection of cluster nodes
144 - * @return this cluster metadata builder
145 - */
146 - public Builder withControllerNodes(Collection<ControllerNode> controllerNodes) {
147 - metadata.nodes = ImmutableSet.copyOf(checkNotNull(controllerNodes));
148 - return this;
149 - }
150 -
151 - /**
152 - * Sets the partitions, returning the cluster metadata builder for method chaining.
153 - * @param partitions collection of partitions
154 - * @return this cluster metadata builder
155 - */
156 - public Builder withPartitions(Collection<Partition> partitions) {
157 - metadata.partitions = ImmutableSet.copyOf(checkNotNull(partitions));
158 - return this;
159 - }
160 -
161 - /**
162 - * Builds the cluster metadata.
163 - * @return cluster metadata
164 - * @throws com.google.common.base.VerifyException VerifyException if the metadata is misconfigured
165 - */
166 - public ClusterMetadata build() {
167 - verifyMetadata();
168 - return metadata;
169 - }
170 -
171 - /**
172 - * Validates the constructed metadata for semantic correctness.
173 - * @throws VerifyException if the metadata is misconfigured.
174 - */
175 - private void verifyMetadata() {
176 - verifyNotNull(metadata.getName(), "Cluster name must be specified");
177 - verify(CollectionUtils.isNotEmpty(metadata.getNodes()), "Cluster nodes must be specified");
178 - verify(CollectionUtils.isNotEmpty(metadata.getPartitions()), "Cluster partitions must be specified");
179 -
180 - // verify that partitions are constituted from valid cluster nodes.
181 - boolean validPartitions = Collections2.transform(metadata.getNodes(), ControllerNode::id)
182 - .containsAll(metadata.getPartitions()
183 - .stream()
184 - .flatMap(r -> r.getMembers().stream())
185 - .collect(Collectors.toSet()));
186 - verify(validPartitions, "Partition locations must be valid cluster nodes");
187 - }
188 - }
189 } 148 }
......
1 /* 1 /*
2 - * Copyright 2015 Open Networking Laboratory 2 + * Copyright 2015-2016 Open Networking Laboratory
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
...@@ -15,27 +15,31 @@ ...@@ -15,27 +15,31 @@
15 */ 15 */
16 package org.onosproject.cluster; 16 package org.onosproject.cluster;
17 17
18 -import java.util.Collection; 18 +import java.util.Set;
19 19
20 -import org.onosproject.store.Store; 20 +import org.onosproject.net.provider.Provider;
21 import org.onosproject.store.service.Versioned; 21 import org.onosproject.store.service.Versioned;
22 22
23 /** 23 /**
24 - * Manages persistence of {@link ClusterMetadata cluster metadata}; not intended for direct use. 24 + * Abstraction of a {@link ClusterMetadata cluster metadata} provider.
25 */ 25 */
26 -public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, ClusterMetadataStoreDelegate> { 26 +public interface ClusterMetadataProvider extends Provider {
27 27
28 /** 28 /**
29 - * Returns the cluster metadata. 29 + * Tells if this provider is currently available and therefore can provide ClusterMetadata.
30 - * <p> 30 + * @return {@code true} if this provider is available and can provide cluster metadata.
31 - * The retuned metadata is encapsulated as a {@link Versioned versioned} and therefore has a specific version. 31 + */
32 + boolean isAvailable();
33 +
34 + /**
35 + * Returns the current cluster metadata.
32 * @return cluster metadata 36 * @return cluster metadata
33 */ 37 */
34 Versioned<ClusterMetadata> getClusterMetadata(); 38 Versioned<ClusterMetadata> getClusterMetadata();
35 39
36 /** 40 /**
37 - * Updates the cluster metadata. 41 + * Updates cluster metadata.
38 - * @param metadata new metadata value 42 + * @param metadata new metadata
39 */ 43 */
40 void setClusterMetadata(ClusterMetadata metadata); 44 void setClusterMetadata(ClusterMetadata metadata);
41 45
...@@ -54,12 +58,12 @@ public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, Cluste ...@@ -54,12 +58,12 @@ public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, Cluste
54 /** 58 /**
55 * Removes a controller node from the list of active members for a partition. 59 * Removes a controller node from the list of active members for a partition.
56 * @param partitionId partition identifier 60 * @param partitionId partition identifier
57 - * @param nodeId id of controller node 61 + * @param nodeId identifier of controller node
58 */ 62 */
59 void removeActivePartitionMember(PartitionId partitionId, NodeId nodeId); 63 void removeActivePartitionMember(PartitionId partitionId, NodeId nodeId);
60 64
61 /** 65 /**
62 - * Returns the collection of controller nodes that are the active members for a partition. 66 + * Returns the set of controller nodes that are the active members for a partition.
63 * <p> 67 * <p>
64 * Active members of a partition are typically those that are actively 68 * Active members of a partition are typically those that are actively
65 * participating in the data replication protocol being employed. When 69 * participating in the data replication protocol being employed. When
...@@ -72,5 +76,5 @@ public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, Cluste ...@@ -72,5 +76,5 @@ public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, Cluste
72 * @param partitionId partition identifier 76 * @param partitionId partition identifier
73 * @return identifiers of controller nodes that are active members 77 * @return identifiers of controller nodes that are active members
74 */ 78 */
75 - Collection<NodeId> getActivePartitionMembers(PartitionId partitionId); 79 + Set<NodeId> getActivePartitionMembers(PartitionId partitionId);
76 } 80 }
......
1 /* 1 /*
2 - * Copyright 2015 Open Networking Laboratory 2 + * Copyright 2015-2016 Open Networking Laboratory
3 * 3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 5 * you may not use this file except in compliance with the License.
...@@ -15,10 +15,11 @@ ...@@ -15,10 +15,11 @@
15 */ 15 */
16 package org.onosproject.cluster; 16 package org.onosproject.cluster;
17 17
18 -import org.onosproject.store.StoreDelegate; 18 +import org.onosproject.net.provider.ProviderRegistry;
19 19
20 /** 20 /**
21 - * Cluster metadata store delegate abstraction. 21 + * Abstraction of a cluster metadata provider registry.
22 */ 22 */
23 -public interface ClusterMetadataStoreDelegate extends StoreDelegate<ClusterMetadataEvent> { 23 +public interface ClusterMetadataProviderRegistry
24 + extends ProviderRegistry<ClusterMetadataProvider, ClusterMetadataProviderService> {
24 } 25 }
......
1 +/*
2 + * Copyright 2015-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.cluster;
17 +
18 +import org.onosproject.net.provider.ProviderService;
19 +import org.onosproject.store.service.Versioned;
20 +
21 +/**
22 + * Service through which a {@link ClusterMetadataProvider provider} can notify core of
23 + * updates made to cluster metadata.
24 + */
25 +public interface ClusterMetadataProviderService extends ProviderService<ClusterMetadataProvider> {
26 +
27 + /**
28 + * Notifies about a change to cluster metadata.
29 + * @param newMetadata new cluster metadata value
30 + */
31 + void clusterMetadataChanged(Versioned<ClusterMetadata> newMetadata);
32 +
33 + /**
34 + * Notifies that a node just become the active member of a partition.
35 + * @param partitionId partition identifier
36 + * @param nodeId identifier of node
37 + */
38 + void newActiveMemberForPartition(PartitionId partitionId, NodeId nodeId);
39 +}
...@@ -108,4 +108,14 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -108,4 +108,14 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
108 return providersByScheme.get(deviceId.uri().getScheme()); 108 return providersByScheme.get(deviceId.uri().getScheme());
109 } 109 }
110 110
111 + /**
112 + * Returns the provider registered with the specified scheme.
113 + *
114 + * @param scheme provider scheme
115 + * @return provider
116 + */
117 + protected synchronized P getProvider(String scheme) {
118 + return providersByScheme.get(scheme);
119 + }
120 +
111 } 121 }
......
...@@ -42,7 +42,6 @@ import org.onosproject.event.AbstractListenerManager; ...@@ -42,7 +42,6 @@ import org.onosproject.event.AbstractListenerManager;
42 import org.slf4j.Logger; 42 import org.slf4j.Logger;
43 43
44 import com.google.common.collect.Collections2; 44 import com.google.common.collect.Collections2;
45 -import com.google.common.collect.Lists;
46 import com.google.common.collect.Sets; 45 import com.google.common.collect.Sets;
47 46
48 import java.util.ArrayList; 47 import java.util.ArrayList;
...@@ -139,11 +138,7 @@ public class ClusterManager ...@@ -139,11 +138,7 @@ public class ClusterManager
139 checkNotNull(nodes, "Nodes cannot be null"); 138 checkNotNull(nodes, "Nodes cannot be null");
140 checkArgument(!nodes.isEmpty(), "Nodes cannot be empty"); 139 checkArgument(!nodes.isEmpty(), "Nodes cannot be empty");
141 140
142 - ClusterMetadata metadata = ClusterMetadata.builder() 141 + ClusterMetadata metadata = new ClusterMetadata("default", nodes, buildDefaultPartitions(nodes));
143 - .withName("default")
144 - .withControllerNodes(nodes)
145 - .withPartitions(buildDefaultPartitions(nodes))
146 - .build();
147 clusterMetadataAdminService.setClusterMetadata(metadata); 142 clusterMetadataAdminService.setClusterMetadata(metadata);
148 try { 143 try {
149 log.warn("Shutting down container for cluster reconfiguration!"); 144 log.warn("Shutting down container for cluster reconfiguration!");
...@@ -175,10 +170,10 @@ public class ClusterManager ...@@ -175,10 +170,10 @@ public class ClusterManager
175 } 170 }
176 } 171 }
177 172
178 - private static Collection<Partition> buildDefaultPartitions(Collection<ControllerNode> nodes) { 173 + private static Set<Partition> buildDefaultPartitions(Collection<ControllerNode> nodes) {
179 List<ControllerNode> sorted = new ArrayList<>(nodes); 174 List<ControllerNode> sorted = new ArrayList<>(nodes);
180 Collections.sort(sorted, (o1, o2) -> o1.id().toString().compareTo(o2.id().toString())); 175 Collections.sort(sorted, (o1, o2) -> o1.id().toString().compareTo(o2.id().toString()));
181 - Collection<Partition> partitions = Lists.newArrayList(); 176 + Set<Partition> partitions = Sets.newHashSet();
182 // add p0 partition 177 // add p0 partition
183 partitions.add(new DefaultPartition(PartitionId.from(0), 178 partitions.add(new DefaultPartition(PartitionId.from(0),
184 Sets.newHashSet(Collections2.transform(nodes, ControllerNode::id)))); 179 Sets.newHashSet(Collections2.transform(nodes, ControllerNode::id))));
......
...@@ -21,81 +21,117 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -21,81 +21,117 @@ import static org.slf4j.LoggerFactory.getLogger;
21 import java.net.InetAddress; 21 import java.net.InetAddress;
22 import java.net.NetworkInterface; 22 import java.net.NetworkInterface;
23 import java.net.SocketException; 23 import java.net.SocketException;
24 +import java.net.URI;
25 +import java.net.URISyntaxException;
24 import java.util.Collection; 26 import java.util.Collection;
25 import java.util.Enumeration; 27 import java.util.Enumeration;
26 28
27 import org.apache.felix.scr.annotations.Activate; 29 import org.apache.felix.scr.annotations.Activate;
28 import org.apache.felix.scr.annotations.Component; 30 import org.apache.felix.scr.annotations.Component;
29 import org.apache.felix.scr.annotations.Deactivate; 31 import org.apache.felix.scr.annotations.Deactivate;
30 -import org.apache.felix.scr.annotations.Reference;
31 -import org.apache.felix.scr.annotations.ReferenceCardinality;
32 import org.apache.felix.scr.annotations.Service; 32 import org.apache.felix.scr.annotations.Service;
33 import org.onlab.packet.IpAddress; 33 import org.onlab.packet.IpAddress;
34 import org.onosproject.cluster.ClusterMetadata; 34 import org.onosproject.cluster.ClusterMetadata;
35 import org.onosproject.cluster.ClusterMetadataAdminService; 35 import org.onosproject.cluster.ClusterMetadataAdminService;
36 import org.onosproject.cluster.ClusterMetadataEvent; 36 import org.onosproject.cluster.ClusterMetadataEvent;
37 import org.onosproject.cluster.ClusterMetadataEventListener; 37 import org.onosproject.cluster.ClusterMetadataEventListener;
38 +import org.onosproject.cluster.ClusterMetadataProvider;
39 +import org.onosproject.cluster.ClusterMetadataProviderRegistry;
40 +import org.onosproject.cluster.ClusterMetadataProviderService;
38 import org.onosproject.cluster.ClusterMetadataService; 41 import org.onosproject.cluster.ClusterMetadataService;
39 -import org.onosproject.cluster.ClusterMetadataStore;
40 -import org.onosproject.cluster.ClusterMetadataStoreDelegate;
41 import org.onosproject.cluster.ControllerNode; 42 import org.onosproject.cluster.ControllerNode;
42 -import org.onosproject.event.AbstractListenerManager; 43 +import org.onosproject.cluster.NodeId;
44 +import org.onosproject.cluster.PartitionId;
45 +import org.onosproject.net.provider.AbstractListenerProviderRegistry;
46 +import org.onosproject.net.provider.AbstractProviderService;
43 import org.onosproject.store.service.Versioned; 47 import org.onosproject.store.service.Versioned;
44 import org.slf4j.Logger; 48 import org.slf4j.Logger;
45 49
50 +import com.google.common.base.Throwables;
51 +
46 /** 52 /**
47 * Implementation of ClusterMetadataService. 53 * Implementation of ClusterMetadataService.
48 */ 54 */
49 @Component(immediate = true) 55 @Component(immediate = true)
50 @Service 56 @Service
51 public class ClusterMetadataManager 57 public class ClusterMetadataManager
52 - extends AbstractListenerManager<ClusterMetadataEvent, ClusterMetadataEventListener> 58 + extends AbstractListenerProviderRegistry<ClusterMetadataEvent,
53 - implements ClusterMetadataService, ClusterMetadataAdminService { 59 + ClusterMetadataEventListener,
60 + ClusterMetadataProvider,
61 + ClusterMetadataProviderService>
62 + implements ClusterMetadataService, ClusterMetadataAdminService, ClusterMetadataProviderRegistry {
54 63
55 private final Logger log = getLogger(getClass()); 64 private final Logger log = getLogger(getClass());
56 private ControllerNode localNode; 65 private ControllerNode localNode;
57 66
58 - private ClusterMetadataStoreDelegate delegate = new InternalStoreDelegate();
59 -
60 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 - protected ClusterMetadataStore store;
62 -
63 @Activate 67 @Activate
64 public void activate() { 68 public void activate() {
65 - store.setDelegate(delegate); 69 + // FIXME: Need to ensure all cluster metadata providers are registered before we activate
66 eventDispatcher.addSink(ClusterMetadataEvent.class, listenerRegistry); 70 eventDispatcher.addSink(ClusterMetadataEvent.class, listenerRegistry);
67 - establishSelfIdentity();
68 log.info("Started"); 71 log.info("Started");
69 } 72 }
70 73
71 @Deactivate 74 @Deactivate
72 public void deactivate() { 75 public void deactivate() {
73 - store.unsetDelegate(delegate);
74 eventDispatcher.removeSink(ClusterMetadataEvent.class); 76 eventDispatcher.removeSink(ClusterMetadataEvent.class);
75 log.info("Stopped"); 77 log.info("Stopped");
76 } 78 }
77 79
78 @Override 80 @Override
79 public ClusterMetadata getClusterMetadata() { 81 public ClusterMetadata getClusterMetadata() {
80 - return Versioned.valueOrElse(store.getClusterMetadata(), null); 82 + Versioned<ClusterMetadata> metadata = getProvider().getClusterMetadata();
83 + return metadata.value();
84 + }
85 +
86 +
87 + @Override
88 + protected ClusterMetadataProviderService createProviderService(
89 + ClusterMetadataProvider provider) {
90 + return new InternalClusterMetadataProviderService(provider);
81 } 91 }
82 92
83 @Override 93 @Override
84 public ControllerNode getLocalNode() { 94 public ControllerNode getLocalNode() {
95 + if (localNode == null) {
96 + establishSelfIdentity();
97 + }
85 return localNode; 98 return localNode;
86 } 99 }
87 100
88 @Override 101 @Override
89 public void setClusterMetadata(ClusterMetadata metadata) { 102 public void setClusterMetadata(ClusterMetadata metadata) {
90 checkNotNull(metadata, "Cluster metadata cannot be null"); 103 checkNotNull(metadata, "Cluster metadata cannot be null");
91 - store.setClusterMetadata(metadata); 104 + ClusterMetadataProvider primaryProvider = getPrimaryProvider();
105 + if (primaryProvider == null) {
106 + throw new IllegalStateException("Missing primary provider. Cannot update cluster metadata");
107 + }
108 + primaryProvider.setClusterMetadata(metadata);
92 } 109 }
93 110
94 - // Store delegate to re-post events emitted from the store. 111 + /**
95 - private class InternalStoreDelegate implements ClusterMetadataStoreDelegate { 112 + * Returns the provider to use for fetching cluster metadata.
96 - @Override 113 + * @return cluster metadata provider
97 - public void notify(ClusterMetadataEvent event) { 114 + */
98 - post(event); 115 + private ClusterMetadataProvider getProvider() {
116 + ClusterMetadataProvider primaryProvider = getPrimaryProvider();
117 + if (primaryProvider != null && primaryProvider.isAvailable()) {
118 + return primaryProvider;
119 + }
120 + log.warn("Primary cluster metadata provider not available. Using default fallback.");
121 + return getProvider("default");
122 + }
123 +
124 + /**
125 + * Returns the primary provider for cluster metadata.
126 + * @return primary cluster metadata provider
127 + */
128 + private ClusterMetadataProvider getPrimaryProvider() {
129 + try {
130 + URI uri = new URI(System.getProperty("onos.cluster.metadata.uri", "config:///cluster.json"));
131 + return getProvider(uri.getScheme());
132 + } catch (URISyntaxException e) {
133 + Throwables.propagate(e);
134 + return null;
99 } 135 }
100 } 136 }
101 137
...@@ -129,4 +165,25 @@ public class ClusterMetadataManager ...@@ -129,4 +165,25 @@ public class ClusterMetadataManager
129 throw new IllegalStateException("Cannot determine local IP", e); 165 throw new IllegalStateException("Cannot determine local IP", e);
130 } 166 }
131 } 167 }
168 +
169 + private class InternalClusterMetadataProviderService
170 + extends AbstractProviderService<ClusterMetadataProvider>
171 + implements ClusterMetadataProviderService {
172 +
173 + InternalClusterMetadataProviderService(ClusterMetadataProvider provider) {
174 + super(provider);
175 + }
176 +
177 + @Override
178 + public void clusterMetadataChanged(Versioned<ClusterMetadata> newMetadata) {
179 + log.info("Cluster metadata changed. New metadata: {}", newMetadata);
180 + post(new ClusterMetadataEvent(ClusterMetadataEvent.Type.METADATA_CHANGED, newMetadata.value()));
181 + }
182 +
183 + @Override
184 + public void newActiveMemberForPartition(PartitionId partitionId, NodeId nodeId) {
185 + log.info("Node {} is active member for partition {}", nodeId, partitionId);
186 + // TODO: notify listeners
187 + }
188 + }
132 } 189 }
...\ No newline at end of file ...\ No newline at end of file
......
1 +/*
2 + * Copyright 2015-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.cluster.impl;
17 +
18 +import static java.net.NetworkInterface.getNetworkInterfaces;
19 +import static org.slf4j.LoggerFactory.getLogger;
20 +
21 +import java.net.Inet4Address;
22 +import java.net.InetAddress;
23 +import java.net.NetworkInterface;
24 +import java.util.Collections;
25 +import java.util.Set;
26 +import java.util.concurrent.atomic.AtomicReference;
27 +import java.util.function.Function;
28 +
29 +import org.apache.felix.scr.annotations.Activate;
30 +import org.apache.felix.scr.annotations.Component;
31 +import org.apache.felix.scr.annotations.Deactivate;
32 +import org.apache.felix.scr.annotations.Reference;
33 +import org.apache.felix.scr.annotations.ReferenceCardinality;
34 +import org.onlab.packet.IpAddress;
35 +import org.onosproject.cluster.ClusterMetadata;
36 +import org.onosproject.cluster.ClusterMetadataProvider;
37 +import org.onosproject.cluster.ClusterMetadataProviderRegistry;
38 +import org.onosproject.cluster.ControllerNode;
39 +import org.onosproject.cluster.DefaultControllerNode;
40 +import org.onosproject.cluster.DefaultPartition;
41 +import org.onosproject.cluster.NodeId;
42 +import org.onosproject.cluster.Partition;
43 +import org.onosproject.cluster.PartitionId;
44 +import org.onosproject.net.provider.ProviderId;
45 +import org.onosproject.store.service.Versioned;
46 +import org.slf4j.Logger;
47 +
48 +import com.google.common.collect.ImmutableSet;
49 +import com.google.common.collect.Sets;
50 +
51 +/**
52 + * Provider of default {@link ClusterMetadata cluster metadata}.
53 + */
54 +@Component(immediate = true)
55 +public class DefaultClusterMetadataProvider implements ClusterMetadataProvider {
56 +
57 + private final Logger log = getLogger(getClass());
58 +
59 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
60 + protected ClusterMetadataProviderRegistry providerRegistry;
61 +
62 + private static final String ONOS_IP = "ONOS_IP";
63 + private static final String ONOS_INTERFACE = "ONOS_INTERFACE";
64 + private static final String ONOS_ALLOW_IPV6 = "ONOS_ALLOW_IPV6";
65 + private static final String DEFAULT_ONOS_INTERFACE = "eth0";
66 + private static final int DEFAULT_ONOS_PORT = 9876;
67 + private static final ProviderId PROVIDER_ID = new ProviderId("default", "none");
68 + private AtomicReference<Versioned<ClusterMetadata>> cachedMetadata = new AtomicReference<>();
69 +
70 + @Activate
71 + public void activate() {
72 + String localIp = getSiteLocalAddress();
73 + ControllerNode localNode =
74 + new DefaultControllerNode(new NodeId(localIp), IpAddress.valueOf(localIp), DEFAULT_ONOS_PORT);
75 + // p0 partition
76 + Partition basePartition = new DefaultPartition(PartitionId.from(0), Sets.newHashSet(localNode.id()));
77 + // p1 partition
78 + Partition extendedPartition = new DefaultPartition(PartitionId.from(1), Sets.newHashSet(localNode.id()));
79 + ClusterMetadata metadata = new ClusterMetadata(PROVIDER_ID,
80 + "default",
81 + ImmutableSet.of(localNode),
82 + ImmutableSet.of(basePartition, extendedPartition));
83 + long version = System.currentTimeMillis();
84 + cachedMetadata.set(new Versioned<>(metadata, version));
85 + providerRegistry.register(this);
86 + log.info("Started");
87 + }
88 +
89 + @Deactivate
90 + public void deactivate() {
91 + providerRegistry.unregister(this);
92 + log.info("Stopped");
93 + }
94 +
95 + @Override
96 + public ProviderId id() {
97 + return PROVIDER_ID;
98 + }
99 +
100 + @Override
101 + public Versioned<ClusterMetadata> getClusterMetadata() {
102 + return cachedMetadata.get();
103 + }
104 +
105 + @Override
106 + public void setClusterMetadata(ClusterMetadata metadata) {
107 + throw new UnsupportedOperationException();
108 + }
109 +
110 + @Override
111 + public void addActivePartitionMember(PartitionId partitionId, NodeId nodeId) {
112 + throw new UnsupportedOperationException();
113 + }
114 +
115 + @Override
116 + public void removeActivePartitionMember(PartitionId partitionId, NodeId nodeId) {
117 + throw new UnsupportedOperationException();
118 + }
119 +
120 + @Override
121 + public Set<NodeId> getActivePartitionMembers(PartitionId partitionId) {
122 + throw new UnsupportedOperationException();
123 + }
124 +
125 + @Override
126 + public boolean isAvailable() {
127 + return true;
128 + }
129 +
130 + private static String getSiteLocalAddress() {
131 +
132 + /*
133 + * If the IP ONOS should use is set via the environment variable we will assume it is valid and should be used.
134 + * Setting the IP address takes presidence over setting the interface via the environment.
135 + */
136 + String useOnosIp = System.getenv(ONOS_IP);
137 + if (useOnosIp != null) {
138 + return useOnosIp;
139 + }
140 +
141 + // Read environment variables for IP interface information or set to default
142 + String useOnosInterface = System.getenv(ONOS_INTERFACE);
143 + if (useOnosInterface == null) {
144 + useOnosInterface = DEFAULT_ONOS_INTERFACE;
145 + }
146 +
147 + // Capture if they want to limit IP address selection to only IPv4 (default).
148 + boolean allowIPv6 = (System.getenv(ONOS_ALLOW_IPV6) != null);
149 +
150 + Function<NetworkInterface, IpAddress> ipLookup = nif -> {
151 + IpAddress fallback = null;
152 +
153 + // nif can be null if the interface name specified doesn't exist on the node's host
154 + if (nif != null) {
155 + for (InetAddress address : Collections.list(nif.getInetAddresses())) {
156 + if (address.isSiteLocalAddress() && (allowIPv6 || address instanceof Inet4Address)) {
157 + return IpAddress.valueOf(address);
158 + }
159 + if (fallback == null && !address.isLoopbackAddress() && !address.isMulticastAddress()
160 + && (allowIPv6 || address instanceof Inet4Address)) {
161 + fallback = IpAddress.valueOf(address);
162 + }
163 + }
164 + }
165 + return fallback;
166 + };
167 + try {
168 + IpAddress ip = ipLookup.apply(NetworkInterface.getByName(useOnosInterface));
169 + if (ip != null) {
170 + return ip.toString();
171 + }
172 + for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
173 + if (!nif.getName().equals(useOnosInterface)) {
174 + ip = ipLookup.apply(nif);
175 + if (ip != null) {
176 + return ip.toString();
177 + }
178 + }
179 + }
180 + } catch (Exception e) {
181 + throw new IllegalStateException("Unable to get network interfaces", e);
182 + }
183 +
184 + return IpAddress.valueOf(InetAddress.getLoopbackAddress()).toString();
185 + }
186 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -954,10 +954,9 @@ public class LldpLinkProviderTest { ...@@ -954,10 +954,9 @@ public class LldpLinkProviderTest {
954 final NodeId nid = new NodeId("test-node"); 954 final NodeId nid = new NodeId("test-node");
955 final IpAddress addr = IpAddress.valueOf(0); 955 final IpAddress addr = IpAddress.valueOf(0);
956 final Partition p = new DefaultPartition(PartitionId.from(1), Sets.newHashSet(nid)); 956 final Partition p = new DefaultPartition(PartitionId.from(1), Sets.newHashSet(nid));
957 - return ClusterMetadata.builder() 957 + return new ClusterMetadata("test-cluster",
958 - .withName("test-cluster") 958 + Sets.newHashSet(new DefaultControllerNode(nid, addr)),
959 - .withControllerNodes(Sets.newHashSet(new DefaultControllerNode(nid, addr))) 959 + Sets.newHashSet(p));
960 - .withPartitions(Sets.newHashSet(p)).build();
961 } 960 }
962 961
963 @Override 962 @Override
......