blob: 7dbf1390ee086ae3ced3543d5a3828f6b6f5d76c [file] [log] [blame]
Madan Jampaniab7e7cd2016-01-14 14:02:32 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Madan Jampaniab7e7cd2016-01-14 14:02:32 -08003 *
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
Jordan Halterman00e92da2018-05-22 23:05:52 -070018import java.net.Inet4Address;
19import java.net.InetAddress;
20import java.net.MalformedURLException;
21import java.net.NetworkInterface;
22import java.net.SocketException;
23import java.net.URL;
24import java.net.UnknownHostException;
25import java.util.Enumeration;
26
Madan Jampaniec1df022015-10-13 21:23:03 -070027import org.apache.felix.scr.annotations.Activate;
28import org.apache.felix.scr.annotations.Component;
29import org.apache.felix.scr.annotations.Deactivate;
Madan Jampaniec1df022015-10-13 21:23:03 -070030import org.apache.felix.scr.annotations.Service;
31import org.onlab.packet.IpAddress;
32import org.onosproject.cluster.ClusterMetadata;
Madan Jampaniab7e7cd2016-01-14 14:02:32 -080033import org.onosproject.cluster.ClusterMetadataAdminService;
Madan Jampaniec1df022015-10-13 21:23:03 -070034import org.onosproject.cluster.ClusterMetadataEvent;
35import org.onosproject.cluster.ClusterMetadataEventListener;
Madan Jampaniad3c5262016-01-20 00:50:17 -080036import org.onosproject.cluster.ClusterMetadataProvider;
37import org.onosproject.cluster.ClusterMetadataProviderRegistry;
38import org.onosproject.cluster.ClusterMetadataProviderService;
Madan Jampaniec1df022015-10-13 21:23:03 -070039import org.onosproject.cluster.ClusterMetadataService;
Madan Jampaniec1df022015-10-13 21:23:03 -070040import org.onosproject.cluster.ControllerNode;
Jordan Halterman00e92da2018-05-22 23:05:52 -070041import org.onosproject.cluster.DefaultControllerNode;
Madan Jampaniad3c5262016-01-20 00:50:17 -080042import org.onosproject.cluster.NodeId;
43import org.onosproject.cluster.PartitionId;
44import org.onosproject.net.provider.AbstractListenerProviderRegistry;
45import org.onosproject.net.provider.AbstractProviderService;
Madan Jampaniec1df022015-10-13 21:23:03 -070046import org.onosproject.store.service.Versioned;
47import org.slf4j.Logger;
48
Heedo Kang4a47a302016-02-29 17:40:23 +090049import static com.google.common.base.Preconditions.checkNotNull;
50import static org.onosproject.security.AppGuard.checkPermission;
51import static org.onosproject.security.AppPermission.Type.CLUSTER_READ;
52import static org.slf4j.LoggerFactory.getLogger;
53
Madan Jampaniec1df022015-10-13 21:23:03 -070054/**
55 * Implementation of ClusterMetadataService.
56 */
57@Component(immediate = true)
58@Service
59public class ClusterMetadataManager
Madan Jampaniad3c5262016-01-20 00:50:17 -080060 extends AbstractListenerProviderRegistry<ClusterMetadataEvent,
61 ClusterMetadataEventListener,
62 ClusterMetadataProvider,
63 ClusterMetadataProviderService>
64 implements ClusterMetadataService, ClusterMetadataAdminService, ClusterMetadataProviderRegistry {
Madan Jampaniec1df022015-10-13 21:23:03 -070065
Madan Jampaniec1df022015-10-13 21:23:03 -070066 private final Logger log = getLogger(getClass());
Madan Jampaniab7e7cd2016-01-14 14:02:32 -080067 private ControllerNode localNode;
Madan Jampaniec1df022015-10-13 21:23:03 -070068
Madan Jampaniec1df022015-10-13 21:23:03 -070069 @Activate
70 public void activate() {
Madan Jampaniad3c5262016-01-20 00:50:17 -080071 // FIXME: Need to ensure all cluster metadata providers are registered before we activate
Madan Jampaniec1df022015-10-13 21:23:03 -070072 eventDispatcher.addSink(ClusterMetadataEvent.class, listenerRegistry);
Madan Jampaniec1df022015-10-13 21:23:03 -070073 log.info("Started");
74 }
75
76 @Deactivate
77 public void deactivate() {
Madan Jampaniec1df022015-10-13 21:23:03 -070078 eventDispatcher.removeSink(ClusterMetadataEvent.class);
79 log.info("Stopped");
80 }
81
82 @Override
83 public ClusterMetadata getClusterMetadata() {
Heedo Kang4a47a302016-02-29 17:40:23 +090084 checkPermission(CLUSTER_READ);
Madan Jampaniad3c5262016-01-20 00:50:17 -080085 Versioned<ClusterMetadata> metadata = getProvider().getClusterMetadata();
86 return metadata.value();
87 }
88
89
90 @Override
91 protected ClusterMetadataProviderService createProviderService(
92 ClusterMetadataProvider provider) {
Heedo Kang4a47a302016-02-29 17:40:23 +090093 checkPermission(CLUSTER_READ);
Madan Jampaniad3c5262016-01-20 00:50:17 -080094 return new InternalClusterMetadataProviderService(provider);
Madan Jampaniec1df022015-10-13 21:23:03 -070095 }
96
97 @Override
98 public ControllerNode getLocalNode() {
Heedo Kang4a47a302016-02-29 17:40:23 +090099 checkPermission(CLUSTER_READ);
Madan Jampaniad3c5262016-01-20 00:50:17 -0800100 if (localNode == null) {
Jordan Halterman19c123a2018-07-30 13:57:19 -0700101 ClusterMetadata metadata = getProvider().getClusterMetadata().value();
102 ControllerNode localNode = metadata.getLocalNode();
Jordan Halterman00e92da2018-05-22 23:05:52 -0700103 try {
104 if (localNode != null) {
105 this.localNode = new DefaultControllerNode(
106 localNode.id(),
107 localNode.ip() != null ? localNode.ip() : findLocalIp(),
108 localNode.tcpPort());
109 } else {
110 IpAddress ip = findLocalIp();
Jordan Halterman19c123a2018-07-30 13:57:19 -0700111 localNode = metadata.getControllerNodes().stream()
112 .filter(node -> node.ip().equals(ip))
113 .findFirst()
114 .orElse(null);
115 if (localNode != null) {
116 this.localNode = localNode;
117 } else {
118 this.localNode = new DefaultControllerNode(NodeId.nodeId(ip.toString()), ip);
119 }
Jordan Halterman00e92da2018-05-22 23:05:52 -0700120 }
121 } catch (SocketException e) {
122 throw new IllegalStateException(e);
123 }
Madan Jampaniad3c5262016-01-20 00:50:17 -0800124 }
Madan Jampaniec1df022015-10-13 21:23:03 -0700125 return localNode;
126 }
127
128 @Override
129 public void setClusterMetadata(ClusterMetadata metadata) {
130 checkNotNull(metadata, "Cluster metadata cannot be null");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800131 ClusterMetadataProvider primaryProvider = getPrimaryProvider();
132 if (primaryProvider == null) {
133 throw new IllegalStateException("Missing primary provider. Cannot update cluster metadata");
134 }
135 primaryProvider.setClusterMetadata(metadata);
Madan Jampaniec1df022015-10-13 21:23:03 -0700136 }
137
Madan Jampaniad3c5262016-01-20 00:50:17 -0800138 /**
139 * Returns the provider to use for fetching cluster metadata.
140 * @return cluster metadata provider
141 */
142 private ClusterMetadataProvider getProvider() {
143 ClusterMetadataProvider primaryProvider = getPrimaryProvider();
144 if (primaryProvider != null && primaryProvider.isAvailable()) {
145 return primaryProvider;
146 }
Madan Jampaniad3c5262016-01-20 00:50:17 -0800147 return getProvider("default");
148 }
149
150 /**
151 * Returns the primary provider for cluster metadata.
152 * @return primary cluster metadata provider
153 */
154 private ClusterMetadataProvider getPrimaryProvider() {
Madan Jampanif172d402016-03-04 00:56:38 -0800155 String metadataUri = System.getProperty("onos.cluster.metadata.uri");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800156 try {
Madan Jampanif172d402016-03-04 00:56:38 -0800157 String protocol = metadataUri == null ? null : new URL(metadataUri).getProtocol();
Ray Milkey36cbc712017-04-07 13:33:59 -0700158 if (protocol != null && (!"file".equals(protocol) && !"http".equals(protocol))) {
Madan Jampanif172d402016-03-04 00:56:38 -0800159 return getProvider(protocol);
160 }
161 // file provider supports both "file" and "http" uris
162 return getProvider("file");
163 } catch (MalformedURLException e) {
Madan Jampaniad3c5262016-01-20 00:50:17 -0800164 return null;
Madan Jampaniec1df022015-10-13 21:23:03 -0700165 }
166 }
167
Jordan Halterman00e92da2018-05-22 23:05:52 -0700168 private IpAddress findLocalIp() throws SocketException {
169 Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
Madan Jampaniec1df022015-10-13 21:23:03 -0700170 while (interfaces.hasMoreElements()) {
171 NetworkInterface iface = interfaces.nextElement();
Jordan Halterman00e92da2018-05-22 23:05:52 -0700172 if (iface.isLoopback() || iface.isPointToPoint()) {
173 continue;
174 }
175
Madan Jampaniec1df022015-10-13 21:23:03 -0700176 Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
177 while (inetAddresses.hasMoreElements()) {
Jordan Halterman00e92da2018-05-22 23:05:52 -0700178 InetAddress inetAddress = inetAddresses.nextElement();
179 if (inetAddress instanceof Inet4Address) {
180 Inet4Address inet4Address = (Inet4Address) inetAddress;
181 try {
182 if (!inet4Address.getHostAddress().equals(InetAddress.getLocalHost().getHostAddress())) {
183 return IpAddress.valueOf(inetAddress);
184 }
185 } catch (UnknownHostException e) {
186 return IpAddress.valueOf(inetAddress);
187 }
Madan Jampaniec1df022015-10-13 21:23:03 -0700188 }
189 }
190 }
191 throw new IllegalStateException("Unable to determine local ip");
192 }
193
Madan Jampaniad3c5262016-01-20 00:50:17 -0800194 private class InternalClusterMetadataProviderService
195 extends AbstractProviderService<ClusterMetadataProvider>
196 implements ClusterMetadataProviderService {
197
198 InternalClusterMetadataProviderService(ClusterMetadataProvider provider) {
199 super(provider);
200 }
201
202 @Override
203 public void clusterMetadataChanged(Versioned<ClusterMetadata> newMetadata) {
204 log.info("Cluster metadata changed. New metadata: {}", newMetadata);
205 post(new ClusterMetadataEvent(ClusterMetadataEvent.Type.METADATA_CHANGED, newMetadata.value()));
206 }
207
208 @Override
209 public void newActiveMemberForPartition(PartitionId partitionId, NodeId nodeId) {
210 log.info("Node {} is active member for partition {}", nodeId, partitionId);
211 // TODO: notify listeners
212 }
213 }
Heedo Kang4a47a302016-02-29 17:40:23 +0900214}