blob: ce85758f8856fd1562983e9495c4f0c90ccd2039 [file] [log] [blame]
Madan Jampaniab7e7cd2016-01-14 14:02:32 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
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
Madan Jampaniec1df022015-10-13 21:23:03 -070018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
Madan Jampaniec1df022015-10-13 21:23:03 -070021import org.apache.felix.scr.annotations.Service;
22import org.onlab.packet.IpAddress;
23import org.onosproject.cluster.ClusterMetadata;
Madan Jampaniab7e7cd2016-01-14 14:02:32 -080024import org.onosproject.cluster.ClusterMetadataAdminService;
Madan Jampaniec1df022015-10-13 21:23:03 -070025import org.onosproject.cluster.ClusterMetadataEvent;
26import org.onosproject.cluster.ClusterMetadataEventListener;
Madan Jampaniad3c5262016-01-20 00:50:17 -080027import org.onosproject.cluster.ClusterMetadataProvider;
28import org.onosproject.cluster.ClusterMetadataProviderRegistry;
29import org.onosproject.cluster.ClusterMetadataProviderService;
Madan Jampaniec1df022015-10-13 21:23:03 -070030import org.onosproject.cluster.ClusterMetadataService;
Madan Jampaniec1df022015-10-13 21:23:03 -070031import org.onosproject.cluster.ControllerNode;
Madan Jampaniad3c5262016-01-20 00:50:17 -080032import org.onosproject.cluster.NodeId;
33import org.onosproject.cluster.PartitionId;
34import org.onosproject.net.provider.AbstractListenerProviderRegistry;
35import org.onosproject.net.provider.AbstractProviderService;
Madan Jampaniec1df022015-10-13 21:23:03 -070036import org.onosproject.store.service.Versioned;
37import org.slf4j.Logger;
38
Heedo Kang4a47a302016-02-29 17:40:23 +090039import java.net.InetAddress;
40import java.net.MalformedURLException;
41import java.net.NetworkInterface;
42import java.net.SocketException;
43import java.net.URL;
44import java.util.Collection;
45import java.util.Enumeration;
46
47import static com.google.common.base.Preconditions.checkNotNull;
48import static org.onosproject.security.AppGuard.checkPermission;
49import static org.onosproject.security.AppPermission.Type.CLUSTER_READ;
50import static org.slf4j.LoggerFactory.getLogger;
51
Madan Jampaniec1df022015-10-13 21:23:03 -070052/**
53 * Implementation of ClusterMetadataService.
54 */
55@Component(immediate = true)
56@Service
57public class ClusterMetadataManager
Madan Jampaniad3c5262016-01-20 00:50:17 -080058 extends AbstractListenerProviderRegistry<ClusterMetadataEvent,
59 ClusterMetadataEventListener,
60 ClusterMetadataProvider,
61 ClusterMetadataProviderService>
62 implements ClusterMetadataService, ClusterMetadataAdminService, ClusterMetadataProviderRegistry {
Madan Jampaniec1df022015-10-13 21:23:03 -070063
Madan Jampaniec1df022015-10-13 21:23:03 -070064 private final Logger log = getLogger(getClass());
Madan Jampaniab7e7cd2016-01-14 14:02:32 -080065 private ControllerNode localNode;
Madan Jampaniec1df022015-10-13 21:23:03 -070066
Madan Jampaniec1df022015-10-13 21:23:03 -070067 @Activate
68 public void activate() {
Madan Jampaniad3c5262016-01-20 00:50:17 -080069 // FIXME: Need to ensure all cluster metadata providers are registered before we activate
Madan Jampaniec1df022015-10-13 21:23:03 -070070 eventDispatcher.addSink(ClusterMetadataEvent.class, listenerRegistry);
Madan Jampaniec1df022015-10-13 21:23:03 -070071 log.info("Started");
72 }
73
74 @Deactivate
75 public void deactivate() {
Madan Jampaniec1df022015-10-13 21:23:03 -070076 eventDispatcher.removeSink(ClusterMetadataEvent.class);
77 log.info("Stopped");
78 }
79
80 @Override
81 public ClusterMetadata getClusterMetadata() {
Heedo Kang4a47a302016-02-29 17:40:23 +090082 checkPermission(CLUSTER_READ);
Madan Jampaniad3c5262016-01-20 00:50:17 -080083 Versioned<ClusterMetadata> metadata = getProvider().getClusterMetadata();
84 return metadata.value();
85 }
86
87
88 @Override
89 protected ClusterMetadataProviderService createProviderService(
90 ClusterMetadataProvider provider) {
Heedo Kang4a47a302016-02-29 17:40:23 +090091 checkPermission(CLUSTER_READ);
Madan Jampaniad3c5262016-01-20 00:50:17 -080092 return new InternalClusterMetadataProviderService(provider);
Madan Jampaniec1df022015-10-13 21:23:03 -070093 }
94
95 @Override
96 public ControllerNode getLocalNode() {
Heedo Kang4a47a302016-02-29 17:40:23 +090097 checkPermission(CLUSTER_READ);
Madan Jampaniad3c5262016-01-20 00:50:17 -080098 if (localNode == null) {
99 establishSelfIdentity();
100 }
Madan Jampaniec1df022015-10-13 21:23:03 -0700101 return localNode;
102 }
103
104 @Override
105 public void setClusterMetadata(ClusterMetadata metadata) {
106 checkNotNull(metadata, "Cluster metadata cannot be null");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800107 ClusterMetadataProvider primaryProvider = getPrimaryProvider();
108 if (primaryProvider == null) {
109 throw new IllegalStateException("Missing primary provider. Cannot update cluster metadata");
110 }
111 primaryProvider.setClusterMetadata(metadata);
Madan Jampaniec1df022015-10-13 21:23:03 -0700112 }
113
Madan Jampaniad3c5262016-01-20 00:50:17 -0800114 /**
115 * Returns the provider to use for fetching cluster metadata.
116 * @return cluster metadata provider
117 */
118 private ClusterMetadataProvider getProvider() {
119 ClusterMetadataProvider primaryProvider = getPrimaryProvider();
120 if (primaryProvider != null && primaryProvider.isAvailable()) {
121 return primaryProvider;
122 }
Madan Jampaniad3c5262016-01-20 00:50:17 -0800123 return getProvider("default");
124 }
125
126 /**
127 * Returns the primary provider for cluster metadata.
128 * @return primary cluster metadata provider
129 */
130 private ClusterMetadataProvider getPrimaryProvider() {
Madan Jampanif172d402016-03-04 00:56:38 -0800131 String metadataUri = System.getProperty("onos.cluster.metadata.uri");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800132 try {
Madan Jampanif172d402016-03-04 00:56:38 -0800133 String protocol = metadataUri == null ? null : new URL(metadataUri).getProtocol();
134 if (protocol != null && (!protocol.equals("file") && !protocol.equals("http"))) {
135 return getProvider(protocol);
136 }
137 // file provider supports both "file" and "http" uris
138 return getProvider("file");
139 } catch (MalformedURLException e) {
Madan Jampaniad3c5262016-01-20 00:50:17 -0800140 return null;
Madan Jampaniec1df022015-10-13 21:23:03 -0700141 }
142 }
143
144 private IpAddress findLocalIp(Collection<ControllerNode> controllerNodes) throws SocketException {
145 Enumeration<NetworkInterface> interfaces =
146 NetworkInterface.getNetworkInterfaces();
147 while (interfaces.hasMoreElements()) {
148 NetworkInterface iface = interfaces.nextElement();
149 Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
150 while (inetAddresses.hasMoreElements()) {
151 IpAddress ip = IpAddress.valueOf(inetAddresses.nextElement());
152 if (controllerNodes.stream()
153 .map(ControllerNode::ip)
154 .anyMatch(nodeIp -> ip.equals(nodeIp))) {
155 return ip;
156 }
157 }
158 }
159 throw new IllegalStateException("Unable to determine local ip");
160 }
161
162 private void establishSelfIdentity() {
163 try {
164 IpAddress ip = findLocalIp(getClusterMetadata().getNodes());
165 localNode = getClusterMetadata().getNodes()
166 .stream()
167 .filter(node -> node.ip().equals(ip))
168 .findFirst()
169 .get();
170 } catch (SocketException e) {
171 throw new IllegalStateException("Cannot determine local IP", e);
172 }
173 }
Madan Jampaniad3c5262016-01-20 00:50:17 -0800174
175 private class InternalClusterMetadataProviderService
176 extends AbstractProviderService<ClusterMetadataProvider>
177 implements ClusterMetadataProviderService {
178
179 InternalClusterMetadataProviderService(ClusterMetadataProvider provider) {
180 super(provider);
181 }
182
183 @Override
184 public void clusterMetadataChanged(Versioned<ClusterMetadata> newMetadata) {
185 log.info("Cluster metadata changed. New metadata: {}", newMetadata);
186 post(new ClusterMetadataEvent(ClusterMetadataEvent.Type.METADATA_CHANGED, newMetadata.value()));
187 }
188
189 @Override
190 public void newActiveMemberForPartition(PartitionId partitionId, NodeId nodeId) {
191 log.info("Node {} is active member for partition {}", nodeId, partitionId);
192 // TODO: notify listeners
193 }
194 }
Heedo Kang4a47a302016-02-29 17:40:23 +0900195}