Madan Jampani

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

Showing 106 changed files with 1588 additions and 196 deletions
...@@ -100,6 +100,7 @@ public class ReactiveForwarding { ...@@ -100,6 +100,7 @@ public class ReactiveForwarding {
100 context.block(); 100 context.block();
101 return; 101 return;
102 } 102 }
103 +
103 HostId id = HostId.hostId(ethPkt.getDestinationMAC()); 104 HostId id = HostId.hostId(ethPkt.getDestinationMAC());
104 105
105 // Do we know who this is for? If not, flood and bail. 106 // Do we know who this is for? If not, flood and bail.
...@@ -112,7 +113,9 @@ public class ReactiveForwarding { ...@@ -112,7 +113,9 @@ public class ReactiveForwarding {
112 // Are we on an edge switch that our destination is on? If so, 113 // Are we on an edge switch that our destination is on? If so,
113 // simply forward out to the destination and bail. 114 // simply forward out to the destination and bail.
114 if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) { 115 if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) {
115 - installRule(context, dst.location().port()); 116 + if (!context.inPacket().receivedFrom().port().equals(dst.location().port())) {
117 + installRule(context, dst.location().port());
118 + }
116 return; 119 return;
117 } 120 }
118 121
...@@ -175,21 +178,24 @@ public class ReactiveForwarding { ...@@ -175,21 +178,24 @@ public class ReactiveForwarding {
175 // We don't yet support bufferids in the flowservice so packet out first. 178 // We don't yet support bufferids in the flowservice so packet out first.
176 packetOut(context, portNumber); 179 packetOut(context, portNumber);
177 180
178 - // Install the flow rule to handle this type of message from now on. 181 + if (context.inPacket().parsed().getEtherType() == Ethernet.TYPE_IPV4) {
179 - Ethernet inPkt = context.inPacket().parsed();
180 - TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
181 - builder.matchEthType(inPkt.getEtherType())
182 - .matchEthSrc(inPkt.getSourceMAC())
183 - .matchEthDst(inPkt.getDestinationMAC())
184 - .matchInport(context.inPacket().receivedFrom().port());
185 182
186 - TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder(); 183 + // Install the flow rule to handle this type of message from now on.
187 - treat.setOutput(portNumber); 184 + Ethernet inPkt = context.inPacket().parsed();
185 + TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
186 + builder.matchEthType(inPkt.getEtherType())
187 + .matchEthSrc(inPkt.getSourceMAC())
188 + .matchEthDst(inPkt.getDestinationMAC())
189 + .matchInport(context.inPacket().receivedFrom().port());
188 190
189 - FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(), 191 + TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder();
190 - builder.build(), treat.build(), 0, appId); 192 + treat.setOutput(portNumber);
191 193
192 - flowRuleService.applyFlowRules(f); 194 + FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(),
195 + builder.build(), treat.build(), 0, appId);
196 +
197 + flowRuleService.applyFlowRules(f);
198 + }
193 } 199 }
194 200
195 } 201 }
......
...@@ -56,7 +56,8 @@ public interface MastershipService { ...@@ -56,7 +56,8 @@ public interface MastershipService {
56 Set<DeviceId> getDevicesOf(NodeId nodeId); 56 Set<DeviceId> getDevicesOf(NodeId nodeId);
57 57
58 /** 58 /**
59 - * Returns the mastership term service for getting term information. 59 + * Returns the mastership term service for getting read-only
60 + * term information.
60 * 61 *
61 * @return the MastershipTermService for this mastership manager 62 * @return the MastershipTermService for this mastership manager
62 */ 63 */
......
...@@ -64,4 +64,14 @@ public interface MastershipStore extends Store<MastershipEvent, MastershipStoreD ...@@ -64,4 +64,14 @@ public interface MastershipStore extends Store<MastershipEvent, MastershipStoreD
64 * @return the current master's ID and the term value for device, or null 64 * @return the current master's ID and the term value for device, or null
65 */ 65 */
66 MastershipTerm getTermFor(DeviceId deviceId); 66 MastershipTerm getTermFor(DeviceId deviceId);
67 +
68 + /**
69 + * Revokes a controller instance's mastership over a device and hands
70 + * over mastership to another controller instance.
71 + *
72 + * @param nodeId the controller instance identifier
73 + * @param deviceId device to revoke mastership for
74 + * @return a mastership event
75 + */
76 + MastershipEvent unsetMaster(NodeId nodeId, DeviceId deviceId);
67 } 77 }
......
1 +package org.onlab.onos.net;
2 +
3 +import com.google.common.collect.ImmutableSet;
4 +
5 +import java.util.HashMap;
6 +import java.util.Map;
7 +import java.util.Set;
8 +
9 +import static com.google.common.base.Preconditions.checkArgument;
10 +
11 +/**
12 + * Base abstraction of an annotated entity.
13 + */
14 +public class AbstractAnnotated implements Annotated {
15 +
16 + private static final Map<String, String> EMPTY = new HashMap<>();
17 +
18 + private final Map<String, String> annotations;
19 +
20 + // For serialization
21 + protected AbstractAnnotated() {
22 + this.annotations = EMPTY;
23 + }
24 +
25 + /**
26 + * Creates a new entity, annotated with the specified annotations.
27 + *
28 + * @param annotations optional key/value annotations map
29 + */
30 + protected AbstractAnnotated(Map<String, String>[] annotations) {
31 + checkArgument(annotations.length <= 1, "Only one set of annotations is expected");
32 + this.annotations = annotations.length == 1 ? annotations[0] : EMPTY;
33 + }
34 +
35 + @Override
36 + public Set<String> annotationKeys() {
37 + return ImmutableSet.copyOf(annotations.keySet());
38 + }
39 +
40 + @Override
41 + public String annotation(String key) {
42 + return annotations.get(key);
43 + }
44 +
45 +}
...@@ -2,10 +2,12 @@ package org.onlab.onos.net; ...@@ -2,10 +2,12 @@ package org.onlab.onos.net;
2 2
3 import org.onlab.onos.net.provider.ProviderId; 3 import org.onlab.onos.net.provider.ProviderId;
4 4
5 +import java.util.Map;
6 +
5 /** 7 /**
6 * Base implementation of a network model entity. 8 * Base implementation of a network model entity.
7 */ 9 */
8 -public class AbstractModel implements Provided { 10 +public class AbstractModel extends AbstractAnnotated implements Provided {
9 11
10 private final ProviderId providerId; 12 private final ProviderId providerId;
11 13
...@@ -15,11 +17,16 @@ public class AbstractModel implements Provided { ...@@ -15,11 +17,16 @@ public class AbstractModel implements Provided {
15 } 17 }
16 18
17 /** 19 /**
18 - * Creates a model entity attributed to the specified provider. 20 + * Creates a model entity attributed to the specified provider and
21 + * optionally annotated.
19 * 22 *
20 - * @param providerId identity of the provider 23 + * @param providerId identity of the provider
24 + * @param annotations optional key/value annotations
21 */ 25 */
22 - protected AbstractModel(ProviderId providerId) { 26 + @SafeVarargs
27 + protected AbstractModel(ProviderId providerId,
28 + Map<String, String>... annotations) {
29 + super(annotations);
23 this.providerId = providerId; 30 this.providerId = providerId;
24 } 31 }
25 32
......
1 +package org.onlab.onos.net;
2 +
3 +import java.util.Set;
4 +
5 +/**
6 + * Represents an entity that carries arbitrary annotations.
7 + */
8 +public interface Annotated {
9 +
10 + /**
11 + * Returns the set of annotation keys currently available.
12 + *
13 + * @return set of annotation keys
14 + */
15 + Set<String> annotationKeys();
16 +
17 + /**
18 + * Returns the annotation value for the specified key.
19 + *
20 + * @param key annotation key
21 + * @return annotation value; null if there is no annotation
22 + */
23 + String annotation(String key);
24 +
25 +}
...@@ -3,5 +3,5 @@ package org.onlab.onos.net; ...@@ -3,5 +3,5 @@ package org.onlab.onos.net;
3 /** 3 /**
4 * Base abstraction of a piece of information about network elements. 4 * Base abstraction of a piece of information about network elements.
5 */ 5 */
6 -public interface Description { 6 +public interface Description extends Annotated {
7 } 7 }
......
1 package org.onlab.onos.net.device; 1 package org.onlab.onos.net.device;
2 2
3 +import org.onlab.onos.net.AbstractAnnotated;
4 +
3 import java.net.URI; 5 import java.net.URI;
6 +import java.util.Map;
4 7
5 import static com.google.common.base.MoreObjects.toStringHelper; 8 import static com.google.common.base.MoreObjects.toStringHelper;
6 import static com.google.common.base.Preconditions.checkNotNull; 9 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -9,7 +12,8 @@ import static org.onlab.onos.net.Device.Type; ...@@ -9,7 +12,8 @@ import static org.onlab.onos.net.Device.Type;
9 /** 12 /**
10 * Default implementation of immutable device description entity. 13 * Default implementation of immutable device description entity.
11 */ 14 */
12 -public class DefaultDeviceDescription implements DeviceDescription { 15 +public class DefaultDeviceDescription extends AbstractAnnotated
16 + implements DeviceDescription {
13 private final URI uri; 17 private final URI uri;
14 private final Type type; 18 private final Type type;
15 private final String manufacturer; 19 private final String manufacturer;
...@@ -26,10 +30,14 @@ public class DefaultDeviceDescription implements DeviceDescription { ...@@ -26,10 +30,14 @@ public class DefaultDeviceDescription implements DeviceDescription {
26 * @param hwVersion device HW version 30 * @param hwVersion device HW version
27 * @param swVersion device SW version 31 * @param swVersion device SW version
28 * @param serialNumber device serial number 32 * @param serialNumber device serial number
33 + * @param annotations optional key/value annotations map
29 */ 34 */
35 + @SafeVarargs
30 public DefaultDeviceDescription(URI uri, Type type, String manufacturer, 36 public DefaultDeviceDescription(URI uri, Type type, String manufacturer,
31 String hwVersion, String swVersion, 37 String hwVersion, String swVersion,
32 - String serialNumber) { 38 + String serialNumber,
39 + Map<String, String>... annotations) {
40 + super(annotations);
33 this.uri = checkNotNull(uri, "Device URI cannot be null"); 41 this.uri = checkNotNull(uri, "Device URI cannot be null");
34 this.type = checkNotNull(type, "Device type cannot be null"); 42 this.type = checkNotNull(type, "Device type cannot be null");
35 this.manufacturer = manufacturer; 43 this.manufacturer = manufacturer;
......
...@@ -48,6 +48,7 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -48,6 +48,7 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
48 DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId, 48 DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId,
49 DeviceDescription deviceDescription); 49 DeviceDescription deviceDescription);
50 50
51 + // TODO: We may need to enforce that ancillary cannot interfere this state
51 /** 52 /**
52 * Removes the specified infrastructure device. 53 * Removes the specified infrastructure device.
53 * 54 *
...@@ -60,22 +61,24 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -60,22 +61,24 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
60 * Updates the ports of the specified infrastructure device using the given 61 * Updates the ports of the specified infrastructure device using the given
61 * list of port descriptions. The list is assumed to be comprehensive. 62 * list of port descriptions. The list is assumed to be comprehensive.
62 * 63 *
64 + * @param providerId provider identifier
63 * @param deviceId device identifier 65 * @param deviceId device identifier
64 * @param portDescriptions list of port descriptions 66 * @param portDescriptions list of port descriptions
65 * @return ready to send events describing what occurred; empty list if no change 67 * @return ready to send events describing what occurred; empty list if no change
66 */ 68 */
67 - List<DeviceEvent> updatePorts(DeviceId deviceId, 69 + List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
68 List<PortDescription> portDescriptions); 70 List<PortDescription> portDescriptions);
69 71
70 /** 72 /**
71 * Updates the port status of the specified infrastructure device using the 73 * Updates the port status of the specified infrastructure device using the
72 * given port description. 74 * given port description.
73 * 75 *
76 + * @param providerId provider identifier
74 * @param deviceId device identifier 77 * @param deviceId device identifier
75 * @param portDescription port description 78 * @param portDescription port description
76 * @return ready to send event describing what occurred; null if no change 79 * @return ready to send event describing what occurred; null if no change
77 */ 80 */
78 - DeviceEvent updatePortStatus(DeviceId deviceId, 81 + DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
79 PortDescription portDescription); 82 PortDescription portDescription);
80 83
81 /** 84 /**
......
...@@ -27,9 +27,11 @@ public class DefaultFlowRule implements FlowRule { ...@@ -27,9 +27,11 @@ public class DefaultFlowRule implements FlowRule {
27 27
28 private final ApplicationId appId; 28 private final ApplicationId appId;
29 29
30 + private boolean expired;
31 +
30 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, 32 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
31 TrafficTreatment treatment, int priority, FlowRuleState state, 33 TrafficTreatment treatment, int priority, FlowRuleState state,
32 - long life, long packets, long bytes, long flowId) { 34 + long life, long packets, long bytes, long flowId, boolean expired) {
33 this.deviceId = deviceId; 35 this.deviceId = deviceId;
34 this.priority = priority; 36 this.priority = priority;
35 this.selector = selector; 37 this.selector = selector;
...@@ -37,7 +39,7 @@ public class DefaultFlowRule implements FlowRule { ...@@ -37,7 +39,7 @@ public class DefaultFlowRule implements FlowRule {
37 this.state = state; 39 this.state = state;
38 this.appId = ApplicationId.valueOf((int) (flowId >> 32)); 40 this.appId = ApplicationId.valueOf((int) (flowId >> 32));
39 this.id = FlowId.valueOf(flowId); 41 this.id = FlowId.valueOf(flowId);
40 - 42 + this.expired = expired;
41 this.life = life; 43 this.life = life;
42 this.packets = packets; 44 this.packets = packets;
43 this.bytes = bytes; 45 this.bytes = bytes;
...@@ -186,4 +188,9 @@ public class DefaultFlowRule implements FlowRule { ...@@ -186,4 +188,9 @@ public class DefaultFlowRule implements FlowRule {
186 .toString(); 188 .toString();
187 } 189 }
188 190
191 + @Override
192 + public boolean expired() {
193 + return expired;
194 + }
195 +
189 } 196 }
......
...@@ -111,4 +111,11 @@ public interface FlowRule { ...@@ -111,4 +111,11 @@ public interface FlowRule {
111 */ 111 */
112 long bytes(); 112 long bytes();
113 113
114 + /**
115 + * Indicates that this flow has expired at the device.
116 + *
117 + * @return true if it has expired, false otherwise
118 + */
119 + boolean expired();
120 +
114 } 121 }
......
1 package org.onlab.onos.net.host; 1 package org.onlab.onos.net.host;
2 2
3 -import static com.google.common.base.MoreObjects.toStringHelper; 3 +import com.google.common.collect.ImmutableSet;
4 - 4 +import org.onlab.onos.net.AbstractAnnotated;
5 -import java.util.HashSet;
6 -import java.util.Set;
7 -
8 import org.onlab.onos.net.HostLocation; 5 import org.onlab.onos.net.HostLocation;
9 import org.onlab.packet.IpPrefix; 6 import org.onlab.packet.IpPrefix;
10 import org.onlab.packet.MacAddress; 7 import org.onlab.packet.MacAddress;
11 import org.onlab.packet.VlanId; 8 import org.onlab.packet.VlanId;
12 9
13 -import com.google.common.collect.ImmutableSet; 10 +import java.util.HashSet;
11 +import java.util.Map;
12 +import java.util.Set;
13 +
14 +import static com.google.common.base.MoreObjects.toStringHelper;
14 15
15 -public class DefaultHostDescription implements HostDescription { 16 +/**
17 + * Default implementation of an immutable host description.
18 + */
19 +public class DefaultHostDescription extends AbstractAnnotated
20 + implements HostDescription {
16 21
17 private final MacAddress mac; 22 private final MacAddress mac;
18 private final VlanId vlan; 23 private final VlanId vlan;
19 private final HostLocation location; 24 private final HostLocation location;
20 private final Set<IpPrefix> ips; 25 private final Set<IpPrefix> ips;
21 26
27 + /**
28 + * Creates a host description using the supplied information.
29 + *
30 + * @param mac host MAC address
31 + * @param vlan host VLAN identifier
32 + * @param location host location
33 + * @param annotations optional key/value annotations map
34 + */
35 + @SafeVarargs
22 public DefaultHostDescription(MacAddress mac, VlanId vlan, 36 public DefaultHostDescription(MacAddress mac, VlanId vlan,
23 - HostLocation loc) { 37 + HostLocation location,
24 - this.mac = mac; 38 + Map<String, String>... annotations) {
25 - this.vlan = vlan; 39 + this(mac, vlan, location, new HashSet<IpPrefix>(), annotations);
26 - this.location = loc;
27 - this.ips = new HashSet<IpPrefix>();
28 } 40 }
29 41
42 + /**
43 + * Creates a host description using the supplied information.
44 + *
45 + * @param mac host MAC address
46 + * @param vlan host VLAN identifier
47 + * @param location host location
48 + * @param ips of host IP addresses
49 + * @param annotations optional key/value annotations map
50 + */
51 + @SafeVarargs
30 public DefaultHostDescription(MacAddress mac, VlanId vlan, 52 public DefaultHostDescription(MacAddress mac, VlanId vlan,
31 - HostLocation loc, Set<IpPrefix> ips) { 53 + HostLocation location, Set<IpPrefix> ips,
54 + Map<String, String>... annotations) {
55 + super(annotations);
32 this.mac = mac; 56 this.mac = mac;
33 this.vlan = vlan; 57 this.vlan = vlan;
34 - this.location = loc; 58 + this.location = location;
35 - this.ips = new HashSet<IpPrefix>(ips); 59 + this.ips = new HashSet<>(ips);
36 } 60 }
37 61
38 @Override 62 @Override
......
...@@ -35,10 +35,22 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -35,10 +35,22 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
35 public synchronized S register(P provider) { 35 public synchronized S register(P provider) {
36 checkNotNull(provider, "Provider cannot be null"); 36 checkNotNull(provider, "Provider cannot be null");
37 checkState(!services.containsKey(provider.id()), "Provider %s already registered", provider.id()); 37 checkState(!services.containsKey(provider.id()), "Provider %s already registered", provider.id());
38 +
39 + // If the provider is a primary one, check for a conflict.
40 + ProviderId pid = provider.id();
41 + checkState(pid.isAncillary() || !providersByScheme.containsKey(pid.scheme()),
42 + "A primary provider with id %s is already registered",
43 + providersByScheme.get(pid.scheme()));
44 +
38 S service = createProviderService(provider); 45 S service = createProviderService(provider);
39 services.put(provider.id(), service); 46 services.put(provider.id(), service);
40 providers.put(provider.id(), provider); 47 providers.put(provider.id(), provider);
41 - // FIXME populate scheme look-up 48 +
49 + // Register the provider by URI scheme only if it is not ancillary.
50 + if (!pid.isAncillary()) {
51 + providersByScheme.put(pid.scheme(), provider);
52 + }
53 +
42 return service; 54 return service;
43 } 55 }
44 56
......
...@@ -5,12 +5,35 @@ import java.util.Objects; ...@@ -5,12 +5,35 @@ import java.util.Objects;
5 import static com.google.common.base.MoreObjects.toStringHelper; 5 import static com.google.common.base.MoreObjects.toStringHelper;
6 6
7 /** 7 /**
8 - * Notion of provider identity. 8 + * External identity of a {@link org.onlab.onos.net.provider.Provider} family.
9 + * It also carriers two designations of external characteristics, the URI
10 + * scheme and primary/ancillary indicator.
11 + * <p/>
12 + * The device URI scheme is used to determine applicability of a provider to
13 + * operations on a specific device. The ancillary indicator serves to designate
14 + * a provider as a primary or ancillary.
15 + *
16 + * A {@link org.onlab.onos.net.provider.ProviderRegistry} uses this designation
17 + * to permit only one primary provider per device URI scheme. Multiple
18 + * ancillary providers can register with the same device URI scheme however.
9 */ 19 */
10 public class ProviderId { 20 public class ProviderId {
11 21
12 private final String scheme; 22 private final String scheme;
13 private final String id; 23 private final String id;
24 + private final boolean ancillary;
25 +
26 + /**
27 + * Creates a new primary provider identifier from the specified string.
28 + * The providers are expected to follow the reverse DNS convention, e.g.
29 + * {@code org.onlab.onos.provider.of.device}
30 + *
31 + * @param scheme device URI scheme to which this provider is bound, e.g. "of", "snmp"
32 + * @param id string identifier
33 + */
34 + public ProviderId(String scheme, String id) {
35 + this(scheme, id, false);
36 + }
14 37
15 /** 38 /**
16 * Creates a new provider identifier from the specified string. 39 * Creates a new provider identifier from the specified string.
...@@ -19,10 +42,12 @@ public class ProviderId { ...@@ -19,10 +42,12 @@ public class ProviderId {
19 * 42 *
20 * @param scheme device URI scheme to which this provider is bound, e.g. "of", "snmp" 43 * @param scheme device URI scheme to which this provider is bound, e.g. "of", "snmp"
21 * @param id string identifier 44 * @param id string identifier
45 + * @param ancillary ancillary provider indicator
22 */ 46 */
23 - public ProviderId(String scheme, String id) { 47 + public ProviderId(String scheme, String id, boolean ancillary) {
24 this.scheme = scheme; 48 this.scheme = scheme;
25 this.id = id; 49 this.id = id;
50 + this.ancillary = ancillary;
26 } 51 }
27 52
28 /** 53 /**
...@@ -43,6 +68,15 @@ public class ProviderId { ...@@ -43,6 +68,15 @@ public class ProviderId {
43 return id; 68 return id;
44 } 69 }
45 70
71 + /**
72 + * Indicates whether this identifier designates an ancillary providers.
73 + *
74 + * @return true if the provider is ancillary; false if primary
75 + */
76 + public boolean isAncillary() {
77 + return ancillary;
78 + }
79 +
46 @Override 80 @Override
47 public int hashCode() { 81 public int hashCode() {
48 return Objects.hash(scheme, id); 82 return Objects.hash(scheme, id);
...@@ -56,14 +90,16 @@ public class ProviderId { ...@@ -56,14 +90,16 @@ public class ProviderId {
56 if (obj instanceof ProviderId) { 90 if (obj instanceof ProviderId) {
57 final ProviderId other = (ProviderId) obj; 91 final ProviderId other = (ProviderId) obj;
58 return Objects.equals(this.scheme, other.scheme) && 92 return Objects.equals(this.scheme, other.scheme) &&
59 - Objects.equals(this.id, other.id); 93 + Objects.equals(this.id, other.id) &&
94 + this.ancillary == other.ancillary;
60 } 95 }
61 return false; 96 return false;
62 } 97 }
63 98
64 @Override 99 @Override
65 public String toString() { 100 public String toString() {
66 - return toStringHelper(this).add("scheme", scheme).add("id", id).toString(); 101 + return toStringHelper(this).add("scheme", scheme).add("id", id)
102 + .add("ancillary", ancillary).toString();
67 } 103 }
68 104
69 } 105 }
......
...@@ -2,6 +2,7 @@ package org.onlab.onos.net.topology; ...@@ -2,6 +2,7 @@ package org.onlab.onos.net.topology;
2 2
3 import com.google.common.collect.ImmutableSet; 3 import com.google.common.collect.ImmutableSet;
4 import com.google.common.collect.Maps; 4 import com.google.common.collect.Maps;
5 +import org.onlab.onos.net.AbstractAnnotated;
5 import org.onlab.onos.net.ConnectPoint; 6 import org.onlab.onos.net.ConnectPoint;
6 import org.onlab.onos.net.Device; 7 import org.onlab.onos.net.Device;
7 import org.onlab.onos.net.DeviceId; 8 import org.onlab.onos.net.DeviceId;
...@@ -12,7 +13,8 @@ import java.util.Map; ...@@ -12,7 +13,8 @@ import java.util.Map;
12 /** 13 /**
13 * Default implementation of an immutable topology graph data carrier. 14 * Default implementation of an immutable topology graph data carrier.
14 */ 15 */
15 -public class DefaultGraphDescription implements GraphDescription { 16 +public class DefaultGraphDescription extends AbstractAnnotated
17 + implements GraphDescription {
16 18
17 private final long nanos; 19 private final long nanos;
18 private final ImmutableSet<TopologyVertex> vertexes; 20 private final ImmutableSet<TopologyVertex> vertexes;
...@@ -25,11 +27,16 @@ public class DefaultGraphDescription implements GraphDescription { ...@@ -25,11 +27,16 @@ public class DefaultGraphDescription implements GraphDescription {
25 * Creates a minimal topology graph description to allow core to construct 27 * Creates a minimal topology graph description to allow core to construct
26 * and process the topology graph. 28 * and process the topology graph.
27 * 29 *
28 - * @param nanos time in nanos of when the topology description was created 30 + * @param nanos time in nanos of when the topology description was created
29 - * @param devices collection of infrastructure devices 31 + * @param devices collection of infrastructure devices
30 - * @param links collection of infrastructure links 32 + * @param links collection of infrastructure links
33 + * @param annotations optional key/value annotations map
31 */ 34 */
32 - public DefaultGraphDescription(long nanos, Iterable<Device> devices, Iterable<Link> links) { 35 + @SafeVarargs
36 + public DefaultGraphDescription(long nanos, Iterable<Device> devices,
37 + Iterable<Link> links,
38 + Map<String, String>... annotations) {
39 + super(annotations);
33 this.nanos = nanos; 40 this.nanos = nanos;
34 this.vertexes = buildVertexes(devices); 41 this.vertexes = buildVertexes(devices);
35 this.edges = buildEdges(links); 42 this.edges = buildEdges(links);
......
1 +package org.onlab.onos.cluster;
2 +
3 +import static org.junit.Assert.assertEquals;
4 +
5 +import org.junit.Test;
6 +
7 +import com.google.common.testing.EqualsTester;
8 +
9 +public class MastershipTermTest {
10 +
11 + private static final NodeId N1 = new NodeId("foo");
12 + private static final NodeId N2 = new NodeId("bar");
13 +
14 + private static final MastershipTerm TERM1 = MastershipTerm.of(N1, 0);
15 + private static final MastershipTerm TERM2 = MastershipTerm.of(N2, 1);
16 + private static final MastershipTerm TERM3 = MastershipTerm.of(N2, 1);
17 + private static final MastershipTerm TERM4 = MastershipTerm.of(N1, 1);
18 +
19 + @Test
20 + public void basics() {
21 + assertEquals("incorrect term number", 0, TERM1.termNumber());
22 + assertEquals("incorrect master", new NodeId("foo"), TERM1.master());
23 + }
24 +
25 + @Test
26 + public void testEquality() {
27 + new EqualsTester().addEqualityGroup(MastershipTerm.of(N1, 0), TERM1)
28 + .addEqualityGroup(TERM2, TERM3)
29 + .addEqualityGroup(TERM4);
30 + }
31 +
32 +}
...@@ -35,7 +35,7 @@ public class AbstractProviderRegistryTest { ...@@ -35,7 +35,7 @@ public class AbstractProviderRegistryTest {
35 assertThat("provider not found", registry.getProviders().contains(fooId)); 35 assertThat("provider not found", registry.getProviders().contains(fooId));
36 assertEquals("incorrect provider", psFoo.provider(), pFoo); 36 assertEquals("incorrect provider", psFoo.provider(), pFoo);
37 37
38 - ProviderId barId = new ProviderId("of", "bar"); 38 + ProviderId barId = new ProviderId("snmp", "bar");
39 TestProvider pBar = new TestProvider(barId); 39 TestProvider pBar = new TestProvider(barId);
40 TestProviderService psBar = registry.register(pBar); 40 TestProviderService psBar = registry.register(pBar);
41 assertEquals("incorrect provider count", 2, registry.getProviders().size()); 41 assertEquals("incorrect provider count", 2, registry.getProviders().size());
...@@ -49,6 +49,16 @@ public class AbstractProviderRegistryTest { ...@@ -49,6 +49,16 @@ public class AbstractProviderRegistryTest {
49 assertThat("provider not found", registry.getProviders().contains(barId)); 49 assertThat("provider not found", registry.getProviders().contains(barId));
50 } 50 }
51 51
52 + @Test
53 + public void ancillaryProviders() {
54 + TestProviderRegistry registry = new TestProviderRegistry();
55 + TestProvider pFoo = new TestProvider(new ProviderId("of", "foo"));
56 + TestProvider pBar = new TestProvider(new ProviderId("of", "bar", true));
57 + registry.register(pFoo);
58 + registry.register(pBar);
59 + assertEquals("incorrect provider count", 2, registry.getProviders().size());
60 + }
61 +
52 @Test(expected = IllegalStateException.class) 62 @Test(expected = IllegalStateException.class)
53 public void duplicateRegistration() { 63 public void duplicateRegistration() {
54 TestProviderRegistry registry = new TestProviderRegistry(); 64 TestProviderRegistry registry = new TestProviderRegistry();
...@@ -57,6 +67,15 @@ public class AbstractProviderRegistryTest { ...@@ -57,6 +67,15 @@ public class AbstractProviderRegistryTest {
57 registry.register(pFoo); 67 registry.register(pFoo);
58 } 68 }
59 69
70 + @Test(expected = IllegalStateException.class)
71 + public void duplicateSchemeRegistration() {
72 + TestProviderRegistry registry = new TestProviderRegistry();
73 + TestProvider pFoo = new TestProvider(new ProviderId("of", "foo"));
74 + TestProvider pBar = new TestProvider(new ProviderId("of", "bar"));
75 + registry.register(pFoo);
76 + registry.register(pBar);
77 + }
78 +
60 @Test 79 @Test
61 public void voidUnregistration() { 80 public void voidUnregistration() {
62 TestProviderRegistry registry = new TestProviderRegistry(); 81 TestProviderRegistry registry = new TestProviderRegistry();
......
...@@ -11,6 +11,8 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -11,6 +11,8 @@ import org.apache.felix.scr.annotations.Deactivate;
11 import org.apache.felix.scr.annotations.Reference; 11 import org.apache.felix.scr.annotations.Reference;
12 import org.apache.felix.scr.annotations.ReferenceCardinality; 12 import org.apache.felix.scr.annotations.ReferenceCardinality;
13 import org.apache.felix.scr.annotations.Service; 13 import org.apache.felix.scr.annotations.Service;
14 +import org.onlab.onos.cluster.ClusterEvent;
15 +import org.onlab.onos.cluster.ClusterEventListener;
14 import org.onlab.onos.cluster.ClusterService; 16 import org.onlab.onos.cluster.ClusterService;
15 import org.onlab.onos.cluster.MastershipAdminService; 17 import org.onlab.onos.cluster.MastershipAdminService;
16 import org.onlab.onos.cluster.MastershipEvent; 18 import org.onlab.onos.cluster.MastershipEvent;
...@@ -52,9 +54,12 @@ implements MastershipService, MastershipAdminService { ...@@ -52,9 +54,12 @@ implements MastershipService, MastershipAdminService {
52 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 protected ClusterService clusterService; 55 protected ClusterService clusterService;
54 56
57 + private ClusterEventListener clusterListener = new InternalClusterEventListener();
58 +
55 @Activate 59 @Activate
56 public void activate() { 60 public void activate() {
57 eventDispatcher.addSink(MastershipEvent.class, listenerRegistry); 61 eventDispatcher.addSink(MastershipEvent.class, listenerRegistry);
62 + clusterService.addListener(clusterListener);
58 store.setDelegate(delegate); 63 store.setDelegate(delegate);
59 log.info("Started"); 64 log.info("Started");
60 } 65 }
...@@ -62,6 +67,7 @@ implements MastershipService, MastershipAdminService { ...@@ -62,6 +67,7 @@ implements MastershipService, MastershipAdminService {
62 @Deactivate 67 @Deactivate
63 public void deactivate() { 68 public void deactivate() {
64 eventDispatcher.removeSink(MastershipEvent.class); 69 eventDispatcher.removeSink(MastershipEvent.class);
70 + clusterService.removeListener(clusterListener);
65 store.unsetDelegate(delegate); 71 store.unsetDelegate(delegate);
66 log.info("Stopped"); 72 log.info("Stopped");
67 } 73 }
...@@ -71,12 +77,16 @@ implements MastershipService, MastershipAdminService { ...@@ -71,12 +77,16 @@ implements MastershipService, MastershipAdminService {
71 checkNotNull(nodeId, NODE_ID_NULL); 77 checkNotNull(nodeId, NODE_ID_NULL);
72 checkNotNull(deviceId, DEVICE_ID_NULL); 78 checkNotNull(deviceId, DEVICE_ID_NULL);
73 checkNotNull(role, ROLE_NULL); 79 checkNotNull(role, ROLE_NULL);
74 - //TODO figure out appropriate action for non-MASTER roles, if we even set those 80 +
81 + MastershipEvent event = null;
75 if (role.equals(MastershipRole.MASTER)) { 82 if (role.equals(MastershipRole.MASTER)) {
76 - MastershipEvent event = store.setMaster(nodeId, deviceId); 83 + event = store.setMaster(nodeId, deviceId);
77 - if (event != null) { 84 + } else {
78 - post(event); 85 + event = store.unsetMaster(nodeId, deviceId);
79 - } 86 + }
87 +
88 + if (event != null) {
89 + post(event);
80 } 90 }
81 } 91 }
82 92
...@@ -88,8 +98,16 @@ implements MastershipService, MastershipAdminService { ...@@ -88,8 +98,16 @@ implements MastershipService, MastershipAdminService {
88 98
89 @Override 99 @Override
90 public void relinquishMastership(DeviceId deviceId) { 100 public void relinquishMastership(DeviceId deviceId) {
91 - checkNotNull(deviceId, DEVICE_ID_NULL); 101 + MastershipRole role = getLocalRole(deviceId);
92 - // FIXME: add method to store to give up mastership and trigger new master selection process 102 + if (!role.equals(MastershipRole.MASTER)) {
103 + return;
104 + }
105 +
106 + MastershipEvent event = store.unsetMaster(
107 + clusterService.getLocalNode().id(), deviceId);
108 + if (event != null) {
109 + post(event);
110 + }
93 } 111 }
94 112
95 @Override 113 @Override
...@@ -146,6 +164,26 @@ implements MastershipService, MastershipAdminService { ...@@ -146,6 +164,26 @@ implements MastershipService, MastershipAdminService {
146 164
147 } 165 }
148 166
167 + //callback for reacting to cluster events
168 + private class InternalClusterEventListener implements ClusterEventListener {
169 +
170 + @Override
171 + public void event(ClusterEvent event) {
172 + switch (event.type()) {
173 + //FIXME: worry about addition when the time comes
174 + case INSTANCE_ADDED:
175 + case INSTANCE_ACTIVATED:
176 + break;
177 + case INSTANCE_REMOVED:
178 + case INSTANCE_DEACTIVATED:
179 + break;
180 + default:
181 + log.warn("unknown cluster event {}", event);
182 + }
183 + }
184 +
185 + }
186 +
149 public class InternalDelegate implements MastershipStoreDelegate { 187 public class InternalDelegate implements MastershipStoreDelegate {
150 188
151 @Override 189 @Override
......
...@@ -16,6 +16,7 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -16,6 +16,7 @@ import org.onlab.onos.cluster.ClusterService;
16 import org.onlab.onos.cluster.MastershipEvent; 16 import org.onlab.onos.cluster.MastershipEvent;
17 import org.onlab.onos.cluster.MastershipListener; 17 import org.onlab.onos.cluster.MastershipListener;
18 import org.onlab.onos.cluster.MastershipService; 18 import org.onlab.onos.cluster.MastershipService;
19 +import org.onlab.onos.cluster.MastershipTermService;
19 import org.onlab.onos.cluster.MastershipTerm; 20 import org.onlab.onos.cluster.MastershipTerm;
20 import org.onlab.onos.event.AbstractListenerRegistry; 21 import org.onlab.onos.event.AbstractListenerRegistry;
21 import org.onlab.onos.event.EventDeliveryService; 22 import org.onlab.onos.event.EventDeliveryService;
...@@ -76,6 +77,8 @@ public class DeviceManager ...@@ -76,6 +77,8 @@ public class DeviceManager
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected MastershipService mastershipService; 78 protected MastershipService mastershipService;
78 79
80 + protected MastershipTermService termService;
81 +
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected ClockService clockService; 83 protected ClockService clockService;
81 84
...@@ -84,6 +87,7 @@ public class DeviceManager ...@@ -84,6 +87,7 @@ public class DeviceManager
84 store.setDelegate(delegate); 87 store.setDelegate(delegate);
85 eventDispatcher.addSink(DeviceEvent.class, listenerRegistry); 88 eventDispatcher.addSink(DeviceEvent.class, listenerRegistry);
86 mastershipService.addListener(mastershipListener); 89 mastershipService.addListener(mastershipListener);
90 + termService = mastershipService.requestTermService();
87 log.info("Started"); 91 log.info("Started");
88 } 92 }
89 93
...@@ -198,7 +202,7 @@ public class DeviceManager ...@@ -198,7 +202,7 @@ public class DeviceManager
198 log.info("Device {} connected", deviceId); 202 log.info("Device {} connected", deviceId);
199 mastershipService.requestRoleFor(deviceId); 203 mastershipService.requestRoleFor(deviceId);
200 provider().roleChanged(event.subject(), 204 provider().roleChanged(event.subject(),
201 - mastershipService.getLocalRole(deviceId)); 205 + mastershipService.requestRoleFor(deviceId));
202 post(event); 206 post(event);
203 } 207 }
204 } 208 }
...@@ -208,8 +212,11 @@ public class DeviceManager ...@@ -208,8 +212,11 @@ public class DeviceManager
208 checkNotNull(deviceId, DEVICE_ID_NULL); 212 checkNotNull(deviceId, DEVICE_ID_NULL);
209 checkValidity(); 213 checkValidity();
210 DeviceEvent event = store.markOffline(deviceId); 214 DeviceEvent event = store.markOffline(deviceId);
215 +
216 + //we're no longer capable of mastership.
211 if (event != null) { 217 if (event != null) {
212 log.info("Device {} disconnected", deviceId); 218 log.info("Device {} disconnected", deviceId);
219 + mastershipService.relinquishMastership(deviceId);
213 post(event); 220 post(event);
214 } 221 }
215 } 222 }
...@@ -221,8 +228,9 @@ public class DeviceManager ...@@ -221,8 +228,9 @@ public class DeviceManager
221 checkNotNull(portDescriptions, 228 checkNotNull(portDescriptions,
222 "Port descriptions list cannot be null"); 229 "Port descriptions list cannot be null");
223 checkValidity(); 230 checkValidity();
224 - List<DeviceEvent> events = store.updatePorts(deviceId, 231 + this.provider().id();
225 - portDescriptions); 232 + List<DeviceEvent> events = store.updatePorts(this.provider().id(),
233 + deviceId, portDescriptions);
226 for (DeviceEvent event : events) { 234 for (DeviceEvent event : events) {
227 post(event); 235 post(event);
228 } 236 }
...@@ -234,8 +242,8 @@ public class DeviceManager ...@@ -234,8 +242,8 @@ public class DeviceManager
234 checkNotNull(deviceId, DEVICE_ID_NULL); 242 checkNotNull(deviceId, DEVICE_ID_NULL);
235 checkNotNull(portDescription, PORT_DESCRIPTION_NULL); 243 checkNotNull(portDescription, PORT_DESCRIPTION_NULL);
236 checkValidity(); 244 checkValidity();
237 - DeviceEvent event = store.updatePortStatus(deviceId, 245 + DeviceEvent event = store.updatePortStatus(this.provider().id(),
238 - portDescription); 246 + deviceId, portDescription);
239 if (event != null) { 247 if (event != null) {
240 log.info("Device {} port {} status changed", deviceId, event 248 log.info("Device {} port {} status changed", deviceId, event
241 .port().number()); 249 .port().number());
......
...@@ -161,7 +161,11 @@ implements FlowRuleService, FlowRuleProviderRegistry { ...@@ -161,7 +161,11 @@ implements FlowRuleService, FlowRuleProviderRegistry {
161 switch (stored.state()) { 161 switch (stored.state()) {
162 case ADDED: 162 case ADDED:
163 case PENDING_ADD: 163 case PENDING_ADD:
164 - frp.applyFlowRule(stored); 164 + if (flowRule.expired()) {
165 + event = store.removeFlowRule(flowRule);
166 + } else {
167 + frp.applyFlowRule(stored);
168 + }
165 break; 169 break;
166 case PENDING_REMOVE: 170 case PENDING_REMOVE:
167 case REMOVED: 171 case REMOVED:
......
...@@ -231,6 +231,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -231,6 +231,7 @@ public class ProxyArpManager implements ProxyArpService {
231 arp.setOpCode(ARP.OP_REPLY); 231 arp.setOpCode(ARP.OP_REPLY);
232 arp.setProtocolType(ARP.PROTO_TYPE_IP); 232 arp.setProtocolType(ARP.PROTO_TYPE_IP);
233 arp.setHardwareType(ARP.HW_TYPE_ETHERNET); 233 arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
234 +
234 arp.setProtocolAddressLength((byte) IpPrefix.INET_LEN); 235 arp.setProtocolAddressLength((byte) IpPrefix.INET_LEN);
235 arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH); 236 arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
236 arp.setSenderHardwareAddress(h.mac().getAddress()); 237 arp.setSenderHardwareAddress(h.mac().getAddress());
...@@ -238,7 +239,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -238,7 +239,7 @@ public class ProxyArpManager implements ProxyArpService {
238 239
239 arp.setTargetProtocolAddress(((ARP) request.getPayload()) 240 arp.setTargetProtocolAddress(((ARP) request.getPayload())
240 .getSenderProtocolAddress()); 241 .getSenderProtocolAddress());
241 - arp.setSenderProtocolAddress(h.ipAddresses().iterator().next().toInt()); 242 + arp.setSenderProtocolAddress(h.ipAddresses().iterator().next().toRealInt());
242 eth.setPayload(arp); 243 eth.setPayload(arp);
243 return eth; 244 return eth;
244 } 245 }
...@@ -291,7 +292,6 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -291,7 +292,6 @@ public class ProxyArpManager implements ProxyArpService {
291 case DEVICE_MASTERSHIP_CHANGED: 292 case DEVICE_MASTERSHIP_CHANGED:
292 case DEVICE_SUSPENDED: 293 case DEVICE_SUSPENDED:
293 case DEVICE_UPDATED: 294 case DEVICE_UPDATED:
294 - case PORT_UPDATED:
295 // nothing to do in these cases; handled when links get reported 295 // nothing to do in these cases; handled when links get reported
296 break; 296 break;
297 case DEVICE_REMOVED: 297 case DEVICE_REMOVED:
...@@ -301,9 +301,12 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -301,9 +301,12 @@ public class ProxyArpManager implements ProxyArpService {
301 } 301 }
302 break; 302 break;
303 case PORT_ADDED: 303 case PORT_ADDED:
304 + case PORT_UPDATED:
304 synchronized (externalPorts) { 305 synchronized (externalPorts) {
305 - externalPorts.put(device, event.port().number()); 306 + if (event.port().isEnabled()) {
306 - internalPorts.remove(device, event.port().number()); 307 + externalPorts.put(device, event.port().number());
308 + internalPorts.remove(device, event.port().number());
309 + }
307 } 310 }
308 break; 311 break;
309 case PORT_REMOVED: 312 case PORT_REMOVED:
......
...@@ -65,8 +65,8 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -65,8 +65,8 @@ public class DefaultTopologyProvider extends AbstractProvider
65 private volatile boolean isStarted = false; 65 private volatile boolean isStarted = false;
66 66
67 private TopologyProviderService providerService; 67 private TopologyProviderService providerService;
68 - private DeviceListener deviceListener = new InnerDeviceListener(); 68 + private DeviceListener deviceListener = new InternalDeviceListener();
69 - private LinkListener linkListener = new InnerLinkListener(); 69 + private LinkListener linkListener = new InternalLinkListener();
70 70
71 private EventAccumulator accumulator; 71 private EventAccumulator accumulator;
72 private ExecutorService executor; 72 private ExecutorService executor;
...@@ -132,7 +132,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -132,7 +132,7 @@ public class DefaultTopologyProvider extends AbstractProvider
132 } 132 }
133 133
134 // Callback for device events 134 // Callback for device events
135 - private class InnerDeviceListener implements DeviceListener { 135 + private class InternalDeviceListener implements DeviceListener {
136 @Override 136 @Override
137 public void event(DeviceEvent event) { 137 public void event(DeviceEvent event) {
138 DeviceEvent.Type type = event.type(); 138 DeviceEvent.Type type = event.type();
...@@ -144,7 +144,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -144,7 +144,7 @@ public class DefaultTopologyProvider extends AbstractProvider
144 } 144 }
145 145
146 // Callback for link events 146 // Callback for link events
147 - private class InnerLinkListener implements LinkListener { 147 + private class InternalLinkListener implements LinkListener {
148 @Override 148 @Override
149 public void event(LinkEvent event) { 149 public void event(LinkEvent event) {
150 accumulator.add(event); 150 accumulator.add(event);
......
...@@ -15,10 +15,11 @@ import org.onlab.onos.cluster.MastershipTermService; ...@@ -15,10 +15,11 @@ import org.onlab.onos.cluster.MastershipTermService;
15 import org.onlab.onos.cluster.NodeId; 15 import org.onlab.onos.cluster.NodeId;
16 import org.onlab.onos.event.impl.TestEventDispatcher; 16 import org.onlab.onos.event.impl.TestEventDispatcher;
17 import org.onlab.onos.net.DeviceId; 17 import org.onlab.onos.net.DeviceId;
18 -import org.onlab.onos.net.trivial.impl.SimpleMastershipStore; 18 +import org.onlab.onos.store.trivial.impl.SimpleMastershipStore;
19 import org.onlab.packet.IpPrefix; 19 import org.onlab.packet.IpPrefix;
20 20
21 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertEquals;
22 +import static org.junit.Assert.assertNull;
22 import static org.onlab.onos.net.MastershipRole.*; 23 import static org.onlab.onos.net.MastershipRole.*;
23 24
24 /** 25 /**
...@@ -65,7 +66,24 @@ public class MastershipManagerTest { ...@@ -65,7 +66,24 @@ public class MastershipManagerTest {
65 66
66 @Test 67 @Test
67 public void relinquishMastership() { 68 public void relinquishMastership() {
68 - //TODO 69 + //no backups - should turn to standby and no master for device
70 + mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
71 + assertEquals("wrong role:", MASTER, mgr.getLocalRole(DEV_MASTER));
72 + mgr.relinquishMastership(DEV_MASTER);
73 + assertNull("wrong master:", mgr.getMasterFor(DEV_OTHER));
74 + assertEquals("wrong role:", STANDBY, mgr.getLocalRole(DEV_MASTER));
75 +
76 + //not master, nothing should happen
77 + mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY);
78 + mgr.relinquishMastership(DEV_OTHER);
79 + assertNull("wrong role:", mgr.getMasterFor(DEV_OTHER));
80 +
81 + //provide NID_OTHER as backup and relinquish
82 + mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
83 + assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_MASTER));
84 + mgr.setRole(NID_OTHER, DEV_MASTER, STANDBY);
85 + mgr.relinquishMastership(DEV_MASTER);
86 + assertEquals("wrong master:", NID_OTHER, mgr.getMasterFor(DEV_MASTER));
69 } 87 }
70 88
71 @Test 89 @Test
...@@ -95,7 +113,6 @@ public class MastershipManagerTest { ...@@ -95,7 +113,6 @@ public class MastershipManagerTest {
95 mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER); 113 mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
96 mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY); 114 mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY);
97 assertEquals("should be one device:", 1, mgr.getDevicesOf(NID_LOCAL).size()); 115 assertEquals("should be one device:", 1, mgr.getDevicesOf(NID_LOCAL).size());
98 -
99 //hand both devices to NID_LOCAL 116 //hand both devices to NID_LOCAL
100 mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER); 117 mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER);
101 assertEquals("should be two devices:", 2, mgr.getDevicesOf(NID_LOCAL).size()); 118 assertEquals("should be two devices:", 2, mgr.getDevicesOf(NID_LOCAL).size());
......
...@@ -27,7 +27,7 @@ import org.onlab.onos.net.device.DeviceService; ...@@ -27,7 +27,7 @@ import org.onlab.onos.net.device.DeviceService;
27 import org.onlab.onos.net.device.PortDescription; 27 import org.onlab.onos.net.device.PortDescription;
28 import org.onlab.onos.net.provider.AbstractProvider; 28 import org.onlab.onos.net.provider.AbstractProvider;
29 import org.onlab.onos.net.provider.ProviderId; 29 import org.onlab.onos.net.provider.ProviderId;
30 -import org.onlab.onos.net.trivial.impl.SimpleDeviceStore; 30 +import org.onlab.onos.store.trivial.impl.SimpleDeviceStore;
31 31
32 import java.util.ArrayList; 32 import java.util.ArrayList;
33 import java.util.Iterator; 33 import java.util.Iterator;
......
...@@ -40,7 +40,7 @@ import org.onlab.onos.net.flow.criteria.Criterion; ...@@ -40,7 +40,7 @@ import org.onlab.onos.net.flow.criteria.Criterion;
40 import org.onlab.onos.net.flow.instructions.Instruction; 40 import org.onlab.onos.net.flow.instructions.Instruction;
41 import org.onlab.onos.net.provider.AbstractProvider; 41 import org.onlab.onos.net.provider.AbstractProvider;
42 import org.onlab.onos.net.provider.ProviderId; 42 import org.onlab.onos.net.provider.ProviderId;
43 -import org.onlab.onos.net.trivial.impl.SimpleFlowRuleStore; 43 +import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
44 44
45 import com.google.common.collect.Lists; 45 import com.google.common.collect.Lists;
46 import com.google.common.collect.Sets; 46 import com.google.common.collect.Sets;
......
...@@ -34,7 +34,7 @@ import org.onlab.onos.net.host.HostProviderService; ...@@ -34,7 +34,7 @@ import org.onlab.onos.net.host.HostProviderService;
34 import org.onlab.onos.net.host.PortAddresses; 34 import org.onlab.onos.net.host.PortAddresses;
35 import org.onlab.onos.net.provider.AbstractProvider; 35 import org.onlab.onos.net.provider.AbstractProvider;
36 import org.onlab.onos.net.provider.ProviderId; 36 import org.onlab.onos.net.provider.ProviderId;
37 -import org.onlab.onos.net.trivial.impl.SimpleHostStore; 37 +import org.onlab.onos.store.trivial.impl.SimpleHostStore;
38 import org.onlab.packet.IpPrefix; 38 import org.onlab.packet.IpPrefix;
39 import org.onlab.packet.MacAddress; 39 import org.onlab.packet.MacAddress;
40 import org.onlab.packet.VlanId; 40 import org.onlab.packet.VlanId;
......
...@@ -23,7 +23,7 @@ import org.onlab.onos.net.provider.AbstractProvider; ...@@ -23,7 +23,7 @@ import org.onlab.onos.net.provider.AbstractProvider;
23 import org.onlab.onos.net.provider.ProviderId; 23 import org.onlab.onos.net.provider.ProviderId;
24 import org.onlab.onos.event.impl.TestEventDispatcher; 24 import org.onlab.onos.event.impl.TestEventDispatcher;
25 import org.onlab.onos.net.device.impl.DeviceManager; 25 import org.onlab.onos.net.device.impl.DeviceManager;
26 -import org.onlab.onos.net.trivial.impl.SimpleLinkStore; 26 +import org.onlab.onos.store.trivial.impl.SimpleLinkStore;
27 27
28 import java.util.ArrayList; 28 import java.util.ArrayList;
29 import java.util.Iterator; 29 import java.util.Iterator;
......
...@@ -24,7 +24,7 @@ import org.onlab.onos.net.topology.TopologyProvider; ...@@ -24,7 +24,7 @@ import org.onlab.onos.net.topology.TopologyProvider;
24 import org.onlab.onos.net.topology.TopologyProviderRegistry; 24 import org.onlab.onos.net.topology.TopologyProviderRegistry;
25 import org.onlab.onos.net.topology.TopologyProviderService; 25 import org.onlab.onos.net.topology.TopologyProviderService;
26 import org.onlab.onos.net.topology.TopologyService; 26 import org.onlab.onos.net.topology.TopologyService;
27 -import org.onlab.onos.net.trivial.impl.SimpleTopologyStore; 27 +import org.onlab.onos.store.trivial.impl.SimpleTopologyStore;
28 28
29 import java.util.ArrayList; 29 import java.util.ArrayList;
30 import java.util.List; 30 import java.util.List;
......
1 /** 1 /**
2 * Distributed cluster store and messaging subsystem implementation. 2 * Distributed cluster store and messaging subsystem implementation.
3 */ 3 */
4 -package org.onlab.onos.store.cluster.impl;
...\ No newline at end of file ...\ No newline at end of file
4 +package org.onlab.onos.store.cluster.impl;
......
1 +package org.onlab.onos.store.cluster.messaging;
2 +
3 +import static org.onlab.onos.store.cluster.messaging.MessageSubject.AE_ADVERTISEMENT;
4 +import java.util.Map;
5 +
6 +import org.onlab.onos.cluster.NodeId;
7 +import org.onlab.onos.store.Timestamp;
8 +
9 +import com.google.common.collect.ImmutableMap;
10 +
11 +/**
12 + * Anti-Entropy advertisement message.
13 + * <p>
14 + * Message to advertise the information this node holds.
15 + *
16 + * @param <ID> ID type
17 + */
18 +public class AntiEntropyAdvertisement<ID> extends ClusterMessage {
19 +
20 + private final NodeId sender;
21 + private final ImmutableMap<ID, Timestamp> advertisement;
22 +
23 + /**
24 + * Creates anti-entropy advertisement message.
25 + *
26 + * @param sender sender of this message
27 + * @param advertisement timestamp information of the data sender holds
28 + */
29 + public AntiEntropyAdvertisement(NodeId sender, Map<ID, Timestamp> advertisement) {
30 + super(AE_ADVERTISEMENT);
31 + this.sender = sender;
32 + this.advertisement = ImmutableMap.copyOf(advertisement);
33 + }
34 +
35 + public NodeId sender() {
36 + return sender;
37 + }
38 +
39 + public ImmutableMap<ID, Timestamp> advertisement() {
40 + return advertisement;
41 + }
42 +
43 + // Default constructor for serializer
44 + protected AntiEntropyAdvertisement() {
45 + super(AE_ADVERTISEMENT);
46 + this.sender = null;
47 + this.advertisement = null;
48 + }
49 +}
1 +package org.onlab.onos.store.cluster.messaging;
2 +
3 +import static org.onlab.onos.store.cluster.messaging.MessageSubject.AE_REPLY;
4 +
5 +import java.util.Map;
6 +import java.util.Set;
7 +
8 +import org.onlab.onos.cluster.NodeId;
9 +import org.onlab.onos.store.device.impl.VersionedValue;
10 +
11 +import com.google.common.collect.ImmutableMap;
12 +import com.google.common.collect.ImmutableSet;
13 +
14 +/**
15 + * Anti-Entropy reply message.
16 + * <p>
17 + * Message to send in reply to advertisement or another reply.
18 + * Suggest to the sender about the more up-to-date data this node has,
19 + * and request for more recent data that the receiver has.
20 + */
21 +public class AntiEntropyReply<ID, V extends VersionedValue<?>> extends ClusterMessage {
22 +
23 + private final NodeId sender;
24 + private final ImmutableMap<ID, V> suggestion;
25 + private final ImmutableSet<ID> request;
26 +
27 + /**
28 + * Creates a reply to anti-entropy message.
29 + *
30 + * @param sender sender of this message
31 + * @param suggestion collection of more recent values, sender had
32 + * @param request Collection of identifiers
33 + */
34 + public AntiEntropyReply(NodeId sender,
35 + Map<ID, V> suggestion,
36 + Set<ID> request) {
37 + super(AE_REPLY);
38 + this.sender = sender;
39 + this.suggestion = ImmutableMap.copyOf(suggestion);
40 + this.request = ImmutableSet.copyOf(request);
41 + }
42 +
43 + public NodeId sender() {
44 + return sender;
45 + }
46 +
47 + /**
48 + * Returns collection of values, which the recipient of this reply is likely
49 + * to be missing or has outdated version.
50 + *
51 + * @return
52 + */
53 + public ImmutableMap<ID, V> suggestion() {
54 + return suggestion;
55 + }
56 +
57 + /**
58 + * Returns collection of identifier to request.
59 + *
60 + * @return collection of identifier to request
61 + */
62 + public ImmutableSet<ID> request() {
63 + return request;
64 + }
65 +
66 + /**
67 + * Checks if reply contains any suggestion or request.
68 + *
69 + * @return true if nothing is suggested and requested
70 + */
71 + public boolean isEmpty() {
72 + return suggestion.isEmpty() && request.isEmpty();
73 + }
74 +
75 + // Default constructor for serializer
76 + protected AntiEntropyReply() {
77 + super(AE_REPLY);
78 + this.sender = null;
79 + this.suggestion = null;
80 + this.request = null;
81 + }
82 +}
...@@ -15,6 +15,12 @@ public enum MessageSubject { ...@@ -15,6 +15,12 @@ public enum MessageSubject {
15 LEAVING_MEMBER, 15 LEAVING_MEMBER,
16 16
17 /** Signifies a heart-beat message. */ 17 /** Signifies a heart-beat message. */
18 - ECHO 18 + ECHO,
19 +
20 + /** Anti-Entropy advertisement message. */
21 + AE_ADVERTISEMENT,
22 +
23 + /** Anti-Entropy reply message. */
24 + AE_REPLY,
19 25
20 } 26 }
......
1 /** 1 /**
2 * Cluster messaging APIs for the use by the various distributed stores. 2 * Cluster messaging APIs for the use by the various distributed stores.
3 */ 3 */
4 -package org.onlab.onos.store.cluster.messaging;
...\ No newline at end of file ...\ No newline at end of file
4 +package org.onlab.onos.store.cluster.messaging;
......
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import java.util.Collection;
4 +import java.util.HashMap;
5 +import java.util.Map;
6 +
7 +import org.onlab.onos.cluster.NodeId;
8 +import org.onlab.onos.net.Device;
9 +import org.onlab.onos.net.DeviceId;
10 +import org.onlab.onos.store.Timestamp;
11 +import org.onlab.onos.store.cluster.messaging.AntiEntropyAdvertisement;
12 +
13 +// TODO DeviceID needs to be changed to something like (ProviderID, DeviceID)
14 +// TODO: Handle Port as part of these messages, or separate messages for Ports?
15 +
16 +public class DeviceAntiEntropyAdvertisement
17 + extends AntiEntropyAdvertisement<DeviceId> {
18 +
19 +
20 + public DeviceAntiEntropyAdvertisement(NodeId sender,
21 + Map<DeviceId, Timestamp> advertisement) {
22 + super(sender, advertisement);
23 + }
24 +
25 + // May need to add ProviderID, etc.
26 + public static DeviceAntiEntropyAdvertisement create(
27 + NodeId self,
28 + Collection<VersionedValue<Device>> localValues) {
29 +
30 + Map<DeviceId, Timestamp> ads = new HashMap<>(localValues.size());
31 + for (VersionedValue<Device> e : localValues) {
32 + ads.put(e.entity().id(), e.timestamp());
33 + }
34 + return new DeviceAntiEntropyAdvertisement(self, ads);
35 + }
36 +
37 + // For serializer
38 + protected DeviceAntiEntropyAdvertisement() {}
39 +}
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import java.util.Collection;
4 +import java.util.HashMap;
5 +import java.util.HashSet;
6 +import java.util.Map;
7 +import java.util.Set;
8 +
9 +import org.onlab.onos.cluster.NodeId;
10 +import org.onlab.onos.net.Device;
11 +import org.onlab.onos.net.DeviceId;
12 +import org.onlab.onos.store.Timestamp;
13 +import org.onlab.onos.store.cluster.messaging.AntiEntropyReply;
14 +
15 +import com.google.common.collect.ImmutableMap;
16 +import com.google.common.collect.ImmutableSet;
17 +
18 +public class DeviceAntiEntropyReply
19 + extends AntiEntropyReply<DeviceId, VersionedValue<Device>> {
20 +
21 +
22 + public DeviceAntiEntropyReply(NodeId sender,
23 + Map<DeviceId, VersionedValue<Device>> suggestion,
24 + Set<DeviceId> request) {
25 + super(sender, suggestion, request);
26 + }
27 +
28 + /**
29 + * Creates a reply to Anti-Entropy advertisement.
30 + *
31 + * @param advertisement to respond to
32 + * @param self node identifier representing local node
33 + * @param localValues local values held on this node
34 + * @return reply message
35 + */
36 + public static DeviceAntiEntropyReply reply(
37 + DeviceAntiEntropyAdvertisement advertisement,
38 + NodeId self,
39 + Collection<VersionedValue<Device>> localValues
40 + ) {
41 +
42 + ImmutableMap<DeviceId, Timestamp> ads = advertisement.advertisement();
43 +
44 + ImmutableMap.Builder<DeviceId, VersionedValue<Device>>
45 + sug = ImmutableMap.builder();
46 +
47 + Set<DeviceId> req = new HashSet<>(ads.keySet());
48 +
49 + for (VersionedValue<Device> e : localValues) {
50 + final DeviceId id = e.entity().id();
51 + final Timestamp local = e.timestamp();
52 + final Timestamp theirs = ads.get(id);
53 + if (theirs == null) {
54 + // they don't have it, suggest
55 + sug.put(id, e);
56 + // don't need theirs
57 + req.remove(id);
58 + } else if (local.compareTo(theirs) < 0) {
59 + // they got older one, suggest
60 + sug.put(id, e);
61 + // don't need theirs
62 + req.remove(id);
63 + } else if (local.equals(theirs)) {
64 + // same, don't need theirs
65 + req.remove(id);
66 + }
67 + }
68 +
69 + return new DeviceAntiEntropyReply(self, sug.build(), req);
70 + }
71 +
72 + /**
73 + * Creates a reply to request for values held locally.
74 + *
75 + * @param requests message containing the request
76 + * @param self node identifier representing local node
77 + * @param localValues local valeds held on this node
78 + * @return reply message
79 + */
80 + public static DeviceAntiEntropyReply reply(
81 + DeviceAntiEntropyReply requests,
82 + NodeId self,
83 + Map<DeviceId, VersionedValue<Device>> localValues
84 + ) {
85 +
86 + Set<DeviceId> reqs = requests.request();
87 +
88 + Map<DeviceId, VersionedValue<Device>> requested = new HashMap<>(reqs.size());
89 + for (DeviceId id : reqs) {
90 + final VersionedValue<Device> value = localValues.get(id);
91 + if (value != null) {
92 + requested.put(id, value);
93 + }
94 + }
95 +
96 + Set<DeviceId> empty = ImmutableSet.of();
97 + return new DeviceAntiEntropyReply(self, requested, empty);
98 + }
99 +
100 + // For serializer
101 + protected DeviceAntiEntropyReply() {}
102 +}
...@@ -40,6 +40,7 @@ import java.util.Map; ...@@ -40,6 +40,7 @@ import java.util.Map;
40 import java.util.Objects; 40 import java.util.Objects;
41 import java.util.Set; 41 import java.util.Set;
42 import java.util.concurrent.ConcurrentHashMap; 42 import java.util.concurrent.ConcurrentHashMap;
43 +import java.util.concurrent.ConcurrentMap;
43 44
44 import static com.google.common.base.Preconditions.checkArgument; 45 import static com.google.common.base.Preconditions.checkArgument;
45 import static org.onlab.onos.net.device.DeviceEvent.Type.*; 46 import static org.onlab.onos.net.device.DeviceEvent.Type.*;
...@@ -59,8 +60,8 @@ public class OnosDistributedDeviceStore ...@@ -59,8 +60,8 @@ public class OnosDistributedDeviceStore
59 60
60 public static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; 61 public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
61 62
62 - private ConcurrentHashMap<DeviceId, VersionedValue<Device>> devices; 63 + private ConcurrentMap<DeviceId, VersionedValue<Device>> devices;
63 - private ConcurrentHashMap<DeviceId, Map<PortNumber, VersionedValue<Port>>> devicePorts; 64 + private ConcurrentMap<DeviceId, Map<PortNumber, VersionedValue<Port>>> devicePorts;
64 65
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected ClockService clockService; 67 protected ClockService clockService;
...@@ -191,7 +192,7 @@ public class OnosDistributedDeviceStore ...@@ -191,7 +192,7 @@ public class OnosDistributedDeviceStore
191 } 192 }
192 193
193 @Override 194 @Override
194 - public List<DeviceEvent> updatePorts(DeviceId deviceId, 195 + public List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
195 List<PortDescription> portDescriptions) { 196 List<PortDescription> portDescriptions) {
196 List<DeviceEvent> events = new ArrayList<>(); 197 List<DeviceEvent> events = new ArrayList<>();
197 synchronized (this) { 198 synchronized (this) {
...@@ -295,7 +296,7 @@ public class OnosDistributedDeviceStore ...@@ -295,7 +296,7 @@ public class OnosDistributedDeviceStore
295 } 296 }
296 297
297 @Override 298 @Override
298 - public DeviceEvent updatePortStatus(DeviceId deviceId, 299 + public DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
299 PortDescription portDescription) { 300 PortDescription portDescription) {
300 VersionedValue<Device> device = devices.get(deviceId); 301 VersionedValue<Device> device = devices.get(deviceId);
301 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); 302 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
......
1 package org.onlab.onos.store.device.impl; 1 package org.onlab.onos.store.device.impl;
2 2
3 +import java.util.Objects;
4 +
3 import org.onlab.onos.store.Timestamp; 5 import org.onlab.onos.store.Timestamp;
4 6
5 /** 7 /**
...@@ -42,4 +44,35 @@ public class VersionedValue<T> { ...@@ -42,4 +44,35 @@ public class VersionedValue<T> {
42 public Timestamp timestamp() { 44 public Timestamp timestamp() {
43 return timestamp; 45 return timestamp;
44 } 46 }
47 +
48 +
49 + @Override
50 + public int hashCode() {
51 + return Objects.hash(entity, timestamp, isUp);
52 + }
53 +
54 + @Override
55 + public boolean equals(Object obj) {
56 + if (this == obj) {
57 + return true;
58 + }
59 + if (obj == null) {
60 + return false;
61 + }
62 + if (getClass() != obj.getClass()) {
63 + return false;
64 + }
65 + @SuppressWarnings("unchecked")
66 + VersionedValue<T> that = (VersionedValue<T>) obj;
67 + return Objects.equals(this.entity, that.entity) &&
68 + Objects.equals(this.timestamp, that.timestamp) &&
69 + Objects.equals(this.isUp, that.isUp);
70 + }
71 +
72 + // Default constructor for serializer
73 + protected VersionedValue() {
74 + this.entity = null;
75 + this.isUp = false;
76 + this.timestamp = null;
77 + }
45 } 78 }
......
...@@ -2,6 +2,7 @@ package org.onlab.onos.store.cluster.impl; ...@@ -2,6 +2,7 @@ package org.onlab.onos.store.cluster.impl;
2 2
3 import org.junit.After; 3 import org.junit.After;
4 import org.junit.Before; 4 import org.junit.Before;
5 +import org.junit.Ignore;
5 import org.junit.Test; 6 import org.junit.Test;
6 import org.onlab.onos.cluster.DefaultControllerNode; 7 import org.onlab.onos.cluster.DefaultControllerNode;
7 import org.onlab.onos.cluster.NodeId; 8 import org.onlab.onos.cluster.NodeId;
...@@ -58,6 +59,7 @@ public class ClusterCommunicationManagerTest { ...@@ -58,6 +59,7 @@ public class ClusterCommunicationManagerTest {
58 ccm2.deactivate(); 59 ccm2.deactivate();
59 } 60 }
60 61
62 + @Ignore("FIXME: failing randomly?")
61 @Test 63 @Test
62 public void connect() throws Exception { 64 public void connect() throws Exception {
63 cnd1.latch = new CountDownLatch(1); 65 cnd1.latch = new CountDownLatch(1);
......
...@@ -123,6 +123,12 @@ implements MastershipStore { ...@@ -123,6 +123,12 @@ implements MastershipStore {
123 return null; 123 return null;
124 } 124 }
125 125
126 + @Override
127 + public MastershipEvent unsetMaster(NodeId nodeId, DeviceId deviceId) {
128 + // TODO Auto-generated method stub
129 + return null;
130 + }
131 +
126 private class RemoteMasterShipEventHandler extends RemoteCacheEventHandler<DeviceId, NodeId> { 132 private class RemoteMasterShipEventHandler extends RemoteCacheEventHandler<DeviceId, NodeId> {
127 public RemoteMasterShipEventHandler(LoadingCache<DeviceId, Optional<NodeId>> cache) { 133 public RemoteMasterShipEventHandler(LoadingCache<DeviceId, Optional<NodeId>> cache) {
128 super(cache); 134 super(cache);
......
...@@ -221,7 +221,7 @@ public class DistributedDeviceStore ...@@ -221,7 +221,7 @@ public class DistributedDeviceStore
221 } 221 }
222 222
223 @Override 223 @Override
224 - public List<DeviceEvent> updatePorts(DeviceId deviceId, 224 + public List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
225 List<PortDescription> portDescriptions) { 225 List<PortDescription> portDescriptions) {
226 List<DeviceEvent> events = new ArrayList<>(); 226 List<DeviceEvent> events = new ArrayList<>();
227 synchronized (this) { 227 synchronized (this) {
...@@ -319,7 +319,7 @@ public class DistributedDeviceStore ...@@ -319,7 +319,7 @@ public class DistributedDeviceStore
319 } 319 }
320 320
321 @Override 321 @Override
322 - public DeviceEvent updatePortStatus(DeviceId deviceId, 322 + public DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
323 PortDescription portDescription) { 323 PortDescription portDescription) {
324 synchronized (this) { 324 synchronized (this) {
325 Device device = devices.getUnchecked(deviceId).orNull(); 325 Device device = devices.getUnchecked(deviceId).orNull();
......
...@@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableSet; ...@@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableSet;
28 import com.google.common.collect.Multimap; 28 import com.google.common.collect.Multimap;
29 29
30 /** 30 /**
31 - * Manages inventory of flow rules using trivial in-memory implementation. 31 + * TEMPORARY: Manages inventory of flow rules using distributed store implementation.
32 */ 32 */
33 //FIXME: I LIE I AM NOT DISTRIBUTED 33 //FIXME: I LIE I AM NOT DISTRIBUTED
34 @Component(immediate = true) 34 @Component(immediate = true)
......
1 +/**
2 + * Implementation of flow store using Hazelcast distributed structures.
3 + */
4 +package org.onlab.onos.store.flow.impl;
...@@ -39,8 +39,8 @@ import com.google.common.collect.Multimap; ...@@ -39,8 +39,8 @@ import com.google.common.collect.Multimap;
39 import com.google.common.collect.Sets; 39 import com.google.common.collect.Sets;
40 40
41 /** 41 /**
42 - * Manages inventory of end-station hosts using trivial in-memory 42 + * TEMPORARY: Manages inventory of end-station hosts using distributed
43 - * implementation. 43 + * structures implementation.
44 */ 44 */
45 //FIXME: I LIE I AM NOT DISTRIBUTED 45 //FIXME: I LIE I AM NOT DISTRIBUTED
46 @Component(immediate = true) 46 @Component(immediate = true)
......
1 +/**
2 + * Implementation of host store using Hazelcast distributed structures.
3 + */
4 +package org.onlab.onos.store.host.impl;
...@@ -28,7 +28,7 @@ import org.onlab.onos.store.AbstractStore; ...@@ -28,7 +28,7 @@ import org.onlab.onos.store.AbstractStore;
28 import org.slf4j.Logger; 28 import org.slf4j.Logger;
29 29
30 /** 30 /**
31 - * Manages inventory of topology snapshots using trivial in-memory 31 + * TEMPORARY: Manages inventory of topology snapshots using distributed
32 * structures implementation. 32 * structures implementation.
33 */ 33 */
34 //FIXME: I LIE I AM NOT DISTRIBUTED 34 //FIXME: I LIE I AM NOT DISTRIBUTED
......
1 +/**
2 + * Implementation of topology store using Hazelcast distributed structures.
3 + */
4 +package org.onlab.onos.store.topology.impl;
...@@ -201,7 +201,7 @@ public class DistributedDeviceStoreTest { ...@@ -201,7 +201,7 @@ public class DistributedDeviceStoreTest {
201 new DefaultPortDescription(P2, true) 201 new DefaultPortDescription(P2, true)
202 ); 202 );
203 203
204 - List<DeviceEvent> events = deviceStore.updatePorts(DID1, pds); 204 + List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
205 205
206 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 206 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
207 for (DeviceEvent event : events) { 207 for (DeviceEvent event : events) {
...@@ -220,7 +220,7 @@ public class DistributedDeviceStoreTest { ...@@ -220,7 +220,7 @@ public class DistributedDeviceStoreTest {
220 new DefaultPortDescription(P3, true) 220 new DefaultPortDescription(P3, true)
221 ); 221 );
222 222
223 - events = deviceStore.updatePorts(DID1, pds2); 223 + events = deviceStore.updatePorts(PID, DID1, pds2);
224 assertFalse("event should be triggered", events.isEmpty()); 224 assertFalse("event should be triggered", events.isEmpty());
225 for (DeviceEvent event : events) { 225 for (DeviceEvent event : events) {
226 PortNumber num = event.port().number(); 226 PortNumber num = event.port().number();
...@@ -243,7 +243,7 @@ public class DistributedDeviceStoreTest { ...@@ -243,7 +243,7 @@ public class DistributedDeviceStoreTest {
243 new DefaultPortDescription(P1, false), 243 new DefaultPortDescription(P1, false),
244 new DefaultPortDescription(P2, true) 244 new DefaultPortDescription(P2, true)
245 ); 245 );
246 - events = deviceStore.updatePorts(DID1, pds3); 246 + events = deviceStore.updatePorts(PID, DID1, pds3);
247 assertFalse("event should be triggered", events.isEmpty()); 247 assertFalse("event should be triggered", events.isEmpty());
248 for (DeviceEvent event : events) { 248 for (DeviceEvent event : events) {
249 PortNumber num = event.port().number(); 249 PortNumber num = event.port().number();
...@@ -268,9 +268,9 @@ public class DistributedDeviceStoreTest { ...@@ -268,9 +268,9 @@ public class DistributedDeviceStoreTest {
268 List<PortDescription> pds = Arrays.<PortDescription>asList( 268 List<PortDescription> pds = Arrays.<PortDescription>asList(
269 new DefaultPortDescription(P1, true) 269 new DefaultPortDescription(P1, true)
270 ); 270 );
271 - deviceStore.updatePorts(DID1, pds); 271 + deviceStore.updatePorts(PID, DID1, pds);
272 272
273 - DeviceEvent event = deviceStore.updatePortStatus(DID1, 273 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
274 new DefaultPortDescription(P1, false)); 274 new DefaultPortDescription(P1, false));
275 assertEquals(PORT_UPDATED, event.type()); 275 assertEquals(PORT_UPDATED, event.type());
276 assertDevice(DID1, SW1, event.subject()); 276 assertDevice(DID1, SW1, event.subject());
...@@ -286,7 +286,7 @@ public class DistributedDeviceStoreTest { ...@@ -286,7 +286,7 @@ public class DistributedDeviceStoreTest {
286 new DefaultPortDescription(P1, true), 286 new DefaultPortDescription(P1, true),
287 new DefaultPortDescription(P2, true) 287 new DefaultPortDescription(P2, true)
288 ); 288 );
289 - deviceStore.updatePorts(DID1, pds); 289 + deviceStore.updatePorts(PID, DID1, pds);
290 290
291 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 291 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
292 List<Port> ports = deviceStore.getPorts(DID1); 292 List<Port> ports = deviceStore.getPorts(DID1);
...@@ -309,7 +309,7 @@ public class DistributedDeviceStoreTest { ...@@ -309,7 +309,7 @@ public class DistributedDeviceStoreTest {
309 new DefaultPortDescription(P1, true), 309 new DefaultPortDescription(P1, true),
310 new DefaultPortDescription(P2, false) 310 new DefaultPortDescription(P2, false)
311 ); 311 );
312 - deviceStore.updatePorts(DID1, pds); 312 + deviceStore.updatePorts(PID, DID1, pds);
313 313
314 Port port1 = deviceStore.getPort(DID1, P1); 314 Port port1 = deviceStore.getPort(DID1, P1);
315 assertEquals(P1, port1.number()); 315 assertEquals(P1, port1.number());
......
1 +package org.onlab.onos.store.serializers;
2 +
3 +import java.util.Collections;
4 +import java.util.HashMap;
5 +import java.util.Map;
6 +
7 +import org.onlab.util.KryoPool.FamilySerializer;
8 +
9 +import com.esotericsoftware.kryo.Kryo;
10 +import com.esotericsoftware.kryo.io.Input;
11 +import com.esotericsoftware.kryo.io.Output;
12 +import com.esotericsoftware.kryo.serializers.MapSerializer;
13 +import com.google.common.collect.ImmutableMap;
14 +
15 +/**
16 +* Kryo Serializer for {@link ImmutableMap}.
17 +*/
18 +public class ImmutableMapSerializer extends FamilySerializer<ImmutableMap<?, ?>> {
19 +
20 + private final MapSerializer mapSerializer = new MapSerializer();
21 +
22 + public ImmutableMapSerializer() {
23 + // non-null, immutable
24 + super(false, true);
25 + }
26 +
27 + @Override
28 + public void write(Kryo kryo, Output output, ImmutableMap<?, ?> object) {
29 + // wrapping with unmodifiableMap proxy
30 + // to avoid Kryo from writing only the reference marker of this instance,
31 + // which will be embedded right before this method call.
32 + kryo.writeObject(output, Collections.unmodifiableMap(object), mapSerializer);
33 + }
34 +
35 + @Override
36 + public ImmutableMap<?, ?> read(Kryo kryo, Input input,
37 + Class<ImmutableMap<?, ?>> type) {
38 + Map<?, ?> map = kryo.readObject(input, HashMap.class, mapSerializer);
39 + return ImmutableMap.copyOf(map);
40 + }
41 +
42 + @Override
43 + public void registerFamilies(Kryo kryo) {
44 + kryo.register(ImmutableMap.of().getClass(), this);
45 + kryo.register(ImmutableMap.of(1, 2).getClass(), this);
46 + kryo.register(ImmutableMap.of(1, 2, 3, 4).getClass(), this);
47 + // TODO register required ImmutableMap variants
48 + }
49 +}
1 +package org.onlab.onos.store.serializers;
2 +
3 +import java.util.ArrayList;
4 +import java.util.List;
5 +
6 +import org.onlab.util.KryoPool.FamilySerializer;
7 +
8 +import com.esotericsoftware.kryo.Kryo;
9 +import com.esotericsoftware.kryo.io.Input;
10 +import com.esotericsoftware.kryo.io.Output;
11 +import com.esotericsoftware.kryo.serializers.CollectionSerializer;
12 +import com.google.common.collect.ImmutableSet;
13 +
14 +/**
15 +* Kryo Serializer for {@link ImmutableSet}.
16 +*/
17 +public class ImmutableSetSerializer extends FamilySerializer<ImmutableSet<?>> {
18 +
19 + private final CollectionSerializer serializer = new CollectionSerializer();
20 +
21 + public ImmutableSetSerializer() {
22 + // non-null, immutable
23 + super(false, true);
24 + }
25 +
26 + @Override
27 + public void write(Kryo kryo, Output output, ImmutableSet<?> object) {
28 + kryo.writeObject(output, object.asList(), serializer);
29 + }
30 +
31 + @Override
32 + public ImmutableSet<?> read(Kryo kryo, Input input,
33 + Class<ImmutableSet<?>> type) {
34 + List<?> elms = kryo.readObject(input, ArrayList.class, serializer);
35 + return ImmutableSet.copyOf(elms);
36 + }
37 +
38 + @Override
39 + public void registerFamilies(Kryo kryo) {
40 + kryo.register(ImmutableSet.of().getClass(), this);
41 + kryo.register(ImmutableSet.of(1).getClass(), this);
42 + kryo.register(ImmutableSet.of(1, 2).getClass(), this);
43 + // TODO register required ImmutableSet variants
44 + }
45 +}
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 import java.net.URI; 3 import java.net.URI;
4 +import java.nio.ByteBuffer;
4 import java.util.ArrayList; 5 import java.util.ArrayList;
5 import java.util.HashMap; 6 import java.util.HashMap;
6 7
...@@ -100,4 +101,14 @@ public class KryoSerializationManager implements KryoSerializationService { ...@@ -100,4 +101,14 @@ public class KryoSerializationManager implements KryoSerializationService {
100 return serializerPool.deserialize(bytes); 101 return serializerPool.deserialize(bytes);
101 } 102 }
102 103
104 + @Override
105 + public void serialize(Object obj, ByteBuffer buffer) {
106 + serializerPool.serialize(obj, buffer);
107 + }
108 +
109 + @Override
110 + public <T> T deserialize(ByteBuffer buffer) {
111 + return serializerPool.deserialize(buffer);
112 + }
113 +
103 } 114 }
......
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 +import java.nio.ByteBuffer;
4 +
3 // TODO: To be replaced with SerializationService from IOLoop activity 5 // TODO: To be replaced with SerializationService from IOLoop activity
4 /** 6 /**
5 * Service to serialize Objects into byte array. 7 * Service to serialize Objects into byte array.
...@@ -16,6 +18,15 @@ public interface KryoSerializationService { ...@@ -16,6 +18,15 @@ public interface KryoSerializationService {
16 public byte[] serialize(final Object obj); 18 public byte[] serialize(final Object obj);
17 19
18 /** 20 /**
21 + * Serializes the specified object into bytes using one of the
22 + * pre-registered serializers.
23 + *
24 + * @param obj object to be serialized
25 + * @param buffer to write serialized bytes
26 + */
27 + public void serialize(final Object obj, ByteBuffer buffer);
28 +
29 + /**
19 * Deserializes the specified bytes into an object using one of the 30 * Deserializes the specified bytes into an object using one of the
20 * pre-registered serializers. 31 * pre-registered serializers.
21 * 32 *
...@@ -24,4 +35,12 @@ public interface KryoSerializationService { ...@@ -24,4 +35,12 @@ public interface KryoSerializationService {
24 */ 35 */
25 public <T> T deserialize(final byte[] bytes); 36 public <T> T deserialize(final byte[] bytes);
26 37
38 + /**
39 + * Deserializes the specified bytes into an object using one of the
40 + * pre-registered serializers.
41 + *
42 + * @param buffer bytes to be deserialized
43 + * @return deserialized object
44 + */
45 + public <T> T deserialize(final ByteBuffer buffer);
27 } 46 }
......
1 +package org.onlab.onos.store.serializers;
2 +
3 +import org.onlab.onos.net.MastershipRole;
4 +
5 +import com.esotericsoftware.kryo.Kryo;
6 +import com.esotericsoftware.kryo.Serializer;
7 +import com.esotericsoftware.kryo.io.Input;
8 +import com.esotericsoftware.kryo.io.Output;
9 +
10 +/**
11 + * Kryo Serializer for {@link org.onlab.onos.net.MastershipRole}.
12 + */
13 +public class MastershipRoleSerializer extends Serializer<MastershipRole> {
14 +
15 + @Override
16 + public MastershipRole read(Kryo kryo, Input input, Class<MastershipRole> type) {
17 + final String role = kryo.readObject(input, String.class);
18 + return MastershipRole.valueOf(role);
19 + }
20 +
21 + @Override
22 + public void write(Kryo kryo, Output output, MastershipRole object) {
23 + kryo.writeObject(output, object.toString());
24 + }
25 +
26 +}
1 +package org.onlab.onos.store.serializers;
2 +
3 +import org.onlab.onos.cluster.MastershipTerm;
4 +import org.onlab.onos.cluster.NodeId;
5 +
6 +import com.esotericsoftware.kryo.Kryo;
7 +import com.esotericsoftware.kryo.Serializer;
8 +import com.esotericsoftware.kryo.io.Input;
9 +import com.esotericsoftware.kryo.io.Output;
10 +
11 +/**
12 + * Kryo Serializer for {@link org.onlab.onos.cluster.MastershipTerm}.
13 + */
14 +public class MastershipTermSerializer extends Serializer<MastershipTerm> {
15 +
16 + @Override
17 + public MastershipTerm read(Kryo kryo, Input input, Class<MastershipTerm> type) {
18 + final NodeId node = new NodeId(kryo.readObject(input, String.class));
19 + final int term = input.readInt();
20 + return MastershipTerm.of(node, term);
21 + }
22 +
23 + @Override
24 + public void write(Kryo kryo, Output output, MastershipTerm object) {
25 + output.writeString(object.master().toString());
26 + output.writeInt(object.termNumber());
27 + }
28 +
29 +}
1 +package org.onlab.onos.store.serializers;
2 +
3 +import static org.onlab.onos.net.DeviceId.deviceId;
4 +import static org.onlab.onos.net.PortNumber.portNumber;
5 +
6 +import java.net.URI;
7 +import java.nio.ByteBuffer;
8 +import java.util.ArrayList;
9 +import java.util.HashMap;
10 +
11 +import org.junit.After;
12 +import org.junit.Before;
13 +import org.junit.BeforeClass;
14 +import org.junit.Test;
15 +import org.onlab.onos.cluster.MastershipTerm;
16 +import org.onlab.onos.cluster.NodeId;
17 +import org.onlab.onos.net.ConnectPoint;
18 +import org.onlab.onos.net.DefaultDevice;
19 +import org.onlab.onos.net.DefaultLink;
20 +import org.onlab.onos.net.DefaultPort;
21 +import org.onlab.onos.net.Device;
22 +import org.onlab.onos.net.DeviceId;
23 +import org.onlab.onos.net.Link;
24 +import org.onlab.onos.net.LinkKey;
25 +import org.onlab.onos.net.MastershipRole;
26 +import org.onlab.onos.net.PortNumber;
27 +import org.onlab.onos.net.provider.ProviderId;
28 +import org.onlab.packet.IpPrefix;
29 +import org.onlab.util.KryoPool;
30 +
31 +import com.google.common.collect.ImmutableMap;
32 +import com.google.common.collect.ImmutableSet;
33 +import com.google.common.testing.EqualsTester;
34 +
35 +import de.javakaffee.kryoserializers.URISerializer;
36 +
37 +public class KryoSerializerTests {
38 + private static final ProviderId PID = new ProviderId("of", "foo");
39 + private static final DeviceId DID1 = deviceId("of:foo");
40 + private static final DeviceId DID2 = deviceId("of:bar");
41 + private static final PortNumber P1 = portNumber(1);
42 + private static final PortNumber P2 = portNumber(2);
43 + private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
44 + private static final ConnectPoint CP2 = new ConnectPoint(DID2, P2);
45 + private static final String MFR = "whitebox";
46 + private static final String HW = "1.1.x";
47 + private static final String SW1 = "3.8.1";
48 + private static final String SW2 = "3.9.5";
49 + private static final String SN = "43311-12345";
50 + private static final Device DEV1 = new DefaultDevice(PID, DID1, Device.Type.SWITCH, MFR, HW, SW1, SN);
51 +
52 + private static KryoPool kryos;
53 +
54 + @BeforeClass
55 + public static void setUpBeforeClass() throws Exception {
56 + kryos = KryoPool.newBuilder()
57 + .register(
58 + ArrayList.class,
59 + HashMap.class
60 + )
61 + .register(
62 + Device.Type.class,
63 + Link.Type.class
64 +
65 +// ControllerNode.State.class,
66 +// DefaultControllerNode.class,
67 +// MastershipRole.class,
68 +// Port.class,
69 +// Element.class,
70 + )
71 + .register(ConnectPoint.class, new ConnectPointSerializer())
72 + .register(DefaultLink.class, new DefaultLinkSerializer())
73 + .register(DefaultPort.class, new DefaultPortSerializer())
74 + .register(DeviceId.class, new DeviceIdSerializer())
75 + .register(ImmutableMap.class, new ImmutableMapSerializer())
76 + .register(ImmutableSet.class, new ImmutableSetSerializer())
77 + .register(IpPrefix.class, new IpPrefixSerializer())
78 + .register(LinkKey.class, new LinkKeySerializer())
79 + .register(NodeId.class, new NodeIdSerializer())
80 + .register(PortNumber.class, new PortNumberSerializer())
81 + .register(ProviderId.class, new ProviderIdSerializer())
82 +
83 + .register(DefaultDevice.class)
84 +
85 + .register(URI.class, new URISerializer())
86 +
87 + .register(MastershipRole.class, new MastershipRoleSerializer())
88 + .register(MastershipTerm.class, new MastershipTermSerializer())
89 + .build();
90 + }
91 +
92 + @Before
93 + public void setUp() throws Exception {
94 + }
95 +
96 + @After
97 + public void tearDown() throws Exception {
98 + // removing Kryo instance to use fresh Kryo on each tests
99 + kryos.getKryo();
100 + }
101 +
102 + private static <T> void testSerialized(T original) {
103 + ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
104 + kryos.serialize(original, buffer);
105 + buffer.flip();
106 + T copy = kryos.deserialize(buffer);
107 +
108 + new EqualsTester()
109 + .addEqualityGroup(original, copy)
110 + .testEquals();
111 + }
112 +
113 +
114 + @Test
115 + public final void test() {
116 + testSerialized(new ConnectPoint(DID1, P1));
117 + testSerialized(new DefaultLink(PID, CP1, CP2, Link.Type.DIRECT));
118 + testSerialized(new DefaultPort(DEV1, P1, true));
119 + testSerialized(DID1);
120 + testSerialized(ImmutableMap.of(DID1, DEV1, DID2, DEV1));
121 + testSerialized(ImmutableMap.of(DID1, DEV1));
122 + testSerialized(ImmutableMap.of());
123 + testSerialized(ImmutableSet.of(DID1, DID2));
124 + testSerialized(ImmutableSet.of(DID1));
125 + testSerialized(ImmutableSet.of());
126 + testSerialized(IpPrefix.valueOf("192.168.0.1/24"));
127 + testSerialized(new LinkKey(CP1, CP2));
128 + testSerialized(new NodeId("SomeNodeIdentifier"));
129 + testSerialized(P1);
130 + testSerialized(PID);
131 + }
132 +
133 +}
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
25 <groupId>org.apache.felix</groupId> 25 <groupId>org.apache.felix</groupId>
26 <artifactId>org.apache.felix.scr.annotations</artifactId> 26 <artifactId>org.apache.felix.scr.annotations</artifactId>
27 </dependency> 27 </dependency>
28 + <dependency>
29 + <groupId>org.apache.commons</groupId>
30 + <artifactId>commons-lang3</artifactId>
31 + </dependency>
28 </dependencies> 32 </dependencies>
29 33
30 <build> 34 <build>
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import com.google.common.collect.ImmutableMap; 3 import com.google.common.collect.ImmutableMap;
4 import com.google.common.collect.ImmutableSet; 4 import com.google.common.collect.ImmutableSet;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.onlab.graph.AdjacencyListsGraph; 3 import org.onlab.graph.AdjacencyListsGraph;
4 import org.onlab.onos.net.topology.TopologyEdge; 4 import org.onlab.onos.net.topology.TopologyEdge;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.apache.felix.scr.annotations.Component; 3 import org.apache.felix.scr.annotations.Component;
4 import org.apache.felix.scr.annotations.Service; 4 import org.apache.felix.scr.annotations.Service;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.onlab.onos.net.DeviceId; 3 import org.onlab.onos.net.DeviceId;
4 4
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import com.google.common.collect.ImmutableSet; 3 import com.google.common.collect.ImmutableSet;
4 import org.apache.felix.scr.annotations.Activate; 4 import org.apache.felix.scr.annotations.Activate;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED; 3 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
4 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; 4 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED; 3 import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
4 import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED; 4 import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import com.google.common.collect.HashMultimap; 3 import com.google.common.collect.HashMultimap;
4 import com.google.common.collect.ImmutableSet; 4 import com.google.common.collect.ImmutableSet;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
...@@ -7,8 +7,6 @@ import java.util.HashMap; ...@@ -7,8 +7,6 @@ import java.util.HashMap;
7 import java.util.HashSet; 7 import java.util.HashSet;
8 import java.util.Map; 8 import java.util.Map;
9 import java.util.Set; 9 import java.util.Set;
10 -import java.util.concurrent.ConcurrentHashMap;
11 -import java.util.concurrent.ConcurrentMap;
12 import java.util.concurrent.atomic.AtomicInteger; 10 import java.util.concurrent.atomic.AtomicInteger;
13 11
14 import org.apache.felix.scr.annotations.Activate; 12 import org.apache.felix.scr.annotations.Activate;
...@@ -48,8 +46,10 @@ public class SimpleMastershipStore ...@@ -48,8 +46,10 @@ public class SimpleMastershipStore
48 new DefaultControllerNode(new NodeId("local"), LOCALHOST); 46 new DefaultControllerNode(new NodeId("local"), LOCALHOST);
49 47
50 //devices mapped to their masters, to emulate multiple nodes 48 //devices mapped to their masters, to emulate multiple nodes
51 - protected final ConcurrentMap<DeviceId, NodeId> masterMap = 49 + protected final Map<DeviceId, NodeId> masterMap = new HashMap<>();
52 - new ConcurrentHashMap<>(); 50 + //emulate backups with pile of nodes
51 + protected final Set<NodeId> backups = new HashSet<>();
52 + //terms
53 protected final Map<DeviceId, AtomicInteger> termMap = new HashMap<>(); 53 protected final Map<DeviceId, AtomicInteger> termMap = new HashMap<>();
54 54
55 @Activate 55 @Activate
...@@ -64,25 +64,29 @@ public class SimpleMastershipStore ...@@ -64,25 +64,29 @@ public class SimpleMastershipStore
64 64
65 @Override 65 @Override
66 public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) { 66 public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
67 - 67 + MastershipRole role = getRole(nodeId, deviceId);
68 - NodeId node = masterMap.get(deviceId); 68 +
69 - if (node == null) { 69 + synchronized (this) {
70 - synchronized (this) { 70 + switch (role) {
71 - masterMap.put(deviceId, nodeId); 71 + case MASTER:
72 - termMap.put(deviceId, new AtomicInteger()); 72 + return null;
73 + case STANDBY:
74 + masterMap.put(deviceId, nodeId);
75 + termMap.get(deviceId).incrementAndGet();
76 + backups.add(nodeId);
77 + break;
78 + case NONE:
79 + masterMap.put(deviceId, nodeId);
80 + termMap.put(deviceId, new AtomicInteger());
81 + backups.add(nodeId);
82 + break;
83 + default:
84 + log.warn("unknown Mastership Role {}", role);
85 + return null;
73 } 86 }
74 - return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
75 } 87 }
76 88
77 - if (node.equals(nodeId)) { 89 + return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
78 - return null;
79 - } else {
80 - synchronized (this) {
81 - masterMap.put(deviceId, nodeId);
82 - termMap.get(deviceId).incrementAndGet();
83 - return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
84 - }
85 - }
86 } 90 }
87 91
88 @Override 92 @Override
...@@ -103,34 +107,111 @@ public class SimpleMastershipStore ...@@ -103,34 +107,111 @@ public class SimpleMastershipStore
103 107
104 @Override 108 @Override
105 public MastershipRole requestRole(DeviceId deviceId) { 109 public MastershipRole requestRole(DeviceId deviceId) {
106 - return getRole(instance.id(), deviceId); 110 + //query+possible reelection
111 + NodeId node = instance.id();
112 + MastershipRole role = getRole(node, deviceId);
113 +
114 + switch (role) {
115 + case MASTER:
116 + break;
117 + case STANDBY:
118 + synchronized (this) {
119 + //try to "re-elect", since we're really not distributed
120 + NodeId rel = reelect(node);
121 + if (rel == null) {
122 + masterMap.put(deviceId, node);
123 + termMap.put(deviceId, new AtomicInteger());
124 + role = MastershipRole.MASTER;
125 + }
126 + backups.add(node);
127 + }
128 + break;
129 + case NONE:
130 + //first to get to it, say we are master
131 + synchronized (this) {
132 + masterMap.put(deviceId, node);
133 + termMap.put(deviceId, new AtomicInteger());
134 + backups.add(node);
135 + role = MastershipRole.MASTER;
136 + }
137 + break;
138 + default:
139 + log.warn("unknown Mastership Role {}", role);
140 + }
141 + return role;
107 } 142 }
108 143
109 @Override 144 @Override
110 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) { 145 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
111 - NodeId node = masterMap.get(deviceId); 146 + //just query
147 + NodeId current = masterMap.get(deviceId);
112 MastershipRole role; 148 MastershipRole role;
113 - if (node != null) { 149 +
114 - if (node.equals(nodeId)) { 150 + if (current == null) {
151 + if (backups.contains(nodeId)) {
152 + role = MastershipRole.STANDBY;
153 + } else {
154 + role = MastershipRole.NONE;
155 + }
156 + } else {
157 + if (current.equals(nodeId)) {
115 role = MastershipRole.MASTER; 158 role = MastershipRole.MASTER;
116 } else { 159 } else {
117 role = MastershipRole.STANDBY; 160 role = MastershipRole.STANDBY;
118 } 161 }
119 - } else {
120 - //masterMap doesn't contain it.
121 - role = MastershipRole.MASTER;
122 - masterMap.put(deviceId, nodeId);
123 } 162 }
124 return role; 163 return role;
125 } 164 }
126 165
127 @Override 166 @Override
128 public MastershipTerm getTermFor(DeviceId deviceId) { 167 public MastershipTerm getTermFor(DeviceId deviceId) {
129 - if (masterMap.get(deviceId) == null) { 168 + if ((masterMap.get(deviceId) == null) ||
169 + (termMap.get(deviceId) == null)) {
130 return null; 170 return null;
131 } 171 }
132 return MastershipTerm.of( 172 return MastershipTerm.of(
133 masterMap.get(deviceId), termMap.get(deviceId).get()); 173 masterMap.get(deviceId), termMap.get(deviceId).get());
134 } 174 }
135 175
176 + @Override
177 + public MastershipEvent unsetMaster(NodeId nodeId, DeviceId deviceId) {
178 + MastershipRole role = getRole(nodeId, deviceId);
179 + synchronized (this) {
180 + switch (role) {
181 + case MASTER:
182 + NodeId backup = reelect(nodeId);
183 + if (backup == null) {
184 + masterMap.remove(deviceId);
185 + } else {
186 + masterMap.put(deviceId, backup);
187 + termMap.get(deviceId).incrementAndGet();
188 + return new MastershipEvent(MASTER_CHANGED, deviceId, backup);
189 + }
190 + case STANDBY:
191 + case NONE:
192 + if (!termMap.containsKey(deviceId)) {
193 + termMap.put(deviceId, new AtomicInteger());
194 + }
195 + backups.add(nodeId);
196 + break;
197 + default:
198 + log.warn("unknown Mastership Role {}", role);
199 + }
200 + }
201 + return null;
202 + }
203 +
204 + //dumbly selects next-available node that's not the current one
205 + //emulate leader election
206 + private NodeId reelect(NodeId nodeId) {
207 + NodeId backup = null;
208 + for (NodeId n : backups) {
209 + if (!n.equals(nodeId)) {
210 + backup = n;
211 + break;
212 + }
213 + }
214 + return backup;
215 + }
216 +
136 } 217 }
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.apache.felix.scr.annotations.Activate; 3 import org.apache.felix.scr.annotations.Activate;
4 import org.apache.felix.scr.annotations.Component; 4 import org.apache.felix.scr.annotations.Component;
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
2 * Implementations of in-memory stores suitable for unit testing and 2 * Implementations of in-memory stores suitable for unit testing and
3 * experimentation; not for production use. 3 * experimentation; not for production use.
4 */ 4 */
5 -package org.onlab.onos.net.trivial.impl; 5 +package org.onlab.onos.store.trivial.impl;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.junit.Before; 3 import org.junit.Before;
4 import org.junit.Test; 4 import org.junit.Test;
......
1 /** 1 /**
2 * 2 *
3 */ 3 */
4 -package org.onlab.onos.net.trivial.impl; 4 +package org.onlab.onos.store.trivial.impl;
5 5
6 import static org.junit.Assert.*; 6 import static org.junit.Assert.*;
7 import static org.onlab.onos.net.Device.Type.SWITCH; 7 import static org.onlab.onos.net.Device.Type.SWITCH;
...@@ -44,6 +44,7 @@ import com.google.common.collect.Sets; ...@@ -44,6 +44,7 @@ import com.google.common.collect.Sets;
44 public class SimpleDeviceStoreTest { 44 public class SimpleDeviceStoreTest {
45 45
46 private static final ProviderId PID = new ProviderId("of", "foo"); 46 private static final ProviderId PID = new ProviderId("of", "foo");
47 + private static final ProviderId PIDA = new ProviderId("of", "bar", true);
47 private static final DeviceId DID1 = deviceId("of:foo"); 48 private static final DeviceId DID1 = deviceId("of:foo");
48 private static final DeviceId DID2 = deviceId("of:bar"); 49 private static final DeviceId DID2 = deviceId("of:bar");
49 private static final String MFR = "whitebox"; 50 private static final String MFR = "whitebox";
...@@ -89,6 +90,13 @@ public class SimpleDeviceStoreTest { ...@@ -89,6 +90,13 @@ public class SimpleDeviceStoreTest {
89 deviceStore.createOrUpdateDevice(PID, deviceId, description); 90 deviceStore.createOrUpdateDevice(PID, deviceId, description);
90 } 91 }
91 92
93 + private void putDeviceAncillary(DeviceId deviceId, String swVersion) {
94 + DeviceDescription description =
95 + new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
96 + HW, swVersion, SN);
97 + deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
98 + }
99 +
92 private static void assertDevice(DeviceId id, String swVersion, Device device) { 100 private static void assertDevice(DeviceId id, String swVersion, Device device) {
93 assertNotNull(device); 101 assertNotNull(device);
94 assertEquals(id, device.id()); 102 assertEquals(id, device.id());
...@@ -160,6 +168,33 @@ public class SimpleDeviceStoreTest { ...@@ -160,6 +168,33 @@ public class SimpleDeviceStoreTest {
160 } 168 }
161 169
162 @Test 170 @Test
171 + public final void testCreateOrUpdateDeviceAncillary() {
172 + DeviceDescription description =
173 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
174 + HW, SW1, SN);
175 + DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
176 + assertEquals(DEVICE_ADDED, event.type());
177 + assertDevice(DID1, SW1, event.subject());
178 + assertEquals(PIDA, event.subject().providerId());
179 + assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
180 +
181 + DeviceDescription description2 =
182 + new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
183 + HW, SW2, SN);
184 + DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
185 + assertEquals(DEVICE_UPDATED, event2.type());
186 + assertDevice(DID1, SW2, event2.subject());
187 + assertEquals(PID, event2.subject().providerId());
188 + assertTrue(deviceStore.isAvailable(DID1));
189 +
190 + assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
191 +
192 + // For now, Ancillary is ignored once primary appears
193 + assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
194 + }
195 +
196 +
197 + @Test
163 public final void testMarkOffline() { 198 public final void testMarkOffline() {
164 199
165 putDevice(DID1, SW1); 200 putDevice(DID1, SW1);
...@@ -182,7 +217,7 @@ public class SimpleDeviceStoreTest { ...@@ -182,7 +217,7 @@ public class SimpleDeviceStoreTest {
182 new DefaultPortDescription(P2, true) 217 new DefaultPortDescription(P2, true)
183 ); 218 );
184 219
185 - List<DeviceEvent> events = deviceStore.updatePorts(DID1, pds); 220 + List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
186 221
187 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 222 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
188 for (DeviceEvent event : events) { 223 for (DeviceEvent event : events) {
...@@ -201,7 +236,7 @@ public class SimpleDeviceStoreTest { ...@@ -201,7 +236,7 @@ public class SimpleDeviceStoreTest {
201 new DefaultPortDescription(P3, true) 236 new DefaultPortDescription(P3, true)
202 ); 237 );
203 238
204 - events = deviceStore.updatePorts(DID1, pds2); 239 + events = deviceStore.updatePorts(PID, DID1, pds2);
205 assertFalse("event should be triggered", events.isEmpty()); 240 assertFalse("event should be triggered", events.isEmpty());
206 for (DeviceEvent event : events) { 241 for (DeviceEvent event : events) {
207 PortNumber num = event.port().number(); 242 PortNumber num = event.port().number();
...@@ -224,7 +259,7 @@ public class SimpleDeviceStoreTest { ...@@ -224,7 +259,7 @@ public class SimpleDeviceStoreTest {
224 new DefaultPortDescription(P1, false), 259 new DefaultPortDescription(P1, false),
225 new DefaultPortDescription(P2, true) 260 new DefaultPortDescription(P2, true)
226 ); 261 );
227 - events = deviceStore.updatePorts(DID1, pds3); 262 + events = deviceStore.updatePorts(PID, DID1, pds3);
228 assertFalse("event should be triggered", events.isEmpty()); 263 assertFalse("event should be triggered", events.isEmpty());
229 for (DeviceEvent event : events) { 264 for (DeviceEvent event : events) {
230 PortNumber num = event.port().number(); 265 PortNumber num = event.port().number();
...@@ -249,14 +284,42 @@ public class SimpleDeviceStoreTest { ...@@ -249,14 +284,42 @@ public class SimpleDeviceStoreTest {
249 List<PortDescription> pds = Arrays.<PortDescription>asList( 284 List<PortDescription> pds = Arrays.<PortDescription>asList(
250 new DefaultPortDescription(P1, true) 285 new DefaultPortDescription(P1, true)
251 ); 286 );
252 - deviceStore.updatePorts(DID1, pds); 287 + deviceStore.updatePorts(PID, DID1, pds);
288 +
289 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
290 + new DefaultPortDescription(P1, false));
291 + assertEquals(PORT_UPDATED, event.type());
292 + assertDevice(DID1, SW1, event.subject());
293 + assertEquals(P1, event.port().number());
294 + assertFalse("Port is disabled", event.port().isEnabled());
295 +
296 + }
297 + @Test
298 + public final void testUpdatePortStatusAncillary() {
299 + putDeviceAncillary(DID1, SW1);
300 + putDevice(DID1, SW1);
301 + List<PortDescription> pds = Arrays.<PortDescription>asList(
302 + new DefaultPortDescription(P1, true)
303 + );
304 + deviceStore.updatePorts(PID, DID1, pds);
253 305
254 - DeviceEvent event = deviceStore.updatePortStatus(DID1, 306 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
255 new DefaultPortDescription(P1, false)); 307 new DefaultPortDescription(P1, false));
256 assertEquals(PORT_UPDATED, event.type()); 308 assertEquals(PORT_UPDATED, event.type());
257 assertDevice(DID1, SW1, event.subject()); 309 assertDevice(DID1, SW1, event.subject());
258 assertEquals(P1, event.port().number()); 310 assertEquals(P1, event.port().number());
259 assertFalse("Port is disabled", event.port().isEnabled()); 311 assertFalse("Port is disabled", event.port().isEnabled());
312 +
313 + DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1,
314 + new DefaultPortDescription(P1, true));
315 + assertNull("Ancillary is ignored if primary exists", event2);
316 +
317 + DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1,
318 + new DefaultPortDescription(P2, true));
319 + assertEquals(PORT_ADDED, event3.type());
320 + assertDevice(DID1, SW1, event3.subject());
321 + assertEquals(P2, event3.port().number());
322 + assertFalse("Port is disabled if not given from provider", event3.port().isEnabled());
260 } 323 }
261 324
262 @Test 325 @Test
...@@ -267,7 +330,7 @@ public class SimpleDeviceStoreTest { ...@@ -267,7 +330,7 @@ public class SimpleDeviceStoreTest {
267 new DefaultPortDescription(P1, true), 330 new DefaultPortDescription(P1, true),
268 new DefaultPortDescription(P2, true) 331 new DefaultPortDescription(P2, true)
269 ); 332 );
270 - deviceStore.updatePorts(DID1, pds); 333 + deviceStore.updatePorts(PID, DID1, pds);
271 334
272 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 335 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
273 List<Port> ports = deviceStore.getPorts(DID1); 336 List<Port> ports = deviceStore.getPorts(DID1);
...@@ -290,7 +353,7 @@ public class SimpleDeviceStoreTest { ...@@ -290,7 +353,7 @@ public class SimpleDeviceStoreTest {
290 new DefaultPortDescription(P1, true), 353 new DefaultPortDescription(P1, true),
291 new DefaultPortDescription(P2, false) 354 new DefaultPortDescription(P2, false)
292 ); 355 );
293 - deviceStore.updatePorts(DID1, pds); 356 + deviceStore.updatePorts(PID, DID1, pds);
294 357
295 Port port1 = deviceStore.getPort(DID1, P1); 358 Port port1 = deviceStore.getPort(DID1, P1);
296 assertEquals(P1, port1.number()); 359 assertEquals(P1, port1.number());
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import static org.junit.Assert.*; 3 import static org.junit.Assert.*;
4 import static org.onlab.onos.net.DeviceId.deviceId; 4 import static org.onlab.onos.net.DeviceId.deviceId;
......
1 +package org.onlab.onos.store.trivial.impl;
2 +
3 +import java.util.Set;
4 +import java.util.concurrent.atomic.AtomicInteger;
5 +
6 +import org.junit.After;
7 +import org.junit.Before;
8 +import org.junit.Test;
9 +import org.onlab.onos.cluster.MastershipTerm;
10 +import org.onlab.onos.cluster.NodeId;
11 +import org.onlab.onos.net.DeviceId;
12 +
13 +import com.google.common.collect.Sets;
14 +
15 +import static org.junit.Assert.assertEquals;
16 +import static org.junit.Assert.assertNull;
17 +import static org.junit.Assert.assertTrue;
18 +import static org.onlab.onos.net.MastershipRole.*;
19 +import static org.onlab.onos.cluster.MastershipEvent.Type.*;
20 +
21 +/**
22 + * Test for the simple MastershipStore implementation.
23 + */
24 +public class SimpleMastershipStoreTest {
25 +
26 + private static final DeviceId DID1 = DeviceId.deviceId("of:01");
27 + private static final DeviceId DID2 = DeviceId.deviceId("of:02");
28 + private static final DeviceId DID3 = DeviceId.deviceId("of:03");
29 + private static final DeviceId DID4 = DeviceId.deviceId("of:04");
30 +
31 + private static final NodeId N1 = new NodeId("local");
32 + private static final NodeId N2 = new NodeId("other");
33 +
34 + private SimpleMastershipStore sms;
35 +
36 + @Before
37 + public void setUp() throws Exception {
38 + sms = new SimpleMastershipStore();
39 + sms.activate();
40 + }
41 +
42 + @After
43 + public void tearDown() throws Exception {
44 + sms.deactivate();
45 + }
46 +
47 + @Test
48 + public void getRole() {
49 + //special case, no backup or master
50 + put(DID1, N1, false, false);
51 + assertEquals("wrong role", NONE, sms.getRole(N1, DID1));
52 +
53 + //backup exists but we aren't mapped
54 + put(DID2, N1, false, true);
55 + assertEquals("wrong role", STANDBY, sms.getRole(N1, DID2));
56 +
57 + //N2 is master
58 + put(DID3, N2, true, true);
59 + assertEquals("wrong role", MASTER, sms.getRole(N2, DID3));
60 +
61 + //N2 is master but N1 is only in backups set
62 + put(DID4, N2, true, false);
63 + assertEquals("wrong role", STANDBY, sms.getRole(N1, DID4));
64 + }
65 +
66 + @Test
67 + public void getMaster() {
68 + put(DID3, N2, true, true);
69 + assertEquals("wrong role", MASTER, sms.getRole(N2, DID3));
70 + assertEquals("wrong device", N2, sms.getMaster(DID3));
71 + }
72 +
73 + @Test
74 + public void setMaster() {
75 + put(DID1, N1, false, false);
76 + assertEquals("wrong event", MASTER_CHANGED, sms.setMaster(N1, DID1).type());
77 + assertEquals("wrong role", MASTER, sms.getRole(N1, DID1));
78 + //set node that's already master - should be ignored
79 + assertNull("wrong event", sms.setMaster(N1, DID1));
80 +
81 + //set STANDBY to MASTER
82 + put(DID2, N1, false, true);
83 + assertEquals("wrong role", STANDBY, sms.getRole(N1, DID2));
84 + assertEquals("wrong event", MASTER_CHANGED, sms.setMaster(N1, DID2).type());
85 + assertEquals("wrong role", MASTER, sms.getRole(N1, DID2));
86 + }
87 +
88 + @Test
89 + public void getDevices() {
90 + Set<DeviceId> d = Sets.newHashSet(DID1, DID2);
91 +
92 + put(DID1, N2, true, true);
93 + put(DID2, N2, true, true);
94 + put(DID3, N1, true, true);
95 + assertTrue("wrong devices", d.equals(sms.getDevices(N2)));
96 + }
97 +
98 + @Test
99 + public void getTermFor() {
100 + put(DID1, N1, true, true);
101 + assertEquals("wrong term", MastershipTerm.of(N1, 0), sms.getTermFor(DID1));
102 +
103 + //switch to N2 and back - 2 term switches
104 + sms.setMaster(N2, DID1);
105 + sms.setMaster(N1, DID1);
106 + assertEquals("wrong term", MastershipTerm.of(N1, 2), sms.getTermFor(DID1));
107 + }
108 +
109 + @Test
110 + public void requestRole() {
111 + //NONE - become MASTER
112 + put(DID1, N1, false, false);
113 + assertEquals("wrong role", MASTER, sms.requestRole(DID1));
114 +
115 + //STANDBY without backup - become MASTER
116 + put(DID2, N1, false, true);
117 + assertEquals("wrong role", MASTER, sms.requestRole(DID2));
118 +
119 + //STANDBY with backup - stay STANDBY
120 + put(DID3, N2, false, true);
121 + assertEquals("wrong role", STANDBY, sms.requestRole(DID3));
122 +
123 + //local (N1) is MASTER - stay MASTER
124 + put(DID4, N1, true, true);
125 + assertEquals("wrong role", MASTER, sms.requestRole(DID4));
126 + }
127 +
128 + @Test
129 + public void unsetMaster() {
130 + //NONE - record backup but take no other action
131 + put(DID1, N1, false, false);
132 + sms.unsetMaster(N1, DID1);
133 + assertTrue("not backed up", sms.backups.contains(N1));
134 + sms.termMap.clear();
135 + sms.unsetMaster(N1, DID1);
136 + assertTrue("term not set", sms.termMap.containsKey(DID1));
137 +
138 + //no backup, MASTER
139 + put(DID1, N1, true, true);
140 + assertNull("wrong event", sms.unsetMaster(N1, DID1));
141 + assertNull("wrong node", sms.masterMap.get(DID1));
142 +
143 + //backup, switch
144 + sms.masterMap.clear();
145 + put(DID1, N1, true, true);
146 + put(DID2, N2, true, true);
147 + assertEquals("wrong event", MASTER_CHANGED, sms.unsetMaster(N1, DID1).type());
148 + }
149 +
150 + //helper to populate master/backup structures
151 + private void put(DeviceId dev, NodeId node, boolean store, boolean backup) {
152 + if (store) {
153 + sms.masterMap.put(dev, node);
154 + }
155 + if (backup) {
156 + sms.backups.add(node);
157 + }
158 + sms.termMap.put(dev, new AtomicInteger());
159 + }
160 +}
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
11 <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> 11 <bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
12 12
13 <bundle>mvn:com.hazelcast/hazelcast/3.3</bundle> 13 <bundle>mvn:com.hazelcast/hazelcast/3.3</bundle>
14 + <bundle>mvn:com.codahale.metrics/metrics-core/3.0.2</bundle>
14 <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle> 15 <bundle>mvn:com.eclipsesource.minimal-json/minimal-json/0.9.1</bundle>
15 16
16 <bundle>mvn:com.esotericsoftware.kryo/kryo/2.24.0</bundle> 17 <bundle>mvn:com.esotericsoftware.kryo/kryo/2.24.0</bundle>
......
...@@ -48,7 +48,7 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext ...@@ -48,7 +48,7 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
48 OFPacketOut.Builder builder = sw.factory().buildPacketOut(); 48 OFPacketOut.Builder builder = sw.factory().buildPacketOut();
49 OFAction act = buildOutput(outPort.getPortNumber()); 49 OFAction act = buildOutput(outPort.getPortNumber());
50 pktout = builder.setXid(pktin.getXid()) 50 pktout = builder.setXid(pktin.getXid())
51 - .setInPort(pktin.getInPort()) 51 + .setInPort(inport())
52 .setBufferId(pktin.getBufferId()) 52 .setBufferId(pktin.getBufferId())
53 .setActions(Collections.singletonList(act)) 53 .setActions(Collections.singletonList(act))
54 .build(); 54 .build();
...@@ -63,7 +63,7 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext ...@@ -63,7 +63,7 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
63 OFAction act = buildOutput(outPort.getPortNumber()); 63 OFAction act = buildOutput(outPort.getPortNumber());
64 pktout = builder.setXid(pktin.getXid()) 64 pktout = builder.setXid(pktin.getXid())
65 .setBufferId(OFBufferId.NO_BUFFER) 65 .setBufferId(OFBufferId.NO_BUFFER)
66 - .setInPort(pktin.getInPort()) 66 + .setInPort(inport())
67 .setActions(Collections.singletonList(act)) 67 .setActions(Collections.singletonList(act))
68 .setData(ethFrame.serialize()) 68 .setData(ethFrame.serialize())
69 .build(); 69 .build();
...@@ -88,10 +88,16 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext ...@@ -88,10 +88,16 @@ public final class DefaultOpenFlowPacketContext implements OpenFlowPacketContext
88 88
89 @Override 89 @Override
90 public Integer inPort() { 90 public Integer inPort() {
91 + return inport().getPortNumber();
92 + }
93 +
94 +
95 + private OFPort inport() {
96 + //FIXME: this has to change in fucking loxi
91 try { 97 try {
92 - return pktin.getInPort().getPortNumber(); 98 + return pktin.getInPort();
93 } catch (UnsupportedOperationException e) { 99 } catch (UnsupportedOperationException e) {
94 - return pktin.getMatch().get(MatchField.IN_PORT).getPortNumber(); 100 + return pktin.getMatch().get(MatchField.IN_PORT);
95 } 101 }
96 } 102 }
97 103
......
...@@ -243,6 +243,8 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { ...@@ -243,6 +243,8 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
243 if (role == RoleState.SLAVE || role == RoleState.EQUAL) { 243 if (role == RoleState.SLAVE || role == RoleState.EQUAL) {
244 this.role = role; 244 this.role = role;
245 } 245 }
246 + } else {
247 + this.role = role;
246 } 248 }
247 } catch (IOException e) { 249 } catch (IOException e) {
248 log.error("Unable to write to switch {}.", this.dpid); 250 log.error("Unable to write to switch {}.", this.dpid);
......
...@@ -651,7 +651,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler { ...@@ -651,7 +651,7 @@ class OFChannelHandler extends IdleStateAwareChannelHandler {
651 * @param error The error message 651 * @param error The error message
652 */ 652 */
653 protected void logError(OFChannelHandler h, OFErrorMsg error) { 653 protected void logError(OFChannelHandler h, OFErrorMsg error) {
654 - log.error("{} from switch {} in state {}", 654 + log.info("{} from switch {} in state {}",
655 new Object[] { 655 new Object[] {
656 error, 656 error,
657 h.getSwitchInfoString(), 657 h.getSwitchInfoString(),
......
...@@ -6,6 +6,7 @@ import java.util.Collections; ...@@ -6,6 +6,7 @@ import java.util.Collections;
6 import java.util.List; 6 import java.util.List;
7 7
8 import org.onlab.onos.openflow.controller.Dpid; 8 import org.onlab.onos.openflow.controller.Dpid;
9 +import org.onlab.onos.openflow.controller.RoleState;
9 import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch; 10 import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch;
10 import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver; 11 import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver;
11 import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriverFactory; 12 import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriverFactory;
...@@ -61,6 +62,11 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory { ...@@ -61,6 +62,11 @@ public final class DriverManager implements OpenFlowSwitchDriverFactory {
61 return new AbstractOpenFlowSwitch(dpid, desc) { 62 return new AbstractOpenFlowSwitch(dpid, desc) {
62 63
63 @Override 64 @Override
65 + public void setRole(RoleState state) {
66 + this.role = RoleState.MASTER;
67 + }
68 +
69 + @Override
64 public void write(List<OFMessage> msgs) { 70 public void write(List<OFMessage> msgs) {
65 channel.write(msgs); 71 channel.write(msgs);
66 } 72 }
......
...@@ -425,7 +425,7 @@ ...@@ -425,7 +425,7 @@
425 <group> 425 <group>
426 <title>Core Subsystems</title> 426 <title>Core Subsystems</title>
427 <packages> 427 <packages>
428 - org.onlab.onos.cluster.impl: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.event.impl:org.onlab.onos.store.* 428 + org.onlab.onos.cluster.impl: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.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*
429 </packages> 429 </packages>
430 </group> 430 </group>
431 <group> 431 <group>
......
...@@ -73,10 +73,11 @@ public class FlowModBuilder { ...@@ -73,10 +73,11 @@ public class FlowModBuilder {
73 List<OFAction> actions = buildActions(); 73 List<OFAction> actions = buildActions();
74 74
75 //TODO: what to do without bufferid? do we assume that there will be a pktout as well? 75 //TODO: what to do without bufferid? do we assume that there will be a pktout as well?
76 - OFFlowMod fm = factory.buildFlowModify() 76 + OFFlowMod fm = factory.buildFlowAdd()
77 .setCookie(U64.of(cookie.value())) 77 .setCookie(U64.of(cookie.value()))
78 .setBufferId(OFBufferId.NO_BUFFER) 78 .setBufferId(OFBufferId.NO_BUFFER)
79 .setActions(actions) 79 .setActions(actions)
80 + .setIdleTimeout(10)
80 .setMatch(match) 81 .setMatch(match)
81 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) 82 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
82 .setPriority(priority) 83 .setPriority(priority)
...@@ -93,7 +94,7 @@ public class FlowModBuilder { ...@@ -93,7 +94,7 @@ public class FlowModBuilder {
93 OFFlowMod fm = factory.buildFlowDelete() 94 OFFlowMod fm = factory.buildFlowDelete()
94 .setCookie(U64.of(cookie.value())) 95 .setCookie(U64.of(cookie.value()))
95 .setBufferId(OFBufferId.NO_BUFFER) 96 .setBufferId(OFBufferId.NO_BUFFER)
96 - //.setActions(actions) 97 + .setActions(actions)
97 .setMatch(match) 98 .setMatch(match)
98 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM)) 99 .setFlags(Collections.singleton(OFFlowModFlags.SEND_FLOW_REM))
99 .setPriority(priority) 100 .setPriority(priority)
......
...@@ -18,6 +18,7 @@ import org.onlab.packet.IpPrefix; ...@@ -18,6 +18,7 @@ import org.onlab.packet.IpPrefix;
18 import org.onlab.packet.MacAddress; 18 import org.onlab.packet.MacAddress;
19 import org.onlab.packet.VlanId; 19 import org.onlab.packet.VlanId;
20 import org.projectfloodlight.openflow.protocol.OFFlowRemoved; 20 import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
21 +import org.projectfloodlight.openflow.protocol.OFFlowRemovedReason;
21 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; 22 import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
22 import org.projectfloodlight.openflow.protocol.action.OFAction; 23 import org.projectfloodlight.openflow.protocol.action.OFAction;
23 import org.projectfloodlight.openflow.protocol.action.OFActionOutput; 24 import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
...@@ -70,14 +71,15 @@ public class FlowRuleBuilder { ...@@ -70,14 +71,15 @@ public class FlowRuleBuilder {
70 buildSelector(), buildTreatment(), stat.getPriority(), 71 buildSelector(), buildTreatment(), stat.getPriority(),
71 FlowRuleState.ADDED, stat.getDurationNsec() / 1000000, 72 FlowRuleState.ADDED, stat.getDurationNsec() / 1000000,
72 stat.getPacketCount().getValue(), stat.getByteCount().getValue(), 73 stat.getPacketCount().getValue(), stat.getByteCount().getValue(),
73 - stat.getCookie().getValue()); 74 + stat.getCookie().getValue(), false);
74 } else { 75 } else {
75 // TODO: revisit potentially. 76 // TODO: revisit potentially.
76 return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)), 77 return new DefaultFlowRule(DeviceId.deviceId(Dpid.uri(dpid)),
77 buildSelector(), null, removed.getPriority(), 78 buildSelector(), null, removed.getPriority(),
78 FlowRuleState.REMOVED, removed.getDurationNsec() / 1000000, 79 FlowRuleState.REMOVED, removed.getDurationNsec() / 1000000,
79 removed.getPacketCount().getValue(), removed.getByteCount().getValue(), 80 removed.getPacketCount().getValue(), removed.getByteCount().getValue(),
80 - removed.getCookie().getValue()); 81 + removed.getCookie().getValue(),
82 + removed.getReason() == OFFlowRemovedReason.IDLE_TIMEOUT.ordinal());
81 } 83 }
82 } 84 }
83 85
......
...@@ -158,7 +158,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr ...@@ -158,7 +158,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
158 case BARRIER_REPLY: 158 case BARRIER_REPLY:
159 case ERROR: 159 case ERROR:
160 default: 160 default:
161 - log.warn("Unhandled message type: {}", msg.getType()); 161 + log.debug("Unhandled message type: {}", msg.getType());
162 } 162 }
163 163
164 } 164 }
......
...@@ -131,7 +131,7 @@ public class LinkDiscovery implements TimerTask { ...@@ -131,7 +131,7 @@ public class LinkDiscovery implements TimerTask {
131 } 131 }
132 timeout = Timer.getTimer().newTimeout(this, 0, 132 timeout = Timer.getTimer().newTimeout(this, 0,
133 TimeUnit.MILLISECONDS); 133 TimeUnit.MILLISECONDS);
134 - this.log.debug("Started discovery manager for switch {}", 134 + this.log.info("Started discovery manager for switch {}",
135 sw.getId()); 135 sw.getId());
136 136
137 } 137 }
......
1 package org.onlab.onos.provider.of.packet.impl; 1 package org.onlab.onos.provider.of.packet.impl;
2 2
3 -import static org.onlab.onos.openflow.controller.RoleState.SLAVE;
4 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
5 4
6 import java.nio.ByteBuffer; 5 import java.nio.ByteBuffer;
...@@ -95,9 +94,6 @@ public class OpenFlowPacketProvider extends AbstractProvider implements PacketPr ...@@ -95,9 +94,6 @@ public class OpenFlowPacketProvider extends AbstractProvider implements PacketPr
95 if (sw == null) { 94 if (sw == null) {
96 log.warn("Device {} isn't available?", devId); 95 log.warn("Device {} isn't available?", devId);
97 return; 96 return;
98 - } else if (sw.getRole().equals(SLAVE)) {
99 - log.warn("Can't write to Device {} as slave", devId);
100 - return;
101 } 97 }
102 98
103 Ethernet eth = new Ethernet(); 99 Ethernet eth = new Ethernet();
......
...@@ -140,12 +140,12 @@ public class OpenFlowPacketProviderTest { ...@@ -140,12 +140,12 @@ public class OpenFlowPacketProviderTest {
140 sw.sent.clear(); 140 sw.sent.clear();
141 141
142 //wrong Role 142 //wrong Role
143 - sw.setRole(RoleState.SLAVE); 143 + //sw.setRole(RoleState.SLAVE);
144 - provider.emit(passPkt); 144 + //provider.emit(passPkt);
145 - assertEquals("invalid switch", sw, controller.current); 145 + //assertEquals("invalid switch", sw, controller.current);
146 - assertEquals("message sent incorrectly", 0, sw.sent.size()); 146 + //assertEquals("message sent incorrectly", 0, sw.sent.size());
147 147
148 - sw.setRole(RoleState.MASTER); 148 + //sw.setRole(RoleState.MASTER);
149 149
150 //missing switch 150 //missing switch
151 OutboundPacket swFailPkt = outPacket(DID_MISSING, TR, eth); 151 OutboundPacket swFailPkt = outPacket(DID_MISSING, TR, eth);
......
...@@ -34,6 +34,8 @@ cp -r $ONOS_ROOT/tools/package/etc/* $KARAF_DIST/etc ...@@ -34,6 +34,8 @@ cp -r $ONOS_ROOT/tools/package/etc/* $KARAF_DIST/etc
34 mkdir -p $KARAF_DIST/system/org/onlab 34 mkdir -p $KARAF_DIST/system/org/onlab
35 cp -r $M2_REPO/org/onlab $KARAF_DIST/system/org/ 35 cp -r $M2_REPO/org/onlab $KARAF_DIST/system/org/
36 36
37 +export ONOS_FEATURES="${ONOS_FEATURES:-webconsole,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-openflow,onos-app-fwd,onos-app-foo}"
38 +
37 # Cellar Patching -------------------------------------------------------------- 39 # Cellar Patching --------------------------------------------------------------
38 40
39 # Patch the Apache Karaf distribution file to add Cellar features repository 41 # Patch the Apache Karaf distribution file to add Cellar features repository
...@@ -51,7 +53,7 @@ perl -pi.old -e "s|^(featuresRepositories=.*)|\1,mvn:org.onlab.onos/onos-feature ...@@ -51,7 +53,7 @@ perl -pi.old -e "s|^(featuresRepositories=.*)|\1,mvn:org.onlab.onos/onos-feature
51 $ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg 53 $ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
52 54
53 # Patch the Apache Karaf distribution file to load ONOS features 55 # Patch the Apache Karaf distribution file to load ONOS features
54 -perl -pi.old -e 's|^(featuresBoot=.*)|\1,webconsole,onos-api,onos-core,onos-cli,onos-rest,onos-gui,onos-openflow,onos-app-fwd,onos-app-foo|' \ 56 +perl -pi.old -e "s|^(featuresBoot=.*)|\1,$ONOS_FEATURES|" \
55 $ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg 57 $ONOS_STAGE/$KARAF_DIST/etc/org.apache.karaf.features.cfg
56 58
57 # Patch the Apache Karaf distribution with ONOS branding bundle 59 # Patch the Apache Karaf distribution with ONOS branding bundle
......
...@@ -9,5 +9,10 @@ ...@@ -9,5 +9,10 @@
9 nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2) 9 nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
10 10
11 onos-package 11 onos-package
12 -for node in $nodes; do (printf "%s: %s\n" "$node" "`onos-install -f $node`")& done 12 +for node in $nodes; do onos-install -f $node 1>/dev/null & done
13 +
14 +# Wait for shutdown before waiting for restart
15 +sleep 3
16 +
13 for node in $nodes; do onos-wait-for-start $node; done 17 for node in $nodes; do onos-wait-for-start $node; done
18 +for node in $nodes; do onos-check-logs $node; done
......
...@@ -6,22 +6,21 @@ ...@@ -6,22 +6,21 @@
6 export ONOS_ROOT=${ONOS_ROOT:-~/onos-next} 6 export ONOS_ROOT=${ONOS_ROOT:-~/onos-next}
7 7
8 # Setup some environmental context for developers 8 # Setup some environmental context for developers
9 -export JAVA_HOME=$(/usr/libexec/java_home) 9 +export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
10 export MAVEN=${MAVEN:-~/Applications/apache-maven-3.2.2} 10 export MAVEN=${MAVEN:-~/Applications/apache-maven-3.2.2}
11 export KARAF=${KARAF:-~/Applications/apache-karaf-3.0.1} 11 export KARAF=${KARAF:-~/Applications/apache-karaf-3.0.1}
12 export KARAF_LOG=$KARAF/data/log/karaf.log 12 export KARAF_LOG=$KARAF/data/log/karaf.log
13 13
14 # Setup a path 14 # Setup a path
15 -export PS=":" 15 +export PATH="$PATH:$ONOS_ROOT/tools/dev/bin:$ONOS_ROOT/tools/test/bin"
16 -export PATH="$PATH:$ONOS_ROOT/tools/dev:$ONOS_ROOT/tools/build" 16 +export PATH="$PATH:$ONOS_ROOT/tools/build"
17 -export PATH="$PATH:$ONOS_ROOT/tools/test/bin"
18 export PATH="$PATH:$MAVEN/bin:$KARAF/bin" 17 export PATH="$PATH:$MAVEN/bin:$KARAF/bin"
19 export PATH="$PATH:." 18 export PATH="$PATH:."
20 19
21 # Convenience utility to warp to various ONOS source projects 20 # Convenience utility to warp to various ONOS source projects
22 # e.g. 'o api', 'o dev', 'o' 21 # e.g. 'o api', 'o dev', 'o'
23 function o { 22 function o {
24 - cd $(find $ONOS_ROOT/ -type d | egrep -v '\.git|target|src' | \ 23 + cd $(find $ONOS_ROOT/ -type d | egrep -v '\.git|target' | \
25 egrep "${1:-$ONOS_ROOT}" | head -n 1) 24 egrep "${1:-$ONOS_ROOT}" | head -n 1)
26 } 25 }
27 26
...@@ -30,11 +29,12 @@ alias mci='mvn clean install' ...@@ -30,11 +29,12 @@ alias mci='mvn clean install'
30 29
31 # Short-hand for ONOS build, package and test. 30 # Short-hand for ONOS build, package and test.
32 alias ob='onos-build' 31 alias ob='onos-build'
32 +alias obs='onos-build-selective'
33 alias op='onos-package' 33 alias op='onos-package'
34 alias ot='onos-test' 34 alias ot='onos-test'
35 35
36 # Short-hand for tailing the ONOS (karaf) log 36 # Short-hand for tailing the ONOS (karaf) log
37 -alias tl='$ONOS_ROOT/tools/dev/watchLog' 37 +alias tl='$ONOS_ROOT/tools/dev/bin/onos-local-log'
38 alias tlo='tl | grep --colour=always org.onlab' 38 alias tlo='tl | grep --colour=always org.onlab'
39 39
40 # Pretty-print JSON output 40 # Pretty-print JSON output
...@@ -57,6 +57,7 @@ function cell { ...@@ -57,6 +57,7 @@ function cell {
57 if [ -n "$1" ]; then 57 if [ -n "$1" ]; then
58 [ ! -f $ONOS_ROOT/tools/test/cells/$1 ] && \ 58 [ ! -f $ONOS_ROOT/tools/test/cells/$1 ] && \
59 echo "No such cell: $1" >&2 && return 1 59 echo "No such cell: $1" >&2 && return 1
60 + unset OC1 OC2 OC3 OC4 OC5 OC6 OC7 OC8 OC9 OCN OCI
60 . $ONOS_ROOT/tools/test/cells/$1 61 . $ONOS_ROOT/tools/test/cells/$1
61 export OCI=$OC1 62 export OCI=$OC1
62 export ONOS_CELL=$1 63 export ONOS_CELL=$1
...@@ -66,6 +67,7 @@ function cell { ...@@ -66,6 +67,7 @@ function cell {
66 env | egrep "OCI" 67 env | egrep "OCI"
67 env | egrep "OC[0-9]+" | sort 68 env | egrep "OC[0-9]+" | sort
68 env | egrep "OCN" 69 env | egrep "OCN"
70 + env | egrep "ONOS_" | egrep -v 'ONOS_ROOT|ONOS_CELL'
69 fi 71 fi
70 } 72 }
71 73
...@@ -73,7 +75,11 @@ cell local >/dev/null # Default cell is the local VMs ...@@ -73,7 +75,11 @@ cell local >/dev/null # Default cell is the local VMs
73 75
74 # Lists available cells 76 # Lists available cells
75 function cells { 77 function cells {
76 - ls -1 $ONOS_ROOT/tools/test/cells 78 + for cell in $(ls -1 $ONOS_ROOT/tools/test/cells); do
79 + printf "%-12s %s\n" \
80 + "$([ $cell = $ONOS_CELL ] && echo $cell '*' || echo $cell)" \
81 + "$(grep '^#' $ONOS_ROOT/tools/test/cells/$cell | head -n 1)"
82 + done
77 } 83 }
78 84
79 # Miscellaneous 85 # Miscellaneous
......
1 +#!/bin/bash
2 +#------------------------------------------------------------------------------
3 +# Selectively builds only those projects that contained modified Java files.
4 +#------------------------------------------------------------------------------
5 +
6 +projects=$(find $ONOS_ROOT -name '*.java' \
7 + -not -path '*/openflowj/*' -and -not -path '.git/*' \
8 + -exec $ONOS_ROOT/tools/dev/bin/onos-build-selective-hook {} \; | \
9 + sort -u | sed "s:$ONOS_ROOT::g" | tr '\n' ',' | \
10 + sed 's:/,:,:g;s:,/:,:g;s:^/::g;s:,$::g')
11 +
12 +[ -n "$projects" ] && cd $ONOS_ROOT && mvn --projects $projects ${@:-clean install}
...\ No newline at end of file ...\ No newline at end of file
1 +#------------------------------------------------------------------------------
2 +# Echoes project-level directory if a Java file within is newer than its
3 +# class file counterpart
4 +#------------------------------------------------------------------------------
5 +
6 +javaFile=${1#*\/src\/*\/java/}
7 +basename=${1/*\//}
8 +
9 +[ $basename = "package-info.java" ] && exit 0
10 +
11 +src=${1/$javaFile/}
12 +project=${src/src*/}
13 +classFile=${javaFile/.java/.class}
14 +
15 +[ ${project}target/classes/$classFile -nt ${src}$javaFile -o \
16 + ${project}target/test-classes/$classFile -nt ${src}$javaFile ] \
17 + || echo ${src/src*/}
18 +
1 -unset OC1 OC2 OC3 OC4 OC5 OC6 OC7 OC8 OC9 OCN ONOS_NIC
1 -# Default virtual box ONOS instances 1,2 & ONOS mininet box 1 +# Local VirtualBox-based ONOS instances 1,2 & ONOS mininet box
2 -. $ONOS_ROOT/tools/test/cells/.reset
3 2
4 export ONOS_NIC=192.168.56.* 3 export ONOS_NIC=192.168.56.*
5 -
6 export OC1="192.168.56.101" 4 export OC1="192.168.56.101"
7 export OC2="192.168.56.102" 5 export OC2="192.168.56.102"
8 6
......
1 +# ProxMox-based cell of ONOS instance; no mininet-box
2 +
3 +export ONOS_FEATURES="webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-app-fwd,onos-app-mobility,onos-app-tvue"
4 +
5 +export ONOS_NIC="10.128.4.*"
6 +export OC1="10.128.4.60"
7 +
1 # ProxMox-based cell of ONOS instances 1,2 & ONOS mininet box 1 # ProxMox-based cell of ONOS instances 1,2 & ONOS mininet box
2 -. $ONOS_ROOT/tools/test/cells/.reset
3 2
4 export ONOS_NIC="10.1.9.*" 3 export ONOS_NIC="10.1.9.*"
5 -
6 export OC1="10.1.9.94" 4 export OC1="10.1.9.94"
7 export OC2="10.1.9.82" 5 export OC2="10.1.9.82"
8 6
......
1 +# Local VirtualBox-based single ONOS instance & ONOS mininet box
2 +
3 +export ONOS_NIC=192.168.56.*
4 +export OC1="192.168.56.101"
5 +export OCN="192.168.56.103"
6 +
1 -# Default virtual box ONOS instances 1,2 & ONOS mininet box
2 -
3 -export ONOS_NIC=192.168.56.*
4 -
5 -export OC1="192.168.56.11"
6 -export OC2="192.168.56.12"
7 -
8 -export OCN="192.168.56.7"
9 -
10 -
1 +# Local VirtualBox-based ONOS instances 1,2,3 & ONOS mininet box
2 +
3 +export ONOS_NIC=192.168.56.*
4 +export OC1="192.168.56.101"
5 +export OC2="192.168.56.102"
6 +export OC3="192.168.56.104"
7 +
8 +export OCN="192.168.56.103"
9 +
...@@ -55,6 +55,11 @@ ...@@ -55,6 +55,11 @@
55 <groupId>org.objenesis</groupId> 55 <groupId>org.objenesis</groupId>
56 <artifactId>objenesis</artifactId> 56 <artifactId>objenesis</artifactId>
57 </dependency> 57 </dependency>
58 + <dependency>
59 + <groupId>com.codahale.metrics</groupId>
60 + <artifactId>metrics-core</artifactId>
61 + <version>3.0.2</version>
62 + </dependency>
58 </dependencies> 63 </dependencies>
59 64
60 </project> 65 </project>
......
1 +package org.onlab.metrics;
2 +
3 +import java.util.concurrent.ConcurrentHashMap;
4 +import java.util.concurrent.ConcurrentMap;
5 +
6 +/**
7 + * Components to register for metrics.
8 + */
9 +public class MetricsComponent implements MetricsComponentRegistry {
10 + private final String name;
11 +
12 + /**
13 + * Registry to hold the Features defined in this Component.
14 + */
15 + private final ConcurrentMap<String, MetricsFeature> featuresRegistry =
16 + new ConcurrentHashMap<>();
17 +
18 + /**
19 + * Constructs a component from a name.
20 + *
21 + * @param newName name of the component
22 + */
23 + MetricsComponent(final String newName) {
24 + name = newName;
25 + }
26 +
27 + @Override public String getName() {
28 + return name;
29 + }
30 +
31 + @Override public MetricsFeature registerFeature(final String featureName) {
32 + MetricsFeature feature = featuresRegistry.get(featureName);
33 + if (feature == null) {
34 + final MetricsFeature createdFeature = new MetricsFeature(featureName);
35 + feature = featuresRegistry.putIfAbsent(featureName, createdFeature);
36 + if (feature == null) {
37 + feature = createdFeature;
38 + }
39 + }
40 + return feature;
41 + }
42 +}
1 +package org.onlab.metrics;
2 +
3 +/**
4 + * Registry Entry for Metrics Components.
5 + */
6 +public interface MetricsComponentRegistry {
7 + String getName();
8 +
9 + MetricsFeature registerFeature(String featureName);
10 +}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.