Device config synchronizer
- initial sketch of Device Config Synchronizer outline (ONOS-6745)
Change-Id: I57c8ab6c3511f12c15e3501aa61498eb18264b27
diff --git a/apps/configsync/src/test/java/org/onosproject/d/config/sync/impl/DynamicDeviceConfigSynchronizerTest.java b/apps/configsync/src/test/java/org/onosproject/d/config/sync/impl/DynamicDeviceConfigSynchronizerTest.java
new file mode 100644
index 0000000..78812fb
--- /dev/null
+++ b/apps/configsync/src/test/java/org/onosproject/d/config/sync/impl/DynamicDeviceConfigSynchronizerTest.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.d.config.sync.impl;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.config.DynamicConfigEvent;
+import org.onosproject.config.DynamicConfigServiceAdapter;
+import org.onosproject.config.Filter;
+import org.onosproject.d.config.DeviceResourceIds;
+import org.onosproject.d.config.ResourceIds;
+import org.onosproject.d.config.sync.DeviceConfigSynchronizationProvider;
+import org.onosproject.d.config.sync.operation.SetRequest;
+import org.onosproject.d.config.sync.operation.SetRequest.Change;
+import org.onosproject.d.config.sync.operation.SetRequest.Change.Operation;
+import org.onosproject.d.config.sync.operation.SetResponse;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.NetworkConfigServiceAdapter;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.InnerNode;
+import org.onosproject.yang.model.LeafNode;
+import org.onosproject.yang.model.ResourceId;
+
+import com.google.common.collect.Iterables;
+
+public class DynamicDeviceConfigSynchronizerTest {
+
+ static final String TEST_NS = "testNS";
+
+ static final ResourceId REL_INTERFACES = ResourceId.builder()
+ .addBranchPointSchema("interfaces", TEST_NS)
+ .build();
+
+ static final DeviceId DID = DeviceId.deviceId("test:device1");
+
+ DynamicDeviceConfigSynchronizer sut;
+
+ TestDynamicConfigService dyConService;
+
+ CountDownLatch providerCalled = new CountDownLatch(1);
+
+ BiFunction<ResourceId, Filter, DataNode> onDcsRead;
+
+ BiFunction<DeviceId, SetRequest, CompletableFuture<SetResponse>> onSetConfiguration;
+
+ @Before
+ public void setUp() throws Exception {
+
+ sut = new DynamicDeviceConfigSynchronizer();
+ dyConService = new TestDynamicConfigService();
+ sut.dynConfigService = dyConService;
+ sut.netcfgService = new NetworkConfigServiceAdapter();
+
+ sut.activate();
+
+ sut.register(new MockDeviceConfigSynchronizerProvider());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ sut.deactivate();
+ }
+
+ @Test
+ public void testDispatchRequest() throws Exception {
+
+ ResourceId devicePath = DeviceResourceIds.toResourceId(DID);
+ ResourceId cfgPath = REL_INTERFACES;
+ ResourceId absPath = ResourceIds.concat(devicePath, cfgPath);
+ DynamicConfigEvent event = new DynamicConfigEvent(DynamicConfigEvent.Type.NODE_REPLACED, absPath);
+
+ // assertions
+ onDcsRead = (path, filter) -> {
+ assertTrue(filter.isEmptyFilter());
+ assertEquals("DCS get access by absolute RID", absPath, path);
+ return deviceConfigNode();
+ };
+
+ onSetConfiguration = (deviceId, request) -> {
+ assertEquals(DID, deviceId);
+ assertEquals(1, request.changes().size());
+ Change change = Iterables.get(request.changes(), 0);
+ assertEquals("Provider get access by rel RID", REL_INTERFACES, change.path());
+ assertEquals(Operation.REPLACE, change.op());
+ assertEquals("interfaces", change.val().key().schemaId().name());
+ // walk and test children if it adds value
+
+ providerCalled.countDown();
+ return CompletableFuture.completedFuture(SetResponse.ok(request));
+ };
+
+ // start test run
+
+ // imitate event from DCS
+ dyConService.postEvent(event);
+
+ // assert that it reached the provider
+ providerCalled.await(5, TimeUnit.HOURS);
+ }
+
+ /**
+ * DataNode for testing.
+ *
+ * <pre>
+ * +-interfaces
+ * |
+ * +- interface{intf-name="en0"}
+ * |
+ * +- speed = "10G"
+ * +- state = "up"
+ *
+ * </pre>
+ * @return DataNode
+ */
+ private DataNode deviceConfigNode() {
+ InnerNode.Builder intfs = InnerNode.builder("interfaces", TEST_NS);
+ intfs.type(DataNode.Type.SINGLE_INSTANCE_NODE);
+ InnerNode.Builder intf = intfs.createChildBuilder("interface", TEST_NS);
+ intf.type(DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE);
+ intf.addKeyLeaf("name", TEST_NS, "Ethernet0/0");
+ LeafNode.Builder speed = intf.createChildBuilder("mtu", TEST_NS, "1500");
+ speed.type(DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE);
+
+ intf.addNode(speed.build());
+ intfs.addNode(intf.build());
+ return intfs.build();
+ }
+
+ private class TestDynamicConfigService extends DynamicConfigServiceAdapter {
+
+ public void postEvent(DynamicConfigEvent event) {
+ listenerRegistry.process(event);
+ }
+
+ @Override
+ public DataNode readNode(ResourceId path, Filter filter) {
+ return onDcsRead.apply(path, filter);
+ }
+ }
+
+ private class MockDeviceConfigSynchronizerProvider
+ implements DeviceConfigSynchronizationProvider {
+
+ @Override
+ public ProviderId id() {
+ return new ProviderId(DID.uri().getScheme(), "test-provider");
+ }
+
+ @Override
+ public CompletableFuture<SetResponse> setConfiguration(DeviceId deviceId,
+ SetRequest request) {
+ return onSetConfiguration.apply(deviceId, request);
+ }
+ }
+
+}