blob: f655fcc861650a030cb39e8c9f7e9fbb937da654 [file] [log] [blame]
Madan Jampaniab7e7cd2016-01-14 14:02:32 -08001/*
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 */
Madan Jampaniec1df022015-10-13 21:23:03 -070016package org.onosproject.cluster.impl;
17
18import static com.google.common.base.Preconditions.checkNotNull;
19import static org.slf4j.LoggerFactory.getLogger;
20
21import java.net.InetAddress;
Madan Jampanif172d402016-03-04 00:56:38 -080022import java.net.MalformedURLException;
Madan Jampaniec1df022015-10-13 21:23:03 -070023import java.net.NetworkInterface;
24import java.net.SocketException;
Madan Jampanif172d402016-03-04 00:56:38 -080025import java.net.URL;
Madan Jampaniec1df022015-10-13 21:23:03 -070026import java.util.Collection;
27import java.util.Enumeration;
28
29import org.apache.felix.scr.annotations.Activate;
30import org.apache.felix.scr.annotations.Component;
31import org.apache.felix.scr.annotations.Deactivate;
Madan Jampaniec1df022015-10-13 21:23:03 -070032import org.apache.felix.scr.annotations.Service;
33import org.onlab.packet.IpAddress;
34import org.onosproject.cluster.ClusterMetadata;
Madan Jampaniab7e7cd2016-01-14 14:02:32 -080035import org.onosproject.cluster.ClusterMetadataAdminService;
Madan Jampaniec1df022015-10-13 21:23:03 -070036import org.onosproject.cluster.ClusterMetadataEvent;
37import org.onosproject.cluster.ClusterMetadataEventListener;
Madan Jampaniad3c5262016-01-20 00:50:17 -080038import org.onosproject.cluster.ClusterMetadataProvider;
39import org.onosproject.cluster.ClusterMetadataProviderRegistry;
40import org.onosproject.cluster.ClusterMetadataProviderService;
Madan Jampaniec1df022015-10-13 21:23:03 -070041import org.onosproject.cluster.ClusterMetadataService;
Madan Jampaniec1df022015-10-13 21:23:03 -070042import org.onosproject.cluster.ControllerNode;
Madan Jampaniad3c5262016-01-20 00:50:17 -080043import org.onosproject.cluster.NodeId;
44import org.onosproject.cluster.PartitionId;
45import org.onosproject.net.provider.AbstractListenerProviderRegistry;
46import org.onosproject.net.provider.AbstractProviderService;
Madan Jampaniec1df022015-10-13 21:23:03 -070047import org.onosproject.store.service.Versioned;
48import org.slf4j.Logger;
49
50/**
51 * Implementation of ClusterMetadataService.
52 */
53@Component(immediate = true)
54@Service
55public class ClusterMetadataManager
Madan Jampaniad3c5262016-01-20 00:50:17 -080056 extends AbstractListenerProviderRegistry<ClusterMetadataEvent,
57 ClusterMetadataEventListener,
58 ClusterMetadataProvider,
59 ClusterMetadataProviderService>
60 implements ClusterMetadataService, ClusterMetadataAdminService, ClusterMetadataProviderRegistry {
Madan Jampaniec1df022015-10-13 21:23:03 -070061
Madan Jampaniec1df022015-10-13 21:23:03 -070062 private final Logger log = getLogger(getClass());
Madan Jampaniab7e7cd2016-01-14 14:02:32 -080063 private ControllerNode localNode;
Madan Jampaniec1df022015-10-13 21:23:03 -070064
Madan Jampaniec1df022015-10-13 21:23:03 -070065 @Activate
66 public void activate() {
Madan Jampaniad3c5262016-01-20 00:50:17 -080067 // FIXME: Need to ensure all cluster metadata providers are registered before we activate
Madan Jampaniec1df022015-10-13 21:23:03 -070068 eventDispatcher.addSink(ClusterMetadataEvent.class, listenerRegistry);
Madan Jampaniec1df022015-10-13 21:23:03 -070069 log.info("Started");
70 }
71
72 @Deactivate
73 public void deactivate() {
Madan Jampaniec1df022015-10-13 21:23:03 -070074 eventDispatcher.removeSink(ClusterMetadataEvent.class);
75 log.info("Stopped");
76 }
77
78 @Override
79 public ClusterMetadata getClusterMetadata() {
Madan Jampaniad3c5262016-01-20 00:50:17 -080080 Versioned<ClusterMetadata> metadata = getProvider().getClusterMetadata();
81 return metadata.value();
82 }
83
84
85 @Override
86 protected ClusterMetadataProviderService createProviderService(
87 ClusterMetadataProvider provider) {
88 return new InternalClusterMetadataProviderService(provider);
Madan Jampaniec1df022015-10-13 21:23:03 -070089 }
90
91 @Override
92 public ControllerNode getLocalNode() {
Madan Jampaniad3c5262016-01-20 00:50:17 -080093 if (localNode == null) {
94 establishSelfIdentity();
95 }
Madan Jampaniec1df022015-10-13 21:23:03 -070096 return localNode;
97 }
98
99 @Override
100 public void setClusterMetadata(ClusterMetadata metadata) {
101 checkNotNull(metadata, "Cluster metadata cannot be null");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800102 ClusterMetadataProvider primaryProvider = getPrimaryProvider();
103 if (primaryProvider == null) {
104 throw new IllegalStateException("Missing primary provider. Cannot update cluster metadata");
105 }
106 primaryProvider.setClusterMetadata(metadata);
Madan Jampaniec1df022015-10-13 21:23:03 -0700107 }
108
Madan Jampaniad3c5262016-01-20 00:50:17 -0800109 /**
110 * Returns the provider to use for fetching cluster metadata.
111 * @return cluster metadata provider
112 */
113 private ClusterMetadataProvider getProvider() {
114 ClusterMetadataProvider primaryProvider = getPrimaryProvider();
115 if (primaryProvider != null && primaryProvider.isAvailable()) {
116 return primaryProvider;
117 }
118 log.warn("Primary cluster metadata provider not available. Using default fallback.");
119 return getProvider("default");
120 }
121
122 /**
123 * Returns the primary provider for cluster metadata.
124 * @return primary cluster metadata provider
125 */
126 private ClusterMetadataProvider getPrimaryProvider() {
Madan Jampanif172d402016-03-04 00:56:38 -0800127 String metadataUri = System.getProperty("onos.cluster.metadata.uri");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800128 try {
Madan Jampanif172d402016-03-04 00:56:38 -0800129 String protocol = metadataUri == null ? null : new URL(metadataUri).getProtocol();
130 if (protocol != null && (!protocol.equals("file") && !protocol.equals("http"))) {
131 return getProvider(protocol);
132 }
133 // file provider supports both "file" and "http" uris
134 return getProvider("file");
135 } catch (MalformedURLException e) {
Madan Jampaniad3c5262016-01-20 00:50:17 -0800136 return null;
Madan Jampaniec1df022015-10-13 21:23:03 -0700137 }
138 }
139
140 private IpAddress findLocalIp(Collection<ControllerNode> controllerNodes) throws SocketException {
141 Enumeration<NetworkInterface> interfaces =
142 NetworkInterface.getNetworkInterfaces();
143 while (interfaces.hasMoreElements()) {
144 NetworkInterface iface = interfaces.nextElement();
145 Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
146 while (inetAddresses.hasMoreElements()) {
147 IpAddress ip = IpAddress.valueOf(inetAddresses.nextElement());
148 if (controllerNodes.stream()
149 .map(ControllerNode::ip)
150 .anyMatch(nodeIp -> ip.equals(nodeIp))) {
151 return ip;
152 }
153 }
154 }
155 throw new IllegalStateException("Unable to determine local ip");
156 }
157
158 private void establishSelfIdentity() {
159 try {
160 IpAddress ip = findLocalIp(getClusterMetadata().getNodes());
161 localNode = getClusterMetadata().getNodes()
162 .stream()
163 .filter(node -> node.ip().equals(ip))
164 .findFirst()
165 .get();
166 } catch (SocketException e) {
167 throw new IllegalStateException("Cannot determine local IP", e);
168 }
169 }
Madan Jampaniad3c5262016-01-20 00:50:17 -0800170
171 private class InternalClusterMetadataProviderService
172 extends AbstractProviderService<ClusterMetadataProvider>
173 implements ClusterMetadataProviderService {
174
175 InternalClusterMetadataProviderService(ClusterMetadataProvider provider) {
176 super(provider);
177 }
178
179 @Override
180 public void clusterMetadataChanged(Versioned<ClusterMetadata> newMetadata) {
181 log.info("Cluster metadata changed. New metadata: {}", newMetadata);
182 post(new ClusterMetadataEvent(ClusterMetadataEvent.Type.METADATA_CHANGED, newMetadata.value()));
183 }
184
185 @Override
186 public void newActiveMemberForPartition(PartitionId partitionId, NodeId nodeId) {
187 log.info("Node {} is active member for partition {}", nodeId, partitionId);
188 // TODO: notify listeners
189 }
190 }
Madan Jampaniec1df022015-10-13 21:23:03 -0700191}