alshabib

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Showing 70 changed files with 866 additions and 162 deletions
package org.onlab.onos.cli;
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
/**
* Lists all controller cluster nodes.
*/
@Command(scope = "onos", name = "nodes",
description = "Lists all controller cluster nodes")
public class NodesListCommand extends AbstractShellCommand {
private static final String FMT =
"id=%s, ip=%s, state=%s %s";
protected static final Comparator<ControllerNode> ID_COMPARATOR =
new Comparator<ControllerNode>() {
@Override
public int compare(ControllerNode ci1, ControllerNode ci2) {
return ci1.id().toString().compareTo(ci2.id().toString());
}
};
@Override
protected Object doExecute() throws Exception {
ClusterService service = getService(ClusterService.class);
List<ControllerNode> nodes = newArrayList(service.getNodes());
Collections.sort(nodes, ID_COMPARATOR);
ControllerNode self = service.getLocalNode();
for (ControllerNode node : nodes) {
print(FMT, node.id(), node.ip(),
service.getState(node.id()),
node.equals(self) ? "*" : "");
}
return null;
}
}
......@@ -2,6 +2,9 @@
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onlab.onos.cli.NodesListCommand"/>
</command>
<command>
<action class="org.onlab.onos.cli.net.FlowsListCommand"/>
</command>
<command>
......
......@@ -5,10 +5,10 @@ import org.onlab.onos.event.AbstractEvent;
/**
* Describes cluster-related event.
*/
public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerInstance> {
public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerNode> {
/**
* Type of device events.
* Type of cluster-related events.
*/
public enum Type {
/**
......@@ -24,14 +24,13 @@ public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerIns
/**
* Signifies that a cluster instance became active.
*/
INSTANCE_ACTIVE,
INSTANCE_ACTIVATED,
/**
* Signifies that a cluster instance became inactive.
*/
INSTANCE_INACTIVE
INSTANCE_DEACTIVATED
}
// TODO: do we need to fix the verv/adjective mix? discuss
/**
* Creates an event of a given type and for the specified instance and the
......@@ -40,7 +39,7 @@ public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerIns
* @param type cluster event type
* @param instance cluster device subject
*/
public ClusterEvent(Type type, ControllerInstance instance) {
public ClusterEvent(Type type, ControllerNode instance) {
super(type, instance);
}
......@@ -51,7 +50,7 @@ public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerIns
* @param instance event device subject
* @param time occurrence time
*/
public ClusterEvent(Type type, ControllerInstance instance, long time) {
public ClusterEvent(Type type, ControllerNode instance, long time) {
super(type, instance, time);
}
......
package org.onlab.onos.cluster;
import org.onlab.onos.event.EventListener;
/**
* Controller cluster identity.
* Entity capable of receiving device cluster-related events.
*/
public interface InstanceId {
public interface ClusterEventListener extends EventListener<ClusterEvent> {
}
......
......@@ -3,27 +3,53 @@ package org.onlab.onos.cluster;
import java.util.Set;
/**
* Service for obtaining information about the individual instances within
* Service for obtaining information about the individual nodes within
* the controller cluster.
*/
public interface ClusterService {
/**
* Returns the local controller node.
*
* @return local controller node
*/
ControllerNode getLocalNode();
/**
* Returns the set of current cluster members.
*
* @return set of cluster members
*/
Set<ControllerInstance> getInstances();
Set<ControllerNode> getNodes();
/**
* Returns the specified controller node.
*
* @param nodeId controller node identifier
* @return controller node
*/
ControllerNode getNode(NodeId nodeId);
/**
* Returns the availability state of the specified controller instance.
* Returns the availability state of the specified controller node.
*
* @param nodeId controller node identifier
* @return availability state
*/
ControllerInstance.State getState(ControllerInstance instance);
// TODO: determine if this would be better attached to ControllerInstance directly
ControllerNode.State getState(NodeId nodeId);
/**
* Adds the specified cluster event listener.
*
* @param listener the cluster listener
*/
void addListener(ClusterEventListener listener);
// addListener, removeListener
/**
* Removes the specified cluster event listener.
*
* @param listener the cluster listener
*/
void removeListener(ClusterEventListener listener);
}
......
package org.onlab.onos.cluster;
import java.util.Set;
/**
* Manages inventory of controller cluster nodes; not intended for direct use.
*/
public interface ClusterStore {
/**
* Returns the local controller instance.
*
* @return local controller instance
*/
ControllerNode getLocalNode();
/**
* Returns the set of current cluster members.
*
* @return set of cluster members
*/
Set<ControllerNode> getNodes();
/**
* Returns the specified controller instance.
*
* @param nodeId controller instance identifier
* @return controller instance
*/
ControllerNode getNode(NodeId nodeId);
/**
* Returns the availability state of the specified controller instance.
*
* @param nodeId controller instance identifier
* @return availability state
*/
ControllerNode.State getState(NodeId nodeId);
}
......@@ -5,7 +5,7 @@ import org.onlab.packet.IpPrefix;
/**
* Represents a controller instance as a member in a cluster.
*/
public interface ControllerInstance {
public interface ControllerNode {
/** Represents the operational state of the instance. */
public enum State {
......@@ -26,7 +26,7 @@ public interface ControllerInstance {
*
* @return instance identifier
*/
InstanceId id();
NodeId id();
/**
* Returns the IP address of the controller instance.
......
package org.onlab.onos.cluster;
import org.onlab.packet.IpPrefix;
import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
/**
* Default implementation of a controller instance descriptor.
*/
public class DefaultControllerNode implements ControllerNode {
private final NodeId id;
private final IpPrefix ip;
// For serialization
private DefaultControllerNode() {
this.id = null;
this.ip = null;
}
/**
* Creates a new instance with the specified id and IP address.
*
* @param id instance identifier
* @param ip instance IP address
*/
public DefaultControllerNode(NodeId id, IpPrefix ip) {
this.id = id;
this.ip = ip;
}
@Override
public NodeId id() {
return id;
}
@Override
public IpPrefix ip() {
return ip;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof DefaultControllerNode) {
DefaultControllerNode that = (DefaultControllerNode) o;
return Objects.equals(this.id, that.id);
}
return false;
}
@Override
public String toString() {
return toStringHelper(this).add("id", id).add("ip", ip).toString();
}
}
......@@ -15,6 +15,6 @@ public interface MastershipAdminService {
* @param deviceId device identifier
* @param role requested role
*/
void setRole(InstanceId instance, DeviceId deviceId, MastershipRole role);
void setRole(NodeId instance, DeviceId deviceId, MastershipRole role);
}
......
......@@ -8,7 +8,7 @@ import org.onlab.onos.net.DeviceId;
*/
public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceId> {
InstanceId master;
NodeId master;
/**
* Type of mastership events.
......@@ -28,7 +28,7 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI
* @param device event device subject
* @param master master ID subject
*/
protected MastershipEvent(Type type, DeviceId device, InstanceId master) {
protected MastershipEvent(Type type, DeviceId device, NodeId master) {
super(type, device);
this.master = master;
}
......@@ -42,7 +42,7 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI
* @param master master ID subject
* @param time occurrence time
*/
protected MastershipEvent(Type type, DeviceId device, InstanceId master, long time) {
protected MastershipEvent(Type type, DeviceId device, NodeId master, long time) {
super(type, device, time);
this.master = master;
}
......@@ -52,7 +52,7 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI
*
* @return master ID subject
*/
public InstanceId master() {
public NodeId master() {
return master;
}
}
......
......@@ -6,5 +6,4 @@ import org.onlab.onos.event.EventListener;
* Entity capable of receiving device mastership-related events.
*/
public interface MastershipListener extends EventListener<MastershipEvent> {
}
......
......@@ -19,15 +19,15 @@ public interface MastershipService {
* @param deviceId the identifier of the device
* @return the ID of the master controller for the device
*/
InstanceId getMasterFor(DeviceId deviceId);
NodeId getMasterFor(DeviceId deviceId);
/**
* Returns the devices for which a controller is master.
*
* @param instanceId the ID of the controller
* @param nodeId the ID of the controller
* @return a set of device IDs
*/
Set<DeviceId> getDevicesOf(InstanceId instanceId);
Set<DeviceId> getDevicesOf(NodeId nodeId);
/**
* Returns the mastership status of this controller for a given device.
......@@ -38,14 +38,14 @@ public interface MastershipService {
MastershipRole requestRoleFor(DeviceId deviceId);
/**
* Adds the specified mastership listener.
* Adds the specified mastership change listener.
*
* @param listener the mastership listener
*/
void addListener(MastershipListener listener);
/**
* Removes the specified device listener.
* Removes the specified mastership change listener.
*
* @param listener the mastership listener
*/
......
......@@ -6,11 +6,12 @@ import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
/**
* Manages inventory of mastership roles for devices, across controller instances.
* Manages inventory of mastership roles for devices, across controller
* instances; not intended for direct use.
*/
public interface MastershipStore {
// three things to map: InstanceId, DeviceId, MastershipRole
// three things to map: NodeId, DeviceId, MastershipRole
/**
* Sets a device's role for a specified controller instance.
......@@ -20,8 +21,8 @@ public interface MastershipStore {
* @param role new role
* @return a mastership event
*/
MastershipEvent setRole(
InstanceId instance, DeviceId deviceId, MastershipRole role);
MastershipEvent setRole(NodeId instance, DeviceId deviceId,
MastershipRole role);
/**
* Adds or updates the mastership information for a device.
......@@ -31,8 +32,8 @@ public interface MastershipStore {
* @param role new role
* @return a mastership event
*/
MastershipEvent addOrUpdateDevice(
InstanceId instance, DeviceId deviceId, MastershipRole role);
MastershipEvent addOrUpdateDevice(NodeId instance, DeviceId deviceId,
MastershipRole role);
/**
* Returns the master for a device.
......@@ -40,22 +41,22 @@ public interface MastershipStore {
* @param deviceId the device identifier
* @return the instance identifier of the master
*/
InstanceId getMaster(DeviceId deviceId);
NodeId getMaster(DeviceId deviceId);
/**
* Returns the devices that a controller instance is master of.
*
* @param instanceId the instance identifier
* @param nodeId the instance identifier
* @return a set of device identifiers
*/
Set<DeviceId> getDevices(InstanceId instanceId);
Set<DeviceId> getDevices(NodeId nodeId);
/**
* Returns the role of a device for a specific controller instance.
*
* @param instanceId the instance identifier
* @param deviceId the device identifiers
* @param nodeId the instance identifier
* @param deviceId the device identifiers
* @return the role
*/
MastershipRole getRole(InstanceId instanceId, DeviceId deviceId);
MastershipRole getRole(NodeId nodeId, DeviceId deviceId);
}
......
package org.onlab.onos.cluster;
import java.util.Objects;
/**
* Controller cluster identity.
*/
public class NodeId {
private final String id;
// Default constructor for serialization
protected NodeId() {
id = null;
}
/**
* Creates a new cluster node identifier from the specified string.
*
* @param id string identifier
*/
public NodeId(String id) {
this.id = id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof NodeId) {
final NodeId other = (NodeId) obj;
return Objects.equals(this.id, other.id);
}
return false;
}
@Override
public String toString() {
return id;
}
}
......@@ -66,6 +66,9 @@ public class ConnectPoint {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ConnectPoint) {
final ConnectPoint other = (ConnectPoint) obj;
return Objects.equals(this.elementId, other.elementId) &&
......
......@@ -85,6 +85,9 @@ public class DefaultDevice extends AbstractElement implements Device {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultDevice) {
final DefaultDevice other = (DefaultDevice) obj;
return Objects.equals(this.id, other.id) &&
......
......@@ -63,6 +63,9 @@ public class DefaultHost extends AbstractElement implements Host {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultHost) {
final DefaultHost other = (DefaultHost) obj;
return Objects.equals(this.id, other.id) &&
......
......@@ -53,6 +53,9 @@ public class DefaultLink extends AbstractModel implements Link {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultLink) {
final DefaultLink other = (DefaultLink) obj;
return Objects.equals(this.src, other.src) &&
......
......@@ -57,11 +57,14 @@ public class DefaultPath extends DefaultLink implements Path {
@Override
public int hashCode() {
return 31 * super.hashCode() + Objects.hash(links);
return Objects.hash(links);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultPath) {
final DefaultPath other = (DefaultPath) obj;
return Objects.equals(this.links, other.links);
......
......@@ -58,6 +58,9 @@ public class DefaultPort implements Port {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultPort) {
final DefaultPort other = (DefaultPort) obj;
return Objects.equals(this.element.id(), other.element.id()) &&
......
......@@ -7,9 +7,6 @@ import java.net.URI;
*/
public final class DeviceId extends ElementId {
// Default constructor for serialization
protected DeviceId() {}
// Public construction is prohibited
private DeviceId(URI uri) {
super(uri);
......
......@@ -40,6 +40,9 @@ public abstract class ElementId {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ElementId) {
final ElementId that = (ElementId) obj;
return this.getClass() == that.getClass() &&
......
......@@ -79,6 +79,9 @@ public final class PortNumber {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof PortNumber) {
final PortNumber other = (PortNumber) obj;
return this.number == other.number;
......
......@@ -10,7 +10,7 @@ import org.onlab.onos.net.provider.ProviderId;
import java.util.List;
/**
* Manages inventory of infrastructure devices.
* Manages inventory of infrastructure devices; not intended for direct use.
*/
public interface DeviceStore {
......
......@@ -147,7 +147,6 @@ public class DefaultFlowRule implements FlowRule {
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.net.flow;
import org.onlab.onos.net.DeviceId;
/**
* Manages inventory of flow rules.
* Manages inventory of flow rules; not intended for direct use.
*/
public interface FlowRuleStore {
......
......@@ -12,8 +12,7 @@ import org.onlab.packet.VlanId;
import java.util.Set;
/**
* Manages inventory of end-station hosts. It may do so using whatever
* means are appropriate.
* Manages inventory of end-station hosts; not intended for direct use.
*/
public interface HostStore {
......
......@@ -8,8 +8,7 @@ import org.onlab.onos.net.provider.ProviderId;
import java.util.Set;
/**
* Manages inventory of infrastructure links. It may do so using whatever
* means are appropriate.
* Manages inventory of infrastructure links; not intended for direct use.
*/
public interface LinkStore {
......
......@@ -54,6 +54,9 @@ public class DefaultInboundPacket implements InboundPacket {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof InboundPacket) {
final DefaultInboundPacket other = (DefaultInboundPacket) obj;
return Objects.equals(this.receivedFrom, other.receivedFrom) &&
......
......@@ -12,12 +12,6 @@ public class ProviderId {
private final String scheme;
private final String id;
// Default constructor for serialization
protected ProviderId() {
scheme = null;
id = null;
}
/**
* Creates a new provider identifier from the specified string.
* The providers are expected to follow the reverse DNS convention, e.g.
......@@ -40,6 +34,15 @@ public class ProviderId {
return scheme;
}
/**
* Returns the device URI scheme specific id portion.
*
* @return id
*/
public String id() {
return id;
}
@Override
public int hashCode() {
return Objects.hash(scheme, id);
......@@ -50,12 +53,12 @@ public class ProviderId {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
if (obj instanceof ProviderId) {
final ProviderId other = (ProviderId) obj;
return Objects.equals(this.scheme, other.scheme) &&
Objects.equals(this.id, other.id);
}
final ProviderId other = (ProviderId) obj;
return Objects.equals(this.scheme, other.scheme) &&
Objects.equals(this.id, other.id);
return false;
}
@Override
......
......@@ -43,6 +43,9 @@ public final class ClusterId {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ClusterId) {
final ClusterId other = (ClusterId) obj;
return Objects.equals(this.id, other.id);
......
......@@ -59,6 +59,9 @@ public class DefaultTopologyCluster implements TopologyCluster {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultTopologyCluster) {
final DefaultTopologyCluster other = (DefaultTopologyCluster) obj;
return Objects.equals(this.id, other.id) &&
......
......@@ -50,6 +50,9 @@ public class DefaultTopologyEdge implements TopologyEdge {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultTopologyEdge) {
final DefaultTopologyEdge other = (DefaultTopologyEdge) obj;
return Objects.equals(this.link, other.link);
......
......@@ -32,6 +32,9 @@ public class DefaultTopologyVertex implements TopologyVertex {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultTopologyVertex) {
final DefaultTopologyVertex other = (DefaultTopologyVertex) obj;
return Objects.equals(this.deviceId, other.deviceId);
......
......@@ -11,8 +11,7 @@ import java.util.List;
import java.util.Set;
/**
* Manages inventory of topology snapshots. It may do so using whatever
* means appropriate.
* Manages inventory of topology snapshots; not intended for direct use.
*/
public interface TopologyStore {
......
package org.onlab.onos.cluster.impl;
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.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterEvent;
import org.onlab.onos.cluster.ClusterEventListener;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ClusterStore;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.AbstractListenerRegistry;
import org.onlab.onos.event.EventDeliveryService;
import org.slf4j.Logger;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Implementation of the cluster service.
*/
@Component(immediate = true)
@Service
public class ClusterManager implements ClusterService {
public static final String INSTANCE_ID_NULL = "Instance ID cannot be null";
private final Logger log = getLogger(getClass());
protected final AbstractListenerRegistry<ClusterEvent, ClusterEventListener>
listenerRegistry = new AbstractListenerRegistry<>();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterStore store;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EventDeliveryService eventDispatcher;
@Activate
public void activate() {
eventDispatcher.addSink(ClusterEvent.class, listenerRegistry);
log.info("Started");
}
@Deactivate
public void deactivate() {
eventDispatcher.removeSink(ClusterEvent.class);
log.info("Stopped");
}
@Override
public ControllerNode getLocalNode() {
return store.getLocalNode();
}
@Override
public Set<ControllerNode> getNodes() {
return store.getNodes();
}
@Override
public ControllerNode getNode(NodeId nodeId) {
checkNotNull(nodeId, INSTANCE_ID_NULL);
return store.getNode(nodeId);
}
@Override
public ControllerNode.State getState(NodeId nodeId) {
checkNotNull(nodeId, INSTANCE_ID_NULL);
return store.getState(nodeId);
}
@Override
public void addListener(ClusterEventListener listener) {
listenerRegistry.addListener(listener);
}
@Override
public void removeListener(ClusterEventListener listener) {
listenerRegistry.removeListener(listener);
}
}
/**
* Subsystem for tracking controller cluster nodes.
*/
package org.onlab.onos.cluster.impl;
\ No newline at end of file
......@@ -33,7 +33,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Provides basic implementation of the device SB &amp; NB APIs.
* Provides implementation of the device SB &amp; NB APIs.
*/
@Component(immediate = true)
@Service
......
......@@ -33,6 +33,9 @@ import org.slf4j.Logger;
import com.google.common.collect.Lists;
/**
* Provides implementation of the flow NB &amp; SB APIs.
*/
@Component(immediate = true)
@Service
public class FlowRuleManager
......
......@@ -112,7 +112,7 @@ public class DistributedDeviceManagerTest {
mgr.deactivate();
dstore.deactivate();
dstore.theInstance.shutdown();
((TestDistributedDeviceStore) dstore).shutdownHz();
}
private void connectDevice(DeviceId deviceId, String swVersion) {
......@@ -290,5 +290,12 @@ public class DistributedDeviceManagerTest {
}
};
}
/**
* Shutdowns the hazelcast instance.
*/
public void shutdownHz() {
theInstance.shutdown();
}
}
}
......
package org.onlab.onos.store.cluster.impl;
import com.google.common.collect.ImmutableSet;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.Member;
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.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterStore;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.store.StoreService;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import java.util.Set;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Distributed implementation of the cluster nodes store.
*/
@Component(immediate = true)
@Service
public class DistributedClusterStore implements ClusterStore {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StoreService storeService;
private HazelcastInstance theInstance;
// FIXME: experimental implementation; enhance to assure persistence and
// visibility to nodes that are not currently in the cluster
@Activate
public void activate() {
log.info("Started");
theInstance = storeService.getHazelcastInstance();
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
@Override
public ControllerNode getLocalNode() {
return node(theInstance.getCluster().getLocalMember());
}
@Override
public Set<ControllerNode> getNodes() {
ImmutableSet.Builder<ControllerNode> builder = ImmutableSet.builder();
for (Member member : theInstance.getCluster().getMembers()) {
builder.add(node(member));
}
return builder.build();
}
@Override
public ControllerNode getNode(NodeId nodeId) {
for (Member member : theInstance.getCluster().getMembers()) {
if (member.getUuid().equals(nodeId.toString())) {
return node(member);
}
}
return null;
}
@Override
public ControllerNode.State getState(NodeId nodeId) {
return ControllerNode.State.ACTIVE;
}
// Creates a controller node descriptor from the Hazelcast member.
private ControllerNode node(Member member) {
return new DefaultControllerNode(new NodeId(member.getUuid()),
IpPrefix.valueOf(member.getSocketAddress().getAddress().getAddress()));
}
}
/**
* Implementation of a distributed cluster node store using Hazelcast.
*/
package org.onlab.onos.store.cluster.impl;
\ No newline at end of file
......@@ -16,6 +16,9 @@ import com.esotericsoftware.kryo.serializers.CollectionSerializer;
import com.google.common.collect.ImmutableSet;
// TODO move to util, etc.
/**
* Kryo Serializer for {@link DefaultPort}.
*/
public final class DefaultPortSerializer extends
Serializer<DefaultPort> {
......@@ -23,6 +26,9 @@ public final class DefaultPortSerializer extends
= new CollectionSerializer(IpPrefix.class,
new IpPrefixSerializer(), false);
/**
* Default constructor.
*/
public DefaultPortSerializer() {
// non-null, immutable
super(false, true);
......
......@@ -44,6 +44,10 @@ import org.onlab.onos.store.StoreService;
import org.onlab.util.KryoPool;
import org.slf4j.Logger;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
......@@ -68,103 +72,26 @@ import de.javakaffee.kryoserializers.URISerializer;
@Service
public class DistributedDeviceStore implements DeviceStore {
/**
* An IMap EntryListener, which reflects each remote event to cache.
*
* @param <K> IMap key type after deserialization
* @param <V> IMap value type after deserialization
*/
public static final class RemoteEventHandler<K, V> extends
EntryAdapter<byte[], byte[]> {
private LoadingCache<K, Optional<V>> cache;
/**
* Constructor.
*
* @param cache cache to update
*/
public RemoteEventHandler(
LoadingCache<K, Optional<V>> cache) {
this.cache = checkNotNull(cache);
}
@Override
public void mapCleared(MapEvent event) {
cache.invalidateAll();
}
@Override
public void entryUpdated(EntryEvent<byte[], byte[]> event) {
cache.put(POOL.<K>deserialize(event.getKey()),
Optional.of(POOL.<V>deserialize(
event.getValue())));
}
@Override
public void entryRemoved(EntryEvent<byte[], byte[]> event) {
cache.invalidate(POOL.<DeviceId>deserialize(event.getKey()));
}
@Override
public void entryAdded(EntryEvent<byte[], byte[]> event) {
entryUpdated(event);
}
}
/**
* CacheLoader to wrap Map value with Optional,
* to handle negative hit on underlying IMap.
*
* @param <K> IMap key type after deserialization
* @param <V> IMap value type after deserialization
*/
public static final class OptionalCacheLoader<K, V> extends
CacheLoader<K, Optional<V>> {
private IMap<byte[], byte[]> rawMap;
/**
* Constructor.
*
* @param rawMap underlying IMap
*/
public OptionalCacheLoader(IMap<byte[], byte[]> rawMap) {
this.rawMap = checkNotNull(rawMap);
}
@Override
public Optional<V> load(K key) throws Exception {
byte[] keyBytes = serialize(key);
byte[] valBytes = rawMap.get(keyBytes);
if (valBytes == null) {
return Optional.absent();
}
V dev = deserialize(valBytes);
return Optional.of(dev);
}
}
private final Logger log = getLogger(getClass());
public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
// FIXME Slice out types used in common to separate pool/namespace.
private static final KryoPool POOL = KryoPool.newBuilder()
.register(URI.class, new URISerializer())
.register(
ArrayList.class,
HashMap.class,
ProviderId.class,
Device.Type.class,
DeviceId.class,
DefaultDevice.class,
MastershipRole.class,
HashMap.class,
Port.class,
Element.class
)
.register(URI.class, new URISerializer())
.register(ProviderId.class, new ProviderIdSerializer())
.register(DeviceId.class, new DeviceIdSerializer())
.register(PortNumber.class, new PortNumberSerializer())
.register(DefaultPort.class, new DefaultPortSerializer())
.build()
......@@ -190,7 +117,7 @@ public class DistributedDeviceStore implements DeviceStore {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StoreService storeService;
/*protected*/public HazelcastInstance theInstance;
protected HazelcastInstance theInstance;
@Activate
......@@ -517,4 +444,94 @@ public class DistributedDeviceStore implements DeviceStore {
return POOL.deserialize(bytes);
}
public static final class DeviceIdSerializer extends Serializer<DeviceId> {
@Override
public void write(Kryo kryo, Output output, DeviceId object) {
kryo.writeObject(output, object.uri());
}
@Override
public DeviceId read(Kryo kryo, Input input, Class<DeviceId> type) {
final URI uri = kryo.readObject(input, URI.class);
return DeviceId.deviceId(uri);
}
}
/**
* An IMap EntryListener, which reflects each remote event to cache.
*
* @param <K> IMap key type after deserialization
* @param <V> IMap value type after deserialization
*/
public static final class RemoteEventHandler<K, V> extends
EntryAdapter<byte[], byte[]> {
private LoadingCache<K, Optional<V>> cache;
/**
* Constructor.
*
* @param cache cache to update
*/
public RemoteEventHandler(
LoadingCache<K, Optional<V>> cache) {
this.cache = checkNotNull(cache);
}
@Override
public void mapCleared(MapEvent event) {
cache.invalidateAll();
}
@Override
public void entryUpdated(EntryEvent<byte[], byte[]> event) {
cache.put(POOL.<K>deserialize(event.getKey()),
Optional.of(POOL.<V>deserialize(
event.getValue())));
}
@Override
public void entryRemoved(EntryEvent<byte[], byte[]> event) {
cache.invalidate(POOL.<DeviceId>deserialize(event.getKey()));
}
@Override
public void entryAdded(EntryEvent<byte[], byte[]> event) {
entryUpdated(event);
}
}
/**
* CacheLoader to wrap Map value with Optional,
* to handle negative hit on underlying IMap.
*
* @param <K> IMap key type after deserialization
* @param <V> IMap value type after deserialization
*/
public static final class OptionalCacheLoader<K, V> extends
CacheLoader<K, Optional<V>> {
private IMap<byte[], byte[]> rawMap;
/**
* Constructor.
*
* @param rawMap underlying IMap
*/
public OptionalCacheLoader(IMap<byte[], byte[]> rawMap) {
this.rawMap = checkNotNull(rawMap);
}
@Override
public Optional<V> load(K key) throws Exception {
byte[] keyBytes = serialize(key);
byte[] valBytes = rawMap.get(keyBytes);
if (valBytes == null) {
return Optional.absent();
}
V dev = deserialize(valBytes);
return Optional.of(dev);
}
}
}
......
......@@ -8,8 +8,14 @@ import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
// TODO move to util, etc.
/**
* Kryo Serializer for {@link IpPrefix}.
*/
public final class IpPrefixSerializer extends Serializer<IpPrefix> {
/**
* Default constructor.
*/
public IpPrefixSerializer() {
// non-null, immutable
super(false, true);
......
......@@ -8,9 +8,15 @@ import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
// TODO move to util, etc.
/**
* Serializer for {@link PortNumber}.
*/
public final class PortNumberSerializer extends
Serializer<PortNumber> {
/**
* Default constructor.
*/
public PortNumberSerializer() {
// non-null, immutable
super(false, true);
......
package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.provider.ProviderId;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
//TODO move to util, etc.
/**
* Serializer for {@link ProviderId}.
*/
public class ProviderIdSerializer extends Serializer<ProviderId> {
/**
* Default constructor.
*/
public ProviderIdSerializer() {
// non-null, immutable
super(false, true);
}
@Override
public void write(Kryo kryo, Output output, ProviderId object) {
output.writeString(object.scheme());
output.writeString(object.id());
}
@Override
public ProviderId read(Kryo kryo, Input input, Class<ProviderId> type) {
String scheme = input.readString();
String id = input.readString();
return new ProviderId(scheme, id);
}
}
/**
* Common abstractions and facilities for implementing distributed store
* using Hazelcast.
*/
package org.onlab.onos.store;
\ No newline at end of file
......@@ -28,6 +28,9 @@ class PathKey {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof PathKey) {
final PathKey other = (PathKey) obj;
return Objects.equals(this.src, other.src) && Objects.equals(this.dst, other.dst);
......
package org.onlab.onos.net.trivial.impl;
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.Service;
import org.onlab.onos.cluster.ClusterStore;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.NodeId;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import java.util.Set;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Manages inventory of infrastructure DEVICES using trivial in-memory
* structures implementation.
*/
@Component(immediate = true)
@Service
public class SimpleClusterStore implements ClusterStore {
public static final IpPrefix LOCALHOST = IpPrefix.valueOf("127.0.0.1");
private final Logger log = getLogger(getClass());
private ControllerNode instance;
@Activate
public void activate() {
instance = new DefaultControllerNode(new NodeId("local"), LOCALHOST);
log.info("Started");
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
@Override
public ControllerNode getLocalNode() {
return instance;
}
@Override
public Set<ControllerNode> getNodes() {
return ImmutableSet.of(instance);
}
@Override
public ControllerNode getNode(NodeId nodeId) {
return instance.id().equals(nodeId) ? instance : null;
}
@Override
public ControllerNode.State getState(NodeId nodeId) {
return ControllerNode.State.ACTIVE;
}
}
......@@ -35,7 +35,7 @@ import static org.onlab.onos.net.device.DeviceEvent.Type.*;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Manages inventory of infrastructure DEVICES using trivial in-memory
* Manages inventory of infrastructure devices using trivial in-memory
* structures implementation.
*/
@Component(immediate = true)
......
......@@ -179,6 +179,9 @@ public class SimpleLinkStore implements LinkStore {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof LinkKey) {
final LinkKey other = (LinkKey) obj;
return Objects.equals(this.src, other.src) &&
......
......@@ -392,7 +392,7 @@
<group>
<title>Core Subsystems</title>
<packages>
org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.net.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*
org.onlab.onos.cluster.impl:org.onlab.onos.store:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.net.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.cluster:org.onlab.onos.event.impl:org.onlab.onos.store.*
</packages>
</group>
<group>
......
......@@ -6,6 +6,7 @@ export ONOS_ROOT=${ONOS_ROOT:-~/onos-next}
# M2 repository and Karaf gold bits
export M2_REPO=${M2_REPO:-~/.m2/repository}
export KARAF_ZIP=${KARAF_ZIP:-~/Downloads/apache-karaf-3.0.1.zip}
export KARAF_TAR=${KARAF_TAR:-~/Downloads/apache-karaf-3.0.1.tar.gz}
export KARAF_DIST=$(basename $KARAF_ZIP .zip)
# ONOS Version and onos.tar.gz staging environment
......
......@@ -13,7 +13,7 @@ rm -fr $ONOS_STAGE # Remove this when package script is completed
# Make sure we have the original apache karaf bits first
[ ! -d $M2_REPO ] && echo "M2 repository $M2_REPO not found" && exit 1
[ ! -f $KARAF_ZIP ] && echo "Apache Karaf bits $KARAF_ZIP not found" && exit 1
[ ! -f $KARAF_ZIP -a ! -f $KARAF_TAR ] && echo "Apache Karaf bits $KARAF_ZIP or $KARAF_TAR not found" && exit 1
[ -d $ONOS_STAGE ] && echo "ONOS stage $ONOS_STAGE already exists" && exit 1
# Create the stage directory and warp into it
......@@ -21,7 +21,8 @@ mkdir -p $ONOS_STAGE
cd $ONOS_STAGE
# Unroll the Apache Karaf bits, prune them and make ONOS top-level directories.
unzip -q $KARAF_ZIP && rm -rf $KARAF_DIST/demos
[ -f $KARAF_ZIP ] && unzip -q $KARAF_ZIP && rm -rf $KARAF_DIST/demos
[ -f $KARAF_TAR ] && tar zxf $KARAF_TAR && rm -rf $KARAF_DIST/demos
mkdir bin
# Stage the ONOS admin scripts and patch in Karaf service wrapper extras
......@@ -33,15 +34,15 @@ cp -r $ONOS_ROOT/tools/package/etc/* $KARAF_DIST/etc
mkdir -p $KARAF_DIST/system/org/onlab
cp -r $M2_REPO/org/onlab $KARAF_DIST/system/org/
# Wrapper & Cellar Patching ----------------------------------------------------
# Cellar Patching --------------------------------------------------------------
# Patch the Apache Karaf distribution file to add Cellar features repository
perl -pi.old -e "s|^(featuresRepositories=.*)|\1,mvn:org.apache.karaf.cellar/apache-karaf-cellar/3.0.0/xml/features|" \
$ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
#perl -pi.old -e "s|^(featuresRepositories=.*)|\1,mvn:org.apache.karaf.cellar/apache-karaf-cellar/3.0.0/xml/features|" \
# $ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
# Patch the Apache Karaf distribution file to load ONOS features
perl -pi.old -e 's|^(featuresBoot=.*)|\1,cellar|' \
$ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
#perl -pi.old -e 's|^(featuresBoot=.*)|\1,cellar|' \
# $ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
# ONOS Patching ----------------------------------------------------------------
......@@ -49,6 +50,10 @@ perl -pi.old -e 's|^(featuresBoot=.*)|\1,cellar|' \
perl -pi.old -e "s|^(featuresRepositories=.*)|\1,mvn:org.onlab.onos/onos-features/$ONOS_VERSION/xml/features|" \
$ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
# Patch the Apache Karaf distribution file to load ONOS features
perl -pi.old -e 's|^(featuresBoot=.*)|\1,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-openflow,onos-app-tvue,onos-app-fwd|' \
$ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
# Patch the Apache Karaf distribution with ONOS branding bundle
cp $M2_REPO/org/onlab/onos/onos-branding/$ONOS_VERSION/onos-branding-*.jar \
$ONOS_STAGE/$KARAF_DIST/lib
......
......@@ -46,10 +46,7 @@ alias gui='open http://localhost:8181/onos/tvue'
# Test related conveniences
# SSH to a specified ONOS instance
function sshctl {
[ -n "$1" ] && OCI=$1 && shift
ssh -Y sdn@$OCI "$@"
}
alias sshctl=onos-ssh
# Applies the settings in the specified cell file or lists current cell definition
# if no cell file is given.
......
......@@ -21,7 +21,8 @@ ssh $remote "
echo 'Installing ONOS bundles...'
$onos cluster:feature-install default onos-api 1>>$LOG 2>&1
$onos cluster:feature-install default onos-core 1>>$LOG 2>&1
# $onos cluster:feature-install default onos-core 1>>$LOG 2>&1
$onos cluster:feature-install default onos-core-trivial 1>>$LOG 2>&1
$onos cluster:feature-install default onos-openflow 1>>$LOG 2>&1
$onos cluster:feature-install default onos-cli 1>>$LOG 2>&1
# $onos cluster:feature-install default onos-gui 1>>$LOG 2>&1
......
......@@ -27,6 +27,9 @@ ssh $remote "
# Install the upstart configuration file.
sudo cp $ONOS_INSTALL_DIR/debian/onos.conf /etc/init/onos.conf
# Remove any previous ON.Lab bits from ~/.m2 repo
rm -fr ~/.m2/repository/org/onlab
# Ignite the ONOS service.
sudo service onos start
"
......
#!/bin/bash
#-------------------------------------------------------------------------------
# Remotely patches the ONOS VM to tailor its hostname.
#-------------------------------------------------------------------------------
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
address=${1:-$OCI}
remote=$ONOS_USER@$address
name=${2:-onos-1}
[ -z "$address" ] && echo "Null address not allowed" >&2 && exit 1
[ -z "$name" ] && echo "Null name not allowed" >&2 && exit 1
ssh $remote "
sudo perl -pi.bak -e \"s/127.0.1.1.*/127.0.1.1 $name/g\" /etc/hosts
sudo echo $name /etc/hostname
sudo hostname $name
"
\ No newline at end of file
#!/bin/bash
#-------------------------------------------------------------------------------
# Pushes the local id_rsa.pub to the remote ONOS host authorized_keys.
#-------------------------------------------------------------------------------
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
remote=$ONOS_USER@${1:-$OCI}
scp -q ~/.ssh/id_rsa.pub $remote:/tmp
ssh $remote "cat /tmp/id_rsa.pub >> ~/.ssh/authorized_keys"
ssh -n -o PasswordAuthentication=no $remote true
#!/bin/bash
#-------------------------------------------------------------------------------
# Logs in to the remote ONOS instance.
#-------------------------------------------------------------------------------
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
[ -n "$1" ] && OCI=$1 && shift
ssh -Y $ONOS_USER@$OCI "$@"
#!/bin/bash
#-------------------------------------------------------------------------------
# Verifies connectivity to each node in ONOS cell.
#-------------------------------------------------------------------------------
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
for node in $(env | sort | egrep "OC[0-9]+" | cut -d= -f2); do
printf "%s: " $node; ssh -n -o PasswordAuthentication=no $ONOS_USER@$node date
done
\ No newline at end of file
#!/bin/bash
#-------------------------------------------------------------------------------
# Waits for ONOS to reach run-level 100.
#-------------------------------------------------------------------------------
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
remote=$ONOS_USER@${1:-$OCI}
ssh $remote "
# Wait until we reach the run-level 100
running=""
while [ -z \$running ]; do
$ONOS_INSTALL_DIR/bin/onos bundle:list 2>/dev/null | \
grep -q 'START LEVEL 100' && running=1 || sleep 2
done
"
......@@ -41,6 +41,9 @@ public abstract class AbstractEdge<V extends Vertex> implements Edge<V> {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof AbstractEdge) {
final AbstractEdge other = (AbstractEdge) obj;
return Objects.equals(this.src, other.src) && Objects.equals(this.dst, other.dst);
......
......@@ -80,6 +80,9 @@ public class AdjacencyListsGraph<V extends Vertex, E extends Edge<V>>
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof AdjacencyListsGraph) {
AdjacencyListsGraph that = (AdjacencyListsGraph) obj;
return this.getClass() == that.getClass() &&
......
......@@ -107,6 +107,9 @@ public class DefaultMutablePath<V extends Vertex, E extends Edge<V>> implements
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultMutablePath) {
final DefaultMutablePath other = (DefaultMutablePath) obj;
return Objects.equals(this.cost, other.cost) &&
......
......@@ -72,6 +72,9 @@ public class DefaultPath<V extends Vertex, E extends Edge<V>> implements Path<V,
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof DefaultPath) {
final DefaultPath other = (DefaultPath) obj;
return Objects.equals(this.src, other.src) &&
......
......@@ -166,6 +166,9 @@ public class Heap<T> {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Heap) {
Heap that = (Heap) obj;
return this.getClass() == that.getClass() &&
......
......@@ -39,6 +39,9 @@ public class TestEdge extends AbstractEdge<TestVertex> {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof TestEdge) {
final TestEdge other = (TestEdge) obj;
return super.equals(obj) && Objects.equals(this.weight, other.weight);
......
......@@ -20,6 +20,9 @@ public class TestVertex implements Vertex {
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof TestVertex) {
final TestVertex other = (TestVertex) obj;
return Objects.equals(this.name, other.name);
......