Adding DeviceAdminService facade and tests for SimpleDeviceManager.
Showing
7 changed files
with
420 additions
and
30 deletions
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 | } | ... | ... |
net/core/trivial/src/test/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManagerTest.java
0 → 100644
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 | +} |
-
Please register or login to post a comment