blob: 347c8122fd6d9a3c72cc9a9a9df410ca88d2a319 [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 Halterman00e92da2018-05-22 23:05:52 -0700101 ControllerNode localNode = getProvider().getClusterMetadata().value().getLocalNode();
102 try {
103 if (localNode != null) {
104 this.localNode = new DefaultControllerNode(
105 localNode.id(),
106 localNode.ip() != null ? localNode.ip() : findLocalIp(),
107 localNode.tcpPort());
108 } else {
109 IpAddress ip = findLocalIp();
110 this.localNode = new DefaultControllerNode(NodeId.nodeId(ip.toString()), ip);
111 }
112 } catch (SocketException e) {
113 throw new IllegalStateException(e);
114 }
Madan Jampaniad3c5262016-01-20 00:50:17 -0800115 }
Madan Jampaniec1df022015-10-13 21:23:03 -0700116 return localNode;
117 }
118
119 @Override
120 public void setClusterMetadata(ClusterMetadata metadata) {
121 checkNotNull(metadata, "Cluster metadata cannot be null");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800122 ClusterMetadataProvider primaryProvider = getPrimaryProvider();
123 if (primaryProvider == null) {
124 throw new IllegalStateException("Missing primary provider. Cannot update cluster metadata");
125 }
126 primaryProvider.setClusterMetadata(metadata);
Madan Jampaniec1df022015-10-13 21:23:03 -0700127 }
128
Madan Jampaniad3c5262016-01-20 00:50:17 -0800129 /**
130 * Returns the provider to use for fetching cluster metadata.
131 * @return cluster metadata provider
132 */
133 private ClusterMetadataProvider getProvider() {
134 ClusterMetadataProvider primaryProvider = getPrimaryProvider();
135 if (primaryProvider != null && primaryProvider.isAvailable()) {
136 return primaryProvider;
137 }
Madan Jampaniad3c5262016-01-20 00:50:17 -0800138 return getProvider("default");
139 }
140
141 /**
142 * Returns the primary provider for cluster metadata.
143 * @return primary cluster metadata provider
144 */
145 private ClusterMetadataProvider getPrimaryProvider() {
Madan Jampanif172d402016-03-04 00:56:38 -0800146 String metadataUri = System.getProperty("onos.cluster.metadata.uri");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800147 try {
Madan Jampanif172d402016-03-04 00:56:38 -0800148 String protocol = metadataUri == null ? null : new URL(metadataUri).getProtocol();
Ray Milkey36cbc712017-04-07 13:33:59 -0700149 if (protocol != null && (!"file".equals(protocol) && !"http".equals(protocol))) {
Madan Jampanif172d402016-03-04 00:56:38 -0800150 return getProvider(protocol);
151 }
152 // file provider supports both "file" and "http" uris
153 return getProvider("file");
154 } catch (MalformedURLException e) {
Madan Jampaniad3c5262016-01-20 00:50:17 -0800155 return null;
Madan Jampaniec1df022015-10-13 21:23:03 -0700156 }
157 }
158
Jordan Halterman00e92da2018-05-22 23:05:52 -0700159 private IpAddress findLocalIp() throws SocketException {
160 Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
Madan Jampaniec1df022015-10-13 21:23:03 -0700161 while (interfaces.hasMoreElements()) {
162 NetworkInterface iface = interfaces.nextElement();
Jordan Halterman00e92da2018-05-22 23:05:52 -0700163 if (iface.isLoopback() || iface.isPointToPoint()) {
164 continue;
165 }
166
Madan Jampaniec1df022015-10-13 21:23:03 -0700167 Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
168 while (inetAddresses.hasMoreElements()) {
Jordan Halterman00e92da2018-05-22 23:05:52 -0700169 InetAddress inetAddress = inetAddresses.nextElement();
170 if (inetAddress instanceof Inet4Address) {
171 Inet4Address inet4Address = (Inet4Address) inetAddress;
172 try {
173 if (!inet4Address.getHostAddress().equals(InetAddress.getLocalHost().getHostAddress())) {
174 return IpAddress.valueOf(inetAddress);
175 }
176 } catch (UnknownHostException e) {
177 return IpAddress.valueOf(inetAddress);
178 }
Madan Jampaniec1df022015-10-13 21:23:03 -0700179 }
180 }
181 }
182 throw new IllegalStateException("Unable to determine local ip");
183 }
184
Madan Jampaniad3c5262016-01-20 00:50:17 -0800185 private class InternalClusterMetadataProviderService
186 extends AbstractProviderService<ClusterMetadataProvider>
187 implements ClusterMetadataProviderService {
188
189 InternalClusterMetadataProviderService(ClusterMetadataProvider provider) {
190 super(provider);
191 }
192
193 @Override
194 public void clusterMetadataChanged(Versioned<ClusterMetadata> newMetadata) {
195 log.info("Cluster metadata changed. New metadata: {}", newMetadata);
196 post(new ClusterMetadataEvent(ClusterMetadataEvent.Type.METADATA_CHANGED, newMetadata.value()));
197 }
198
199 @Override
200 public void newActiveMemberForPartition(PartitionId partitionId, NodeId nodeId) {
201 log.info("Node {} is active member for partition {}", nodeId, partitionId);
202 // TODO: notify listeners
203 }
204 }
Heedo Kang4a47a302016-02-29 17:40:23 +0900205}