blob: 1fd2d11da0c8fef81a806b6c3877bd4ef8f174a8 [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 }
123 log.warn("Primary cluster metadata provider not available. Using default fallback.");
124 return getProvider("default");
125 }
126
127 /**
128 * Returns the primary provider for cluster metadata.
129 * @return primary cluster metadata provider
130 */
131 private ClusterMetadataProvider getPrimaryProvider() {
Madan Jampanif172d402016-03-04 00:56:38 -0800132 String metadataUri = System.getProperty("onos.cluster.metadata.uri");
Madan Jampaniad3c5262016-01-20 00:50:17 -0800133 try {
Madan Jampanif172d402016-03-04 00:56:38 -0800134 String protocol = metadataUri == null ? null : new URL(metadataUri).getProtocol();
135 if (protocol != null && (!protocol.equals("file") && !protocol.equals("http"))) {
136 return getProvider(protocol);
137 }
138 // file provider supports both "file" and "http" uris
139 return getProvider("file");
140 } catch (MalformedURLException e) {
Madan Jampaniad3c5262016-01-20 00:50:17 -0800141 return null;
Madan Jampaniec1df022015-10-13 21:23:03 -0700142 }
143 }
144
145 private IpAddress findLocalIp(Collection<ControllerNode> controllerNodes) throws SocketException {
146 Enumeration<NetworkInterface> interfaces =
147 NetworkInterface.getNetworkInterfaces();
148 while (interfaces.hasMoreElements()) {
149 NetworkInterface iface = interfaces.nextElement();
150 Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
151 while (inetAddresses.hasMoreElements()) {
152 IpAddress ip = IpAddress.valueOf(inetAddresses.nextElement());
153 if (controllerNodes.stream()
154 .map(ControllerNode::ip)
155 .anyMatch(nodeIp -> ip.equals(nodeIp))) {
156 return ip;
157 }
158 }
159 }
160 throw new IllegalStateException("Unable to determine local ip");
161 }
162
163 private void establishSelfIdentity() {
164 try {
165 IpAddress ip = findLocalIp(getClusterMetadata().getNodes());
166 localNode = getClusterMetadata().getNodes()
167 .stream()
168 .filter(node -> node.ip().equals(ip))
169 .findFirst()
170 .get();
171 } catch (SocketException e) {
172 throw new IllegalStateException("Cannot determine local IP", e);
173 }
174 }
Madan Jampaniad3c5262016-01-20 00:50:17 -0800175
176 private class InternalClusterMetadataProviderService
177 extends AbstractProviderService<ClusterMetadataProvider>
178 implements ClusterMetadataProviderService {
179
180 InternalClusterMetadataProviderService(ClusterMetadataProvider provider) {
181 super(provider);
182 }
183
184 @Override
185 public void clusterMetadataChanged(Versioned<ClusterMetadata> newMetadata) {
186 log.info("Cluster metadata changed. New metadata: {}", newMetadata);
187 post(new ClusterMetadataEvent(ClusterMetadataEvent.Type.METADATA_CHANGED, newMetadata.value()));
188 }
189
190 @Override
191 public void newActiveMemberForPartition(PartitionId partitionId, NodeId nodeId) {
192 log.info("Node {} is active member for partition {}", nodeId, partitionId);
193 // TODO: notify listeners
194 }
195 }
Heedo Kang4a47a302016-02-29 17:40:23 +0900196}