tom

Adding DeviceAdminService facade and tests for SimpleDeviceManager.

1 +package org.onlab.onos.net.device;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +import org.onlab.onos.net.MastershipRole;
5 +
6 +/**
7 + * Service for administering the inventory of infrastructure devices.
8 + */
9 +public interface DeviceAdminService {
10 +
11 + /**
12 + * Applies the current mastership role for the specified device.
13 + *
14 + * @param deviceId device identifier
15 + * @param role requested role
16 + */
17 + void setRole(DeviceId deviceId, MastershipRole role);
18 +
19 + /**
20 + * Removes the device with the specified identifier.
21 + *
22 + * @param deviceId device identifier
23 + */
24 + void removeDevice(DeviceId deviceId);
25 +
26 + // TODO: add ability to administratively suspend/resume device
27 +
28 +}
...@@ -18,6 +18,12 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> { ...@@ -18,6 +18,12 @@ public class DeviceEvent extends AbstractEvent<DeviceEvent.Type, Device> {
18 DEVICE_ADDED, 18 DEVICE_ADDED,
19 19
20 /** 20 /**
21 + * Signifies that some device attributes have changed; excludes
22 + * availability changes.
23 + */
24 + DEVICE_UPDATED,
25 +
26 + /**
21 * Signifies that a device has been removed. 27 * Signifies that a device has been removed.
22 */ 28 */
23 DEVICE_REMOVED, 29 DEVICE_REMOVED,
......
...@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkState; ...@@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkState;
18 public abstract class AbstractProviderRegistry<P extends Provider, S extends ProviderService<P>> 18 public abstract class AbstractProviderRegistry<P extends Provider, S extends ProviderService<P>>
19 implements ProviderRegistry<P, S> { 19 implements ProviderRegistry<P, S> {
20 20
21 + private final Map<ProviderId, P> providers = new HashMap<>();
21 private final Map<ProviderId, S> services = new HashMap<>(); 22 private final Map<ProviderId, S> services = new HashMap<>();
22 23
23 /** 24 /**
...@@ -34,6 +35,7 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -34,6 +35,7 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
34 checkState(!services.containsKey(provider.id()), "Provider %s already registered", provider.id()); 35 checkState(!services.containsKey(provider.id()), "Provider %s already registered", provider.id());
35 S service = createProviderService(provider); 36 S service = createProviderService(provider);
36 services.put(provider.id(), service); 37 services.put(provider.id(), service);
38 + providers.put(provider.id(), provider);
37 return service; 39 return service;
38 } 40 }
39 41
...@@ -44,6 +46,7 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -44,6 +46,7 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
44 if (service != null && service instanceof AbstractProviderService) { 46 if (service != null && service instanceof AbstractProviderService) {
45 ((AbstractProviderService) service).invalidate(); 47 ((AbstractProviderService) service).invalidate();
46 services.remove(provider.id()); 48 services.remove(provider.id());
49 + providers.remove(provider.id());
47 } 50 }
48 } 51 }
49 52
...@@ -52,4 +55,14 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -52,4 +55,14 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
52 return ImmutableSet.copyOf(services.keySet()); 55 return ImmutableSet.copyOf(services.keySet());
53 } 56 }
54 57
58 + /**
59 + * Returns the provider registered with the specified provider ID.
60 + *
61 + * @param providerId provider identifier
62 + * @return provider
63 + */
64 + protected synchronized P getProvider(ProviderId providerId) {
65 + return providers.get(providerId);
66 + }
67 +
55 } 68 }
......
...@@ -13,6 +13,7 @@ import org.onlab.onos.net.DeviceId; ...@@ -13,6 +13,7 @@ import org.onlab.onos.net.DeviceId;
13 import org.onlab.onos.net.MastershipRole; 13 import org.onlab.onos.net.MastershipRole;
14 import org.onlab.onos.net.Port; 14 import org.onlab.onos.net.Port;
15 import org.onlab.onos.net.PortNumber; 15 import org.onlab.onos.net.PortNumber;
16 +import org.onlab.onos.net.device.DeviceAdminService;
16 import org.onlab.onos.net.device.DeviceDescription; 17 import org.onlab.onos.net.device.DeviceDescription;
17 import org.onlab.onos.net.device.DeviceEvent; 18 import org.onlab.onos.net.device.DeviceEvent;
18 import org.onlab.onos.net.device.DeviceListener; 19 import org.onlab.onos.net.device.DeviceListener;
...@@ -37,22 +38,23 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -37,22 +38,23 @@ import static org.slf4j.LoggerFactory.getLogger;
37 @Service 38 @Service
38 public class SimpleDeviceManager 39 public class SimpleDeviceManager
39 extends AbstractProviderRegistry<DeviceProvider, DeviceProviderService> 40 extends AbstractProviderRegistry<DeviceProvider, DeviceProviderService>
40 - implements DeviceService, DeviceProviderRegistry { 41 + implements DeviceService, DeviceAdminService, DeviceProviderRegistry {
41 42
42 - public static final String DEVICE_ID_NULL = "Device ID cannot be null"; 43 + private static final String DEVICE_ID_NULL = "Device ID cannot be null";
43 - public static final String PORT_NUMBER_NULL = "Port number cannot be null"; 44 + private static final String PORT_NUMBER_NULL = "Port number cannot be null";
44 - public static final String DEVICE_DESCRIPTION_NULL = "Device description cannot be null"; 45 + private static final String DEVICE_DESCRIPTION_NULL = "Device description cannot be null";
45 - public static final String PORT_DESCRIPTION_NULL = "Port description cannot be null"; 46 + private static final String PORT_DESCRIPTION_NULL = "Port description cannot be null";
47 + private static final String ROLE_NULL = "Role cannot be null";
46 48
47 private final Logger log = getLogger(getClass()); 49 private final Logger log = getLogger(getClass());
48 50
49 private final AbstractListenerRegistry<DeviceEvent, DeviceListener> 51 private final AbstractListenerRegistry<DeviceEvent, DeviceListener>
50 listenerRegistry = new AbstractListenerRegistry<>(); 52 listenerRegistry = new AbstractListenerRegistry<>();
51 53
52 - private final DeviceStore store = new DeviceStore(); 54 + private final SimpleDeviceStore store = new SimpleDeviceStore();
53 55
54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 - private EventDeliveryService eventDispatcher; 57 + protected EventDeliveryService eventDispatcher;
56 58
57 @Activate 59 @Activate
58 public void activate() { 60 public void activate() {
...@@ -69,12 +71,12 @@ public class SimpleDeviceManager ...@@ -69,12 +71,12 @@ public class SimpleDeviceManager
69 @Override 71 @Override
70 public MastershipRole getRole(DeviceId deviceId) { 72 public MastershipRole getRole(DeviceId deviceId) {
71 checkNotNull(deviceId, DEVICE_ID_NULL); 73 checkNotNull(deviceId, DEVICE_ID_NULL);
72 - return null; 74 + return store.getRole(deviceId);
73 } 75 }
74 76
75 @Override 77 @Override
76 public Iterable<Device> getDevices() { 78 public Iterable<Device> getDevices() {
77 - return null; 79 + return store.getDevices();
78 } 80 }
79 81
80 @Override 82 @Override
...@@ -111,6 +113,28 @@ public class SimpleDeviceManager ...@@ -111,6 +113,28 @@ public class SimpleDeviceManager
111 return new InternalDeviceProviderService(provider); 113 return new InternalDeviceProviderService(provider);
112 } 114 }
113 115
116 + @Override
117 + public void setRole(DeviceId deviceId, MastershipRole newRole) {
118 + checkNotNull(deviceId, DEVICE_ID_NULL);
119 + checkNotNull(newRole, ROLE_NULL);
120 + DeviceEvent event = store.setRole(deviceId, newRole);
121 + if (event != null) {
122 + Device device = event.subject();
123 + DeviceProvider provider = getProvider(device.providerId());
124 + if (provider != null) {
125 + provider.roleChanged(device, newRole);
126 + }
127 + post(event);
128 + }
129 + }
130 +
131 + @Override
132 + public void removeDevice(DeviceId deviceId) {
133 + checkNotNull(deviceId, DEVICE_ID_NULL);
134 + DeviceEvent event = store.removeDevice(deviceId);
135 + post(event);
136 + }
137 +
114 // Personalized device provider service issued to the supplied provider. 138 // Personalized device provider service issued to the supplied provider.
115 private class InternalDeviceProviderService extends AbstractProviderService<DeviceProvider> 139 private class InternalDeviceProviderService extends AbstractProviderService<DeviceProvider>
116 implements DeviceProviderService { 140 implements DeviceProviderService {
...@@ -124,7 +148,8 @@ public class SimpleDeviceManager ...@@ -124,7 +148,8 @@ public class SimpleDeviceManager
124 checkNotNull(deviceId, DEVICE_ID_NULL); 148 checkNotNull(deviceId, DEVICE_ID_NULL);
125 checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL); 149 checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL);
126 log.info("Device {} connected: {}", deviceId, deviceDescription); 150 log.info("Device {} connected: {}", deviceId, deviceDescription);
127 - DeviceEvent event = store.createOrUpdateDevice(deviceId, deviceDescription); 151 + DeviceEvent event = store.createOrUpdateDevice(provider().id(),
152 + deviceId, deviceDescription);
128 post(event); 153 post(event);
129 } 154 }
130 155
...@@ -132,7 +157,7 @@ public class SimpleDeviceManager ...@@ -132,7 +157,7 @@ public class SimpleDeviceManager
132 public void deviceDisconnected(DeviceId deviceId) { 157 public void deviceDisconnected(DeviceId deviceId) {
133 checkNotNull(deviceId, DEVICE_ID_NULL); 158 checkNotNull(deviceId, DEVICE_ID_NULL);
134 log.info("Device {} disconnected", deviceId); 159 log.info("Device {} disconnected", deviceId);
135 - DeviceEvent event = store.removeDevice(deviceId); 160 + DeviceEvent event = store.markOffline(deviceId);
136 post(event); 161 post(event);
137 } 162 }
138 163
......
1 package org.onlab.onos.net.trivial.impl; 1 package org.onlab.onos.net.trivial.impl;
2 2
3 +import org.onlab.onos.net.DefaultDevice;
3 import org.onlab.onos.net.Device; 4 import org.onlab.onos.net.Device;
4 import org.onlab.onos.net.DeviceId; 5 import org.onlab.onos.net.DeviceId;
6 +import org.onlab.onos.net.MastershipRole;
5 import org.onlab.onos.net.Port; 7 import org.onlab.onos.net.Port;
6 import org.onlab.onos.net.PortNumber; 8 import org.onlab.onos.net.PortNumber;
7 import org.onlab.onos.net.device.DeviceDescription; 9 import org.onlab.onos.net.device.DeviceDescription;
8 import org.onlab.onos.net.device.DeviceEvent; 10 import org.onlab.onos.net.device.DeviceEvent;
9 import org.onlab.onos.net.device.PortDescription; 11 import org.onlab.onos.net.device.PortDescription;
12 +import org.onlab.onos.net.provider.ProviderId;
10 13
11 import java.util.ArrayList; 14 import java.util.ArrayList;
15 +import java.util.Collections;
16 +import java.util.HashMap;
17 +import java.util.HashSet;
12 import java.util.List; 18 import java.util.List;
13 import java.util.Map; 19 import java.util.Map;
20 +import java.util.Objects;
21 +import java.util.Set;
14 import java.util.concurrent.ConcurrentHashMap; 22 import java.util.concurrent.ConcurrentHashMap;
15 23
24 +import static com.google.common.base.Preconditions.checkArgument;
25 +import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
26 +import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED;
27 +import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_REMOVED;
28 +
16 /** 29 /**
17 * Manages inventory of infrastructure devices. 30 * Manages inventory of infrastructure devices.
18 */ 31 */
19 -public class DeviceStore { 32 +class SimpleDeviceStore {
33 +
34 + private final Map<DeviceId, DefaultDevice> devices = new ConcurrentHashMap<>();
35 + private final Set<DeviceId> available = new HashSet<>();
36 + private final Map<DeviceId, MastershipRole> roles = new HashMap<>();
37 +
38 + /**
39 + * Returns an iterable collection of all devices known to the system.
40 + *
41 + * @return device collection
42 + */
43 + Iterable<Device> getDevices() {
44 + return Collections.unmodifiableSet(new HashSet<Device>(devices.values()));
45 + }
20 46
21 - private final Map<DeviceId, Device> devices = new ConcurrentHashMap<>(); 47 + /**
48 + * Returns the device with the specified identifier.
49 + *
50 + * @param deviceId device identifier
51 + * @return device
52 + */
53 + Device getDevice(DeviceId deviceId) {
54 + return devices.get(deviceId);
55 + }
22 56
23 /** 57 /**
24 * Creates a new infrastructure device, or updates an existing one using 58 * Creates a new infrastructure device, or updates an existing one using
25 * the supplied device description. 59 * the supplied device description.
26 * 60 *
61 + * @param providerId provider identifier
27 * @param deviceId device identifier 62 * @param deviceId device identifier
28 * @param deviceDescription device description 63 * @param deviceDescription device description
29 * @return ready to send event describing what occurred; null if no change 64 * @return ready to send event describing what occurred; null if no change
30 */ 65 */
31 - public DeviceEvent createOrUpdateDevice(DeviceId deviceId, 66 + DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId,
32 DeviceDescription deviceDescription) { 67 DeviceDescription deviceDescription) {
33 - return null; 68 + DefaultDevice device = devices.get(deviceId);
69 + if (device == null) {
70 + return createDevice(providerId, deviceId, deviceDescription);
71 + }
72 + return updateDevice(providerId, device, deviceDescription);
73 + }
74 +
75 + // Creates the device and returns the appropriate event if necessary.
76 + private DeviceEvent createDevice(ProviderId providerId, DeviceId deviceId,
77 + DeviceDescription desc) {
78 + DefaultDevice device = new DefaultDevice(providerId, deviceId, desc.type(),
79 + desc.manufacturer(),
80 + desc.hwVersion(), desc.swVersion(),
81 + desc.serialNumber());
82 + synchronized (this) {
83 + devices.put(deviceId, device);
84 + available.add(deviceId);
85 + }
86 + return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device);
87 + }
88 +
89 + // Updates the device and returns the appropriate event if necessary.
90 + private DeviceEvent updateDevice(ProviderId providerId, DefaultDevice device,
91 + DeviceDescription desc) {
92 + // We allow only certain attributes to trigger update
93 + if (!Objects.equals(device.hwVersion(), desc.hwVersion()) ||
94 + !Objects.equals(device.swVersion(), desc.swVersion())) {
95 + DefaultDevice updated = new DefaultDevice(providerId, device.id(),
96 + desc.type(),
97 + desc.manufacturer(),
98 + desc.hwVersion(),
99 + desc.swVersion(),
100 + desc.serialNumber());
101 + synchronized (this) {
102 + devices.put(device.id(), updated);
103 + available.add(device.id());
104 + }
105 + return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, device);
106 + }
107 +
108 + // Otherwise merely attempt to change availability
109 + synchronized (this) {
110 + boolean added = available.add(device.id());
111 + return added ? new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device) : null;
112 + }
34 } 113 }
35 114
36 /** 115 /**
...@@ -39,8 +118,13 @@ public class DeviceStore { ...@@ -39,8 +118,13 @@ public class DeviceStore {
39 * @param deviceId device identifier 118 * @param deviceId device identifier
40 * @return ready to send event describing what occurred; null if no change 119 * @return ready to send event describing what occurred; null if no change
41 */ 120 */
42 - public DeviceEvent removeDevice(DeviceId deviceId) { 121 + DeviceEvent markOffline(DeviceId deviceId) {
43 - return null; 122 + synchronized (this) {
123 + Device device = devices.get(deviceId);
124 + checkArgument(device != null, "Device with ID %s is not found", deviceId);
125 + boolean removed = available.remove(deviceId);
126 + return removed ? new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device) : null;
127 + }
44 } 128 }
45 129
46 /** 130 /**
...@@ -51,7 +135,7 @@ public class DeviceStore { ...@@ -51,7 +135,7 @@ public class DeviceStore {
51 * @param portDescriptions list of port descriptions 135 * @param portDescriptions list of port descriptions
52 * @return ready to send events describing what occurred; empty list if no change 136 * @return ready to send events describing what occurred; empty list if no change
53 */ 137 */
54 - public List<DeviceEvent> updatePorts(DeviceId deviceId, 138 + List<DeviceEvent> updatePorts(DeviceId deviceId,
55 List<PortDescription> portDescriptions) { 139 List<PortDescription> portDescriptions) {
56 return new ArrayList<>(); 140 return new ArrayList<>();
57 } 141 }
...@@ -64,39 +148,67 @@ public class DeviceStore { ...@@ -64,39 +148,67 @@ public class DeviceStore {
64 * @param portDescription port description 148 * @param portDescription port description
65 * @return ready to send event describing what occurred; null if no change 149 * @return ready to send event describing what occurred; null if no change
66 */ 150 */
67 - public DeviceEvent updatePortStatus(DeviceId deviceId, 151 + DeviceEvent updatePortStatus(DeviceId deviceId,
68 PortDescription portDescription) { 152 PortDescription portDescription) {
69 return null; 153 return null;
70 } 154 }
71 155
72 /** 156 /**
73 - * Returns the device with the specified identifier. 157 + * Returns the list of ports that belong to the specified device.
74 * 158 *
75 * @param deviceId device identifier 159 * @param deviceId device identifier
76 - * @return device 160 + * @return list of device ports
77 */ 161 */
78 - public Device getDevice(DeviceId deviceId) { 162 + List<Port> getPorts(DeviceId deviceId) {
79 return null; 163 return null;
80 } 164 }
81 165
82 /** 166 /**
83 - * Returns the list of ports that belong to the specified device. 167 + * Returns the specified device port.
84 * 168 *
85 * @param deviceId device identifier 169 * @param deviceId device identifier
86 - * @return list of device ports 170 + * @param portNumber port number
171 + * @return device port
87 */ 172 */
88 - public List<Port> getPorts(DeviceId deviceId) { 173 + Port getPort(DeviceId deviceId, PortNumber portNumber) {
89 return null; 174 return null;
90 } 175 }
91 176
92 /** 177 /**
93 - * Returns the specified device port. 178 + * Returns the mastership role determined for this device.
94 * 179 *
95 * @param deviceId device identifier 180 * @param deviceId device identifier
96 - * @param portNumber port number 181 + * @return mastership role
97 - * @return device port
98 */ 182 */
99 - public Port getPort(DeviceId deviceId, PortNumber portNumber) { 183 + MastershipRole getRole(DeviceId deviceId) {
100 - return null; 184 + MastershipRole role = roles.get(deviceId);
185 + return role != null ? role : MastershipRole.NONE;
186 + }
187 +
188 + /**
189 + * Administratively sets the role of the specified device.
190 + *
191 + * @param deviceId device identifier
192 + * @param role mastership role to apply
193 + * @return mastership role change event or null if no change
194 + */
195 + DeviceEvent setRole(DeviceId deviceId, MastershipRole role) {
196 + Device device = getDevice(deviceId);
197 + checkArgument(device != null, "Device with ID %s not found");
198 + MastershipRole oldRole = roles.put(deviceId, role);
199 + return oldRole == role ? null : new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device);
200 + }
201 +
202 + /**
203 + * Administratively removes the specified device from the store.
204 + *
205 + * @param deviceId device to be removed
206 + */
207 + DeviceEvent removeDevice(DeviceId deviceId) {
208 + synchronized (this) {
209 + roles.remove(deviceId);
210 + Device device = devices.remove(deviceId);
211 + return device != null ? new DeviceEvent(DEVICE_REMOVED, device) : null;
212 + }
101 } 213 }
102 } 214 }
......
1 +package org.onlab.onos.net.trivial.impl;
2 +
3 +import org.junit.After;
4 +import org.junit.Before;
5 +import org.junit.Test;
6 +import org.onlab.onos.event.Event;
7 +import org.onlab.onos.net.Device;
8 +import org.onlab.onos.net.DeviceId;
9 +import org.onlab.onos.net.MastershipRole;
10 +import org.onlab.onos.net.device.DefaultDeviceDescription;
11 +import org.onlab.onos.net.device.DeviceAdminService;
12 +import org.onlab.onos.net.device.DeviceDescription;
13 +import org.onlab.onos.net.device.DeviceEvent;
14 +import org.onlab.onos.net.device.DeviceListener;
15 +import org.onlab.onos.net.device.DeviceProvider;
16 +import org.onlab.onos.net.device.DeviceProviderRegistry;
17 +import org.onlab.onos.net.device.DeviceProviderService;
18 +import org.onlab.onos.net.device.DeviceService;
19 +import org.onlab.onos.net.provider.AbstractProvider;
20 +import org.onlab.onos.net.provider.ProviderId;
21 +
22 +import java.util.ArrayList;
23 +import java.util.Iterator;
24 +import java.util.List;
25 +
26 +import static org.junit.Assert.*;
27 +import static org.onlab.onos.net.Device.Type.SWITCH;
28 +import static org.onlab.onos.net.DeviceId.deviceId;
29 +import static org.onlab.onos.net.device.DeviceEvent.Type.*;
30 +
31 +/**
32 + * Test codifying the device service & device provider service contracts.
33 + */
34 +public class SimpleDeviceManagerTest {
35 +
36 + private static final ProviderId PID = new ProviderId("foo");
37 + private static final DeviceId DID1 = deviceId("of:foo");
38 + private static final DeviceId DID2 = deviceId("of:bar");
39 + private static final String MFR = "whitebox";
40 + private static final String HW = "1.1.x";
41 + private static final String SW1 = "3.8.1";
42 + private static final String SW2 = "3.9.5";
43 + private static final String SN = "43311-12345";
44 +
45 +
46 + private SimpleDeviceManager mgr;
47 +
48 + protected DeviceService service;
49 + protected DeviceAdminService admin;
50 + protected DeviceProviderRegistry registry;
51 + protected DeviceProviderService providerService;
52 + protected TestProvider provider;
53 + protected TestListener listener = new TestListener();
54 +
55 + @Before
56 + public void setUp() {
57 + mgr = new SimpleDeviceManager();
58 + service = mgr;
59 + admin = mgr;
60 + registry = mgr;
61 + mgr.eventDispatcher = new TestEventDispatcher();
62 + mgr.activate();
63 +
64 + service.addListener(listener);
65 +
66 + provider = new TestProvider();
67 + providerService = registry.register(provider);
68 + assertTrue("provider should be registered",
69 + registry.getProviders().contains(provider.id()));
70 + }
71 +
72 + @After
73 + public void tearDown() {
74 + registry.unregister(provider);
75 + assertFalse("provider should not be registered",
76 + registry.getProviders().contains(provider.id()));
77 + service.removeListener(listener);
78 + mgr.deactivate();
79 + }
80 +
81 + private void connectDevice(DeviceId deviceId, String swVersion) {
82 + DeviceDescription description =
83 + new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
84 + HW, swVersion, SN);
85 + providerService.deviceConnected(deviceId, description);
86 + assertNotNull("device should be found", service.getDevice(DID1));
87 + }
88 +
89 + @Test
90 + public void deviceConnected() {
91 + assertNull("device should not be found", service.getDevice(DID1));
92 + connectDevice(DID1, SW1);
93 + validateEvents(DEVICE_ADDED);
94 +
95 + Iterator<Device> it = service.getDevices().iterator();
96 + assertNotNull("one device expected", it.next());
97 + assertFalse("only one device expected", it.hasNext());
98 + }
99 +
100 + @Test
101 + public void deviceDisconnected() {
102 + connectDevice(DID1, SW1);
103 + connectDevice(DID2, SW1);
104 + validateEvents(DEVICE_ADDED, DEVICE_ADDED);
105 +
106 + // Disconnect
107 + providerService.deviceDisconnected(DID1);
108 + assertNotNull("device should not be found", service.getDevice(DID1));
109 + validateEvents(DEVICE_AVAILABILITY_CHANGED);
110 +
111 + // Reconnect
112 + connectDevice(DID1, SW1);
113 + validateEvents(DEVICE_AVAILABILITY_CHANGED);
114 + }
115 +
116 + @Test
117 + public void deviceUpdated() {
118 + connectDevice(DID1, SW1);
119 + validateEvents(DEVICE_ADDED);
120 +
121 + connectDevice(DID1, SW2);
122 + validateEvents(DEVICE_UPDATED);
123 + }
124 +
125 + @Test
126 + public void getRole() {
127 + connectDevice(DID1, SW1);
128 + assertEquals("incorrect role", MastershipRole.NONE, service.getRole(DID1));
129 + }
130 +
131 + @Test
132 + public void setRole() {
133 + connectDevice(DID1, SW1);
134 + admin.setRole(DID1, MastershipRole.MASTER);
135 + validateEvents(DEVICE_ADDED, DEVICE_MASTERSHIP_CHANGED);
136 + assertEquals("incorrect role", MastershipRole.MASTER, service.getRole(DID1));
137 + assertEquals("incorrect device", DID1, provider.deviceReceived.id());
138 + assertEquals("incorrect role", MastershipRole.MASTER, provider.roleReceived);
139 + }
140 +
141 +
142 +
143 + protected void validateEvents(Enum... types) {
144 + int i = 0;
145 + assertEquals("wrong events received", types.length, listener.events.size());
146 + for (Event event : listener.events) {
147 + assertEquals("incorrect event type", types[i], event.type());
148 + i++;
149 + }
150 + listener.events.clear();
151 + }
152 +
153 +
154 + private class TestProvider extends AbstractProvider implements DeviceProvider {
155 + private Device deviceReceived;
156 + private MastershipRole roleReceived;
157 +
158 + public TestProvider() {
159 + super(PID);
160 + }
161 +
162 + @Override
163 + public void triggerProbe(Device device) {
164 + }
165 +
166 + @Override
167 + public void roleChanged(Device device, MastershipRole newRole) {
168 + deviceReceived = device;
169 + roleReceived = newRole;
170 + }
171 + }
172 +
173 + private static class TestListener implements DeviceListener {
174 + final List<DeviceEvent> events = new ArrayList<>();
175 +
176 + @Override
177 + public void event(DeviceEvent event) {
178 + events.add(event);
179 + }
180 + }
181 +
182 +}
1 +package org.onlab.onos.net.trivial.impl;
2 +
3 +import org.onlab.onos.event.DefaultEventSinkRegistry;
4 +import org.onlab.onos.event.Event;
5 +import org.onlab.onos.event.EventDeliveryService;
6 +import org.onlab.onos.event.EventSink;
7 +
8 +import static com.google.common.base.Preconditions.checkState;
9 +
10 +/**
11 + * Implements event delivery system that delivers events synchronously, or
12 + * in-line with the post method invocation.
13 + */
14 +public class TestEventDispatcher extends DefaultEventSinkRegistry
15 + implements EventDeliveryService {
16 +
17 + @Override
18 + public void post(Event event) {
19 + EventSink sink = getSink(event.getClass());
20 + checkState(sink != null, "No sink for event %s", event);
21 + sink.process(event);
22 + }
23 +
24 +}