blob: aa32da22acfcbf98f1d7aa54c45e9e8912a8a8f9 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cluster.impl;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ClusterMetadata;
import org.onosproject.cluster.ClusterMetadataProvider;
import org.onosproject.cluster.ClusterMetadataProviderRegistry;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.PartitionId;
import org.onosproject.core.VersionService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.store.service.Versioned;
import org.slf4j.Logger;
import static java.net.NetworkInterface.getNetworkInterfaces;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Provider of default {@link ClusterMetadata cluster metadata}.
*/
@Component(immediate = true)
public class DefaultClusterMetadataProvider implements ClusterMetadataProvider {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterMetadataProviderRegistry providerRegistry;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected VersionService versionService;
private static final String ONOS_IP = "ONOS_IP";
private static final String ONOS_INTERFACE = "ONOS_INTERFACE";
private static final String ONOS_ALLOW_IPV6 = "ONOS_ALLOW_IPV6";
private static final String DEFAULT_ONOS_INTERFACE = "eth0";
private static final int DEFAULT_ONOS_PORT = 9876;
private static final ProviderId PROVIDER_ID = new ProviderId("default", "none");
private final AtomicReference<Versioned<ClusterMetadata>> cachedMetadata = new AtomicReference<>();
@Activate
public void activate() {
String localIp = getSiteLocalAddress();
ControllerNode localNode =
new DefaultControllerNode(new NodeId(localIp), IpAddress.valueOf(localIp), DEFAULT_ONOS_PORT);
ClusterMetadata metadata = new ClusterMetadata(
PROVIDER_ID, "default", localNode, ImmutableSet.of());
long version = System.currentTimeMillis();
cachedMetadata.set(new Versioned<>(metadata, version));
providerRegistry.register(this);
log.info("Started");
}
@Deactivate
public void deactivate() {
providerRegistry.unregister(this);
log.info("Stopped");
}
@Override
public ProviderId id() {
return PROVIDER_ID;
}
@Override
public Versioned<ClusterMetadata> getClusterMetadata() {
return cachedMetadata.get();
}
@Override
public void setClusterMetadata(ClusterMetadata metadata) {
throw new UnsupportedOperationException();
}
@Override
public void addActivePartitionMember(PartitionId partitionId, NodeId nodeId) {
throw new UnsupportedOperationException();
}
@Override
public void removeActivePartitionMember(PartitionId partitionId, NodeId nodeId) {
throw new UnsupportedOperationException();
}
@Override
public Set<NodeId> getActivePartitionMembers(PartitionId partitionId) {
throw new UnsupportedOperationException();
}
@Override
public boolean isAvailable() {
return true;
}
private static String getSiteLocalAddress() {
/*
* If the IP ONOS should use is set via the environment variable we will assume it is valid and should be used.
* Setting the IP address takes presidence over setting the interface via the environment.
*/
String useOnosIp = System.getenv(ONOS_IP);
if (useOnosIp != null) {
return useOnosIp;
}
// Read environment variables for IP interface information or set to default
String useOnosInterface = System.getenv(ONOS_INTERFACE);
if (useOnosInterface == null) {
useOnosInterface = DEFAULT_ONOS_INTERFACE;
}
// Capture if they want to limit IP address selection to only IPv4 (default).
boolean allowIPv6 = (System.getenv(ONOS_ALLOW_IPV6) != null);
Function<NetworkInterface, IpAddress> ipLookup = nif -> {
IpAddress fallback = null;
// nif can be null if the interface name specified doesn't exist on the node's host
if (nif != null) {
for (InetAddress address : Collections.list(nif.getInetAddresses())) {
if (address.isSiteLocalAddress() && (allowIPv6 || address instanceof Inet4Address)) {
return IpAddress.valueOf(address);
}
if (fallback == null && !address.isLoopbackAddress() && !address.isMulticastAddress()
&& (allowIPv6 || address instanceof Inet4Address)) {
fallback = IpAddress.valueOf(address);
}
}
}
return fallback;
};
try {
IpAddress ip = ipLookup.apply(NetworkInterface.getByName(useOnosInterface));
if (ip != null) {
return ip.toString();
}
for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
if (!nif.getName().equals(useOnosInterface)) {
ip = ipLookup.apply(nif);
if (ip != null) {
return ip.toString();
}
}
}
} catch (Exception e) {
throw new IllegalStateException("Unable to get network interfaces", e);
}
return IpAddress.valueOf(InetAddress.getLoopbackAddress()).toString();
}
}