blob: 7406cf63f494e30ad4ed5ce76d5603b1729ac3ce [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.device.impl;
tome5ec3fd2014-09-04 15:18:06 -070017
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070018import com.google.common.collect.Sets;
tome5ec3fd2014-09-04 15:18:06 -070019import org.junit.After;
20import org.junit.Before;
21import org.junit.Test;
Andrea Campanella4ed15382022-06-29 16:24:00 +020022import org.onlab.osgi.ComponentContextAdapter;
Ray Milkeycc53abd2015-02-19 12:31:33 -080023import org.onlab.packet.ChassisId;
24import org.onlab.packet.IpAddress;
Andrea Campanella4ed15382022-06-29 16:24:00 +020025import org.onosproject.cfg.ComponentConfigAdapter;
Ray Milkeycc53abd2015-02-19 12:31:33 -080026import org.onosproject.cluster.ClusterServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.cluster.ControllerNode;
28import org.onosproject.cluster.DefaultControllerNode;
29import org.onosproject.cluster.NodeId;
Thomas Vachuska36002e62015-05-19 16:12:29 -070030import org.onosproject.common.event.impl.TestEventDispatcher;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070031import org.onosproject.event.Event;
Ray Milkeya4122362015-08-18 15:19:08 -070032import org.onosproject.net.config.NetworkConfigServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.mastership.MastershipServiceAdapter;
34import org.onosproject.mastership.MastershipTerm;
35import org.onosproject.mastership.MastershipTermService;
36import org.onosproject.net.Device;
37import org.onosproject.net.DeviceId;
38import org.onosproject.net.MastershipRole;
39import org.onosproject.net.Port;
40import org.onosproject.net.PortNumber;
41import org.onosproject.net.device.DefaultDeviceDescription;
42import org.onosproject.net.device.DefaultPortDescription;
43import org.onosproject.net.device.DeviceAdminService;
Brian O'Connorabafb502014-12-02 22:26:20 -080044import org.onosproject.net.device.DeviceDescription;
45import org.onosproject.net.device.DeviceEvent;
46import org.onosproject.net.device.DeviceListener;
47import org.onosproject.net.device.DeviceProvider;
48import org.onosproject.net.device.DeviceProviderRegistry;
49import org.onosproject.net.device.DeviceProviderService;
50import org.onosproject.net.device.DeviceService;
51import org.onosproject.net.device.PortDescription;
52import org.onosproject.net.provider.AbstractProvider;
53import org.onosproject.net.provider.ProviderId;
Jonghwan Hyun6ecf56d2017-08-01 16:07:44 -070054import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
Thomas Vachuskac97aa612015-06-23 16:00:18 -070055import org.onosproject.store.trivial.SimpleDeviceStore;
tome5ec3fd2014-09-04 15:18:06 -070056
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070057import java.util.ArrayList;
58import java.util.Iterator;
59import java.util.List;
60import java.util.Set;
61import java.util.concurrent.CompletableFuture;
tome5ec3fd2014-09-04 15:18:06 -070062
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070063import static org.junit.Assert.*;
Brian O'Connorabafb502014-12-02 22:26:20 -080064import static org.onosproject.net.Device.Type.SWITCH;
65import static org.onosproject.net.DeviceId.deviceId;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070066import static org.onosproject.net.NetTestTools.injectEventDispatcher;
67import static org.onosproject.net.device.DeviceEvent.Type.*;
tome5ec3fd2014-09-04 15:18:06 -070068
69/**
70 * Test codifying the device service & device provider service contracts.
71 */
tom41a2c5f2014-09-19 09:20:35 -070072public class DeviceManagerTest {
tome5ec3fd2014-09-04 15:18:06 -070073
tom7e02cda2014-09-18 12:05:46 -070074 private static final ProviderId PID = new ProviderId("of", "foo");
tome5ec3fd2014-09-04 15:18:06 -070075 private static final DeviceId DID1 = deviceId("of:foo");
76 private static final DeviceId DID2 = deviceId("of:bar");
77 private static final String MFR = "whitebox";
78 private static final String HW = "1.1.x";
79 private static final String SW1 = "3.8.1";
80 private static final String SW2 = "3.9.5";
81 private static final String SN = "43311-12345";
alshabib7911a052014-10-16 17:49:37 -070082 private static final ChassisId CID = new ChassisId();
tome5ec3fd2014-09-04 15:18:06 -070083
tom24c55cd2014-09-06 10:47:25 -070084 private static final PortNumber P1 = PortNumber.portNumber(1);
85 private static final PortNumber P2 = PortNumber.portNumber(2);
86 private static final PortNumber P3 = PortNumber.portNumber(3);
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -070087 private static final NodeId NID_LOCAL = new NodeId("local");
Pavlin Radoslavov444b5192014-10-28 10:45:19 -070088 private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1");
tom24c55cd2014-09-06 10:47:25 -070089
tom41a2c5f2014-09-19 09:20:35 -070090 private DeviceManager mgr;
tome5ec3fd2014-09-04 15:18:06 -070091
92 protected DeviceService service;
93 protected DeviceAdminService admin;
94 protected DeviceProviderRegistry registry;
95 protected DeviceProviderService providerService;
96 protected TestProvider provider;
97 protected TestListener listener = new TestListener();
98
99 @Before
100 public void setUp() {
tom41a2c5f2014-09-19 09:20:35 -0700101 mgr = new DeviceManager();
tome5ec3fd2014-09-04 15:18:06 -0700102 service = mgr;
103 admin = mgr;
104 registry = mgr;
Andrea Campanella4ed15382022-06-29 16:24:00 +0200105 mgr.cfgService = new ComponentConfigAdapter();
tom41a2c5f2014-09-19 09:20:35 -0700106 mgr.store = new SimpleDeviceStore();
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700107 injectEventDispatcher(mgr, new TestEventDispatcher());
Yuta HIGUCHIbcac4992014-11-22 19:27:57 -0800108 TestMastershipManager mastershipManager = new TestMastershipManager();
109 mgr.mastershipService = mastershipManager;
110 mgr.termService = mastershipManager;
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700111 mgr.clusterService = new TestClusterService();
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700112 mgr.networkConfigService = new TestNetworkConfigService();
Jonghwan Hyun6ecf56d2017-08-01 16:07:44 -0700113 mgr.communicationService = new TestClusterCommunicationService();
Andrea Campanella4ed15382022-06-29 16:24:00 +0200114 mgr.activate(new ComponentContextAdapter());
tome5ec3fd2014-09-04 15:18:06 -0700115
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700116
tome5ec3fd2014-09-04 15:18:06 -0700117 service.addListener(listener);
118
119 provider = new TestProvider();
120 providerService = registry.register(provider);
121 assertTrue("provider should be registered",
122 registry.getProviders().contains(provider.id()));
123 }
124
125 @After
126 public void tearDown() {
127 registry.unregister(provider);
128 assertFalse("provider should not be registered",
129 registry.getProviders().contains(provider.id()));
130 service.removeListener(listener);
Andrea Campanella4ed15382022-06-29 16:24:00 +0200131 mgr.deactivate(new ComponentContextAdapter());
tome5ec3fd2014-09-04 15:18:06 -0700132 }
133
134 private void connectDevice(DeviceId deviceId, String swVersion) {
135 DeviceDescription description =
136 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
alshabib7911a052014-10-16 17:49:37 -0700137 HW, swVersion, SN, CID);
tome5ec3fd2014-09-04 15:18:06 -0700138 providerService.deviceConnected(deviceId, description);
139 assertNotNull("device should be found", service.getDevice(DID1));
140 }
141
142 @Test
143 public void deviceConnected() {
144 assertNull("device should not be found", service.getDevice(DID1));
145 connectDevice(DID1, SW1);
146 validateEvents(DEVICE_ADDED);
147
148 Iterator<Device> it = service.getDevices().iterator();
149 assertNotNull("one device expected", it.next());
150 assertFalse("only one device expected", it.hasNext());
tomad2d2092014-09-06 23:24:20 -0700151 assertEquals("incorrect device count", 1, service.getDeviceCount());
mskala32000d32017-07-14 16:27:06 +0200152 assertEquals("incorrect available device count", 1, service.getAvailableDeviceCount());
tomff7eb7c2014-09-08 12:49:03 -0700153 assertTrue("device should be available", service.isAvailable(DID1));
tome5ec3fd2014-09-04 15:18:06 -0700154 }
155
156 @Test
157 public void deviceDisconnected() {
158 connectDevice(DID1, SW1);
159 connectDevice(DID2, SW1);
160 validateEvents(DEVICE_ADDED, DEVICE_ADDED);
tomff7eb7c2014-09-08 12:49:03 -0700161 assertTrue("device should be available", service.isAvailable(DID1));
tome5ec3fd2014-09-04 15:18:06 -0700162
163 // Disconnect
164 providerService.deviceDisconnected(DID1);
165 assertNotNull("device should not be found", service.getDevice(DID1));
tomff7eb7c2014-09-08 12:49:03 -0700166 assertFalse("device should not be available", service.isAvailable(DID1));
tome5ec3fd2014-09-04 15:18:06 -0700167 validateEvents(DEVICE_AVAILABILITY_CHANGED);
168
169 // Reconnect
170 connectDevice(DID1, SW1);
171 validateEvents(DEVICE_AVAILABILITY_CHANGED);
tomad2d2092014-09-06 23:24:20 -0700172
173 assertEquals("incorrect device count", 2, service.getDeviceCount());
mskala32000d32017-07-14 16:27:06 +0200174 assertEquals("incorrect available device count", 2, service.getAvailableDeviceCount());
tome5ec3fd2014-09-04 15:18:06 -0700175 }
176
177 @Test
178 public void deviceUpdated() {
179 connectDevice(DID1, SW1);
180 validateEvents(DEVICE_ADDED);
181
182 connectDevice(DID1, SW2);
183 validateEvents(DEVICE_UPDATED);
184 }
185
186 @Test
187 public void getRole() {
188 connectDevice(DID1, SW1);
tom80c0e5e2014-09-08 18:08:58 -0700189 assertEquals("incorrect role", MastershipRole.MASTER, service.getRole(DID1));
tome5ec3fd2014-09-04 15:18:06 -0700190 }
191
tom24c55cd2014-09-06 10:47:25 -0700192 @Test
193 public void updatePorts() {
194 connectDevice(DID1, SW1);
195 List<PortDescription> pds = new ArrayList<>();
Yuta HIGUCHI53e47962018-03-01 23:50:48 -0800196 pds.add(DefaultPortDescription.builder().withPortNumber(P1).isEnabled(true).build());
197 pds.add(DefaultPortDescription.builder().withPortNumber(P2).isEnabled(true).build());
198 pds.add(DefaultPortDescription.builder().withPortNumber(P3).isEnabled(true).build());
tom24c55cd2014-09-06 10:47:25 -0700199 providerService.updatePorts(DID1, pds);
200 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED, PORT_ADDED);
201 pds.clear();
tome5ec3fd2014-09-04 15:18:06 -0700202
Yuta HIGUCHI53e47962018-03-01 23:50:48 -0800203 pds.add(DefaultPortDescription.builder().withPortNumber(P1).isEnabled(false).build());
204 pds.add(DefaultPortDescription.builder().withPortNumber(P3).isEnabled(true).build());
tom24c55cd2014-09-06 10:47:25 -0700205 providerService.updatePorts(DID1, pds);
206 validateEvents(PORT_UPDATED, PORT_REMOVED);
207 }
208
209 @Test
210 public void updatePortStatus() {
211 connectDevice(DID1, SW1);
212 List<PortDescription> pds = new ArrayList<>();
Yuta HIGUCHI53e47962018-03-01 23:50:48 -0800213 pds.add(DefaultPortDescription.builder().withPortNumber(P1).isEnabled(true).build());
214 pds.add(DefaultPortDescription.builder().withPortNumber(P2).isEnabled(true).build());
tom24c55cd2014-09-06 10:47:25 -0700215 providerService.updatePorts(DID1, pds);
216 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED);
217
Yuta HIGUCHI53e47962018-03-01 23:50:48 -0800218 providerService.portStatusChanged(DID1, DefaultPortDescription.builder()
219 .withPortNumber(P1).isEnabled(false).build());
tom24c55cd2014-09-06 10:47:25 -0700220 validateEvents(PORT_UPDATED);
Yuta HIGUCHI53e47962018-03-01 23:50:48 -0800221 providerService.portStatusChanged(DID1, DefaultPortDescription.builder()
222 .withPortNumber(P1).isEnabled(false).build());
tom24c55cd2014-09-06 10:47:25 -0700223 assertTrue("no events expected", listener.events.isEmpty());
224 }
225
226 @Test
227 public void getPorts() {
228 connectDevice(DID1, SW1);
229 List<PortDescription> pds = new ArrayList<>();
Yuta HIGUCHI53e47962018-03-01 23:50:48 -0800230 pds.add(DefaultPortDescription.builder().withPortNumber(P1).isEnabled(true).build());
231 pds.add(DefaultPortDescription.builder().withPortNumber(P2).isEnabled(true).build());
tom24c55cd2014-09-06 10:47:25 -0700232 providerService.updatePorts(DID1, pds);
233 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED);
234 assertEquals("wrong port count", 2, service.getPorts(DID1).size());
235
236 Port port = service.getPort(DID1, P1);
mskala32000d32017-07-14 16:27:06 +0200237 assertEquals("incorrect port", P1, port.number());
238 assertEquals("incorrect state", true, port.isEnabled());
tom24c55cd2014-09-06 10:47:25 -0700239 }
240
241 @Test
242 public void removeDevice() {
243 connectDevice(DID1, SW1);
244 connectDevice(DID2, SW2);
tomad2d2092014-09-06 23:24:20 -0700245 assertEquals("incorrect device count", 2, service.getDeviceCount());
mskala32000d32017-07-14 16:27:06 +0200246 assertEquals("incorrect available device count", 2, service.getAvailableDeviceCount());
tom24c55cd2014-09-06 10:47:25 -0700247 admin.removeDevice(DID1);
248 assertNull("device should not be found", service.getDevice(DID1));
249 assertNotNull("device should be found", service.getDevice(DID2));
tomad2d2092014-09-06 23:24:20 -0700250 assertEquals("incorrect device count", 1, service.getDeviceCount());
mskala32000d32017-07-14 16:27:06 +0200251 assertEquals("incorrect available device count", 1, service.getAvailableDeviceCount());
Thomas Vachuska811ea2b2020-02-11 10:20:10 -0800252 }
tomad2d2092014-09-06 23:24:20 -0700253
Thomas Vachuska811ea2b2020-02-11 10:20:10 -0800254 @Test
255 public void removeDevicePorts() {
256 connectDevice(DID1, SW1);
257 List<PortDescription> pds = new ArrayList<>();
258 pds.add(DefaultPortDescription.builder().withPortNumber(P1).isEnabled(true).build());
259 pds.add(DefaultPortDescription.builder().withPortNumber(P2).isEnabled(true).build());
260 pds.add(DefaultPortDescription.builder().withPortNumber(P3).isEnabled(true).build());
261 providerService.updatePorts(DID1, pds);
262 validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED, PORT_ADDED);
263
264 // Try removing ports while device is available/connected; it should be a no-op.
265 admin.removeDevicePorts(DID1);
266 assertEquals("wrong port count", 3, service.getPorts(DID1).size());
267
268 // Disconnect device
269 providerService.deviceDisconnected(DID1);
270 assertFalse("device should not be available", service.isAvailable(DID1));
271 validateEvents(DEVICE_AVAILABILITY_CHANGED);
272
273 // Now remove ports for real
274 admin.removeDevicePorts(DID1);
275 validateEvents(PORT_REMOVED, PORT_REMOVED, PORT_REMOVED);
276 assertEquals("wrong port count", 0, service.getPorts(DID1).size());
tom24c55cd2014-09-06 10:47:25 -0700277 }
tome5ec3fd2014-09-04 15:18:06 -0700278
279 protected void validateEvents(Enum... types) {
280 int i = 0;
281 assertEquals("wrong events received", types.length, listener.events.size());
282 for (Event event : listener.events) {
283 assertEquals("incorrect event type", types[i], event.type());
284 i++;
285 }
286 listener.events.clear();
287 }
288
289
290 private class TestProvider extends AbstractProvider implements DeviceProvider {
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700291 private DeviceId deviceReceived;
tome5ec3fd2014-09-04 15:18:06 -0700292 private MastershipRole roleReceived;
293
294 public TestProvider() {
295 super(PID);
296 }
297
298 @Override
Ayaka Koshibe78bcbc12014-11-19 14:28:58 -0800299 public void triggerProbe(DeviceId deviceId) {
tome5ec3fd2014-09-04 15:18:06 -0700300 }
301
302 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700303 public void roleChanged(DeviceId device, MastershipRole newRole) {
tome5ec3fd2014-09-04 15:18:06 -0700304 deviceReceived = device;
305 roleReceived = newRole;
306 }
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700307
308 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700309 public boolean isReachable(DeviceId device) {
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700310 return false;
311 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700312
313 @Override
314 public void changePortState(DeviceId deviceId, PortNumber portNumber,
315 boolean enable) {
316 }
tome5ec3fd2014-09-04 15:18:06 -0700317 }
318
319 private static class TestListener implements DeviceListener {
320 final List<DeviceEvent> events = new ArrayList<>();
321
322 @Override
323 public void event(DeviceEvent event) {
324 events.add(event);
325 }
326 }
327
Yuta HIGUCHIbcac4992014-11-22 19:27:57 -0800328 private static class TestMastershipManager
329 extends MastershipServiceAdapter implements MastershipTermService {
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700330 @Override
tomb41d1ac2014-09-24 01:51:24 -0700331 public MastershipRole getLocalRole(DeviceId deviceId) {
332 return MastershipRole.MASTER;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700333 }
334
335 @Override
336 public Set<DeviceId> getDevicesOf(NodeId nodeId) {
337 return Sets.newHashSet(DID1, DID2);
338 }
339
340 @Override
Madan Jampanide003d92015-05-11 17:14:20 -0700341 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
342 return CompletableFuture.completedFuture(MastershipRole.MASTER);
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700343 }
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700344
345 @Override
Madan Jampanic6e574f2015-05-29 13:41:52 -0700346 public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
347 return CompletableFuture.completedFuture(null);
348 }
349
350 @Override
Yuta HIGUCHIbcac4992014-11-22 19:27:57 -0800351 public MastershipTerm getMastershipTerm(DeviceId deviceId) {
352 // FIXME: just returning something not null
353 return MastershipTerm.of(NID_LOCAL, 1);
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700354 }
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700355 }
356
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700357 // code clone
Ray Milkeycc53abd2015-02-19 12:31:33 -0800358 private final class TestClusterService extends ClusterServiceAdapter {
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700359
360 ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST);
361
362 @Override
363 public ControllerNode getLocalNode() {
364 return local;
365 }
366
pierventrea291aaf2022-01-03 17:19:24 +0100367 @Override
368 public ControllerNode.State getState(NodeId nodeId) {
369 return ControllerNode.State.READY;
370 }
371
Yuta HIGUCHI33faeaf2014-10-07 18:19:44 -0700372 }
373
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700374 private class TestNetworkConfigService extends NetworkConfigServiceAdapter {
375 }
Jonghwan Hyun6ecf56d2017-08-01 16:07:44 -0700376
377 private class TestClusterCommunicationService extends ClusterCommunicationServiceAdapter {
378 }
tome5ec3fd2014-09-04 15:18:06 -0700379}