Updating CassiniDriver according to testing with IPI

Change-Id: Ia183f0a9ef432909aafa5480ee5b740425aa1832
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/OpticalModulationCommand.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/OpticalModulationCommand.java
index 78c5ec2..257ea11 100644
--- a/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/OpticalModulationCommand.java
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/OpticalModulationCommand.java
@@ -22,6 +22,7 @@
 import org.apache.karaf.shell.api.action.Completion;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.net.NetconfOperationCompleter;
 import org.onosproject.cli.net.OpticalConnectPointCompleter;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Device;
@@ -48,8 +49,9 @@
 
     private static final Logger log = getLogger(OpticalModulationCommand.class);
 
-    @Argument(index = 0, name = "-s", description = "set modulation",
+    @Argument(index = 0, name = "operation", description = "set modulation",
             required = true, multiValued = false)
+    @Completion(NetconfOperationCompleter.class)
     private String operation = null;
 
     @Argument(index = 1, name = "connection point", description = "{DeviceID}/{PortNumber}",
@@ -57,9 +59,9 @@
     @Completion(OpticalConnectPointCompleter.class)
     private String connectPoint = null;
 
-    @Argument(index = 2, name = "value", description = "bit rate value in bps, e.g. 100FlowRu = 100GBps",
+    @Argument(index = 2, name = "value", description = "example: dp_qpsk, dp_8qam, dp_16qam",
             required = false, multiValued = false)
-    private Long value = null;
+    private String value = null;
 
     @Override
     protected void doExecute() throws Exception {
@@ -78,25 +80,37 @@
             return;
         }
         Device device = deviceService.getDevice(cp.deviceId());
-        ModulationConfig<Object> modulationConfig = device.as(ModulationConfig.class);
-        // FIXME the parameter "component" equals NULL now, because there is one-to-one mapping between
-        //  <component> and <optical-channel>.
-        if (operation == null) {
-            Direction component = Direction.ALL;
-            Optional<ModulationScheme> scheme = modulationConfig.getModulationScheme(cp.port(), component);
-            if (scheme.isPresent()) {
-                print("The modulation value in port %s on device %s is %s.",
-                        cp.port().toString(), cp.deviceId().toString(), scheme.get().name());
-            } else {
-                print("Can't get modulation for port %s on device %s.",
+        if (device.is(ModulationConfig.class)) {
+            ModulationConfig<Object> modulationConfig = device.as(ModulationConfig.class);
+            // FIXME the parameter "component" equals NULL now, because there is one-to-one mapping between
+            //  <component> and <optical-channel>.
+            if (operation.equals("get")) {
+                Direction component = Direction.ALL;
+                Optional<ModulationScheme> scheme = modulationConfig.getModulationScheme(cp.port(), component);
+                if (scheme.isPresent()) {
+                    print("The modulation value in port %s on device %s is %s.",
+                            cp.port().toString(), cp.deviceId().toString(), scheme.get().name());
+                } else {
+                    print("Can't get modulation for port %s on device %s.",
+                            cp.port().toString(), cp.deviceId().toString());
+                }
+            } else if (operation.equals("edit-config")) {
+                long bitRate = 0;
+                if (value.equalsIgnoreCase(ModulationScheme.DP_QPSK.name())) {
+                    bitRate = 100;
+                } else {
+                    bitRate = 200;
+                }
+                checkNotNull(value);
+                Direction component = Direction.ALL;
+                modulationConfig.setModulationScheme(cp.port(), component, bitRate);
+                print("Set modulation for " + value + " for port %s on device %s.",
                         cp.port().toString(), cp.deviceId().toString());
+            } else {
+                log.warn("Operation {} are not supported now.", operation);
             }
-        } else if (operation.equals("-s")) {
-            checkNotNull(value);
-            Direction component = Direction.ALL;
-            modulationConfig.setModulationScheme(cp.port(), component, value);
         } else {
-            log.warn("Operation {} are not supported now.", operation);
+            print("Device is not capable of handling modulation");
         }
     }
 }
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortAvailableWaveLengthCommand.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortAvailableWaveLengthCommand.java
new file mode 100644
index 0000000..b53644d
--- /dev/null
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortAvailableWaveLengthCommand.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2019-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.net.optical.cli;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.net.OpticalConnectPointCompleter;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.behaviour.LambdaQuery;
+import org.onosproject.net.device.DeviceService;
+
+/**
+ * Lists all the available wavelengths (lambdas) for a given port.
+ */
+@Service
+@Command(scope = "onos", name = "available-wavelength",
+        description = "Lists all the available wavelengths for a given port")
+public class PortAvailableWaveLengthCommand extends AbstractShellCommand {
+
+    private static final String FMT =
+            "signal=%s, central-frequency=%f";
+
+    @Argument(index = 0, name = "connectPoint",
+            description = "Device/Port Description",
+            required = true, multiValued = false)
+    @Completion(OpticalConnectPointCompleter.class)
+    String connectPointString = "";
+
+
+    @Override
+    protected void doExecute() throws Exception {
+        DeviceService deviceService = get(DeviceService.class);
+        ConnectPoint cp = ConnectPoint.deviceConnectPoint(connectPointString);
+
+        Device d = deviceService.getDevice(cp.deviceId());
+        if (d.is(LambdaQuery.class)) {
+            LambdaQuery lambdaQuery = d.as(LambdaQuery.class);
+            lambdaQuery.queryLambdas(cp.port()).forEach(lambda -> {
+                print(FMT, lambda.toString(), lambda.centralFrequency().asGHz());
+            });
+
+        } else {
+            print("Device is not capable of querying lambdas");
+        }
+
+    }
+}
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortWaveLengthCommand.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortWaveLengthCommand.java
index df66587..9f50458 100644
--- a/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortWaveLengthCommand.java
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/cli/PortWaveLengthCommand.java
@@ -15,7 +15,6 @@
  */
 
 
-
 package org.onosproject.net.optical.cli;
 
 import com.google.common.collect.ImmutableMap;
@@ -24,22 +23,23 @@
 import org.apache.karaf.shell.api.action.Completion;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
 import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cli.net.NetconfOperationCompleter;
 import org.onosproject.cli.net.OpticalConnectPointCompleter;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.net.ChannelSpacing;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
 import org.onosproject.net.GridType;
 import org.onosproject.net.OchSignal;
-import org.onosproject.net.ChannelSpacing;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.Device;
 import org.onosproject.net.flow.instructions.Instructions;
 
 import java.util.Map;
@@ -51,7 +51,7 @@
  * Enable the optical channel and tune the wavelength via a flow rule based on a given Signal.
  */
 @Service
-@Command(scope = "onos", name = "port-wavelength",
+@Command(scope = "onos", name = "wavelength-config",
         description = "Enable the optical channel and tune the wavelength via a flow rule ")
 public class PortWaveLengthCommand extends AbstractShellCommand {
 
@@ -72,15 +72,19 @@
             .put(CH_50, ChannelSpacing.CHL_50GHZ)
             .put(CH_100, ChannelSpacing.CHL_100GHZ)
             .build();
+    @Argument(index = 0, name = "operation", description = "Netconf Operation including get, edit-config, etc.",
+            required = true, multiValued = false)
+    @Completion(NetconfOperationCompleter.class)
+    private String operation = null;
 
-    @Argument(index = 0, name = "connectPoint",
+    @Argument(index = 1, name = "connectPoint",
             description = "Device/Port Description",
             required = true, multiValued = false)
     @Completion(OpticalConnectPointCompleter.class)
     String connectPointString = "";
 
 
-    @Argument(index = 1, name = "signal",
+    @Argument(index = 2, name = "signal",
             description = "Optical Signal. Format = " + SIGNAL_FORMAT,
             required = true, multiValued = false)
     String signal = "";
@@ -116,38 +120,44 @@
 
     @Override
     protected void doExecute() throws Exception {
-        FlowRuleService flowService = get(FlowRuleService.class);
-        DeviceService deviceService = get(DeviceService.class);
-        CoreService coreService = get(CoreService.class);
-        ConnectPoint cp = ConnectPoint.deviceConnectPoint(connectPointString);
+        if (operation.equals("edit-config")) {
+            FlowRuleService flowService = get(FlowRuleService.class);
+            DeviceService deviceService = get(DeviceService.class);
+            CoreService coreService = get(CoreService.class);
+            ConnectPoint cp = ConnectPoint.deviceConnectPoint(connectPointString);
 
-        TrafficSelector.Builder trafficSelectorBuilder = DefaultTrafficSelector.builder();
-        TrafficTreatment.Builder trafficTreatmentBuilder = DefaultTrafficTreatment.builder();
-        FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
+            TrafficSelector.Builder trafficSelectorBuilder = DefaultTrafficSelector.builder();
+            TrafficTreatment.Builder trafficTreatmentBuilder = DefaultTrafficTreatment.builder();
+            FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
 
 
-        // an empty traffic selector
-        TrafficSelector trafficSelector = trafficSelectorBuilder.matchInPort(cp.port()).build();
-        OchSignal ochSignal = createOchSignal();
+            // an empty traffic selector
+            TrafficSelector trafficSelector = trafficSelectorBuilder.matchInPort(cp.port()).build();
+            OchSignal ochSignal = createOchSignal();
 
-        TrafficTreatment trafficTreatment = trafficTreatmentBuilder
-                .add(Instructions.modL0Lambda(ochSignal))
-                .add(Instructions.createOutput(deviceService.getPort(cp).number()))
-                .build();
+            TrafficTreatment trafficTreatment = trafficTreatmentBuilder
+                    .add(Instructions.modL0Lambda(ochSignal))
+                    .add(Instructions.createOutput(deviceService.getPort(cp).number()))
+                    .build();
 
-        Device device = deviceService.getDevice(cp.deviceId());
-        int priority = 100;
-        ApplicationId appId = coreService.registerApplication("org.onosproject.optical-model");
-        log.info(appId.name());
-        FlowRule addFlow = flowRuleBuilder
-                .withPriority(priority)
-                .fromApp(appId)
-                .withTreatment(trafficTreatment)
-                .withSelector(trafficSelector)
-                .forDevice(device.id())
-                .makePermanent()
-                .build();
-        flowService.applyFlowRules(addFlow);
+            Device device = deviceService.getDevice(cp.deviceId());
+            int priority = 100;
+            ApplicationId appId = coreService.registerApplication("org.onosproject.optical-model");
+            log.info(appId.name());
+            FlowRule addFlow = flowRuleBuilder
+                    .withPriority(priority)
+                    .fromApp(appId)
+                    .withTreatment(trafficTreatment)
+                    .withSelector(trafficSelector)
+                    .forDevice(device.id())
+                    .makePermanent()
+                    .build();
+            flowService.applyFlowRules(addFlow);
+            String msg = String.format("Setting wavelength %s", ochSignal.centralFrequency().asGHz());
+            print(msg);
+        } else {
+            print("Operation %s are not supported now.", operation);
+        }
 
     }
 }
diff --git a/cli/src/main/java/org/onosproject/cli/net/PowerConfigCommand.java b/cli/src/main/java/org/onosproject/cli/net/PowerConfigCommand.java
index c85d0ea..0ef23a2 100644
--- a/cli/src/main/java/org/onosproject/cli/net/PowerConfigCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/PowerConfigCommand.java
@@ -88,8 +88,9 @@
         } else if (operation.equals("edit-config")) {
             checkNotNull(value);
             powerConfig.setTargetPower(cp.port(), Direction.ALL, value);
+            print("Set %s power on port", value, connectPoint);
         } else {
-            log.warn("Operation {} are not supported now.", operation);
+            print("Operation %s are not supported now.", operation);
         }
     }
 }
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniFlowRuleProgrammable.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniFlowRuleProgrammable.java
index fee9499..db46d8d 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniFlowRuleProgrammable.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniFlowRuleProgrammable.java
@@ -20,8 +20,8 @@
 
 import com.google.common.collect.ImmutableList;
 import org.onlab.util.Frequency;
-import org.onosproject.drivers.odtn.impl.FlowRuleParser;
 import org.onosproject.drivers.odtn.impl.DeviceConnectionCache;
+import org.onosproject.drivers.odtn.impl.FlowRuleParser;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
@@ -184,12 +184,15 @@
                         + " </oc-opt-term:optical-channel>"
                         + "</component>"
                         + "</components>");
-
-        boolean ok =
-                session.editConfig(DatastoreId.RUNNING, null, sb.toString());
+        log.info("Optical Channel Frequency {}", sb.toString());
+        boolean ok = session.editConfig(DatastoreId.CANDIDATE, null, sb.toString());
         if (!ok) {
             throw new NetconfException("error writing channel frequency");
         }
+        ok = session.commit();
+        if (!ok) {
+            throw new NetconfException("error committing channel frequency");
+        }
     }
 
     /**
@@ -205,7 +208,7 @@
 
     /**
      * Apply the flowrule.
-     *
+     * <p>
      * Note: only bidirectional are supported as of now,
      * given OpenConfig note (below). In consequence, only the
      * TX rules are actually mapped to netconf ops.
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationConfig.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationConfig.java
index 163bfb5..a271132 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationConfig.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationConfig.java
@@ -209,7 +209,7 @@
             XMLConfiguration xconf = NetconfSessionUtility.executeRpc(session, rpcReq.toString());
             try {
                 HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/config");
+                        xconf.configurationAt("components/component/optical-channel/config");
 
                 String modulationScheme = String.valueOf(config.getString("modulation"));
 
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOcNos.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOcNos.java
index 5daf5cc..53b56db 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOcNos.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOcNos.java
@@ -35,8 +35,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -60,10 +58,10 @@
 
 
     enum BitRate {
-        GBPS_200(20000000),      // 200 Gbps
-        GBPS_100(10000000),        // 100 Gbps
-        GBPS_40(4000000),          // 40 Gbps
-        GBPS_10(1000000);          // 10 Gbps
+        GBPS_200(200),      // 200 Gbps
+        GBPS_100(100),        // 100 Gbps
+        GBPS_40(40),          // 40 Gbps
+        GBPS_10(10);          // 10 Gbps
 
         private final long value;
 
@@ -228,12 +226,6 @@
 
         CassiniModulationOcNos cassini;
 
-        List<PortNumber> getPorts(Object component) {
-            // FIXME
-            log.warn("Not Implemented Yet!");
-            return new ArrayList<PortNumber>();
-        }
-
         /*
          * mirror method in the internal class.
          * @param port port
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOpenConfig.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOpenConfig.java
index bcb055f..5592041 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOpenConfig.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOpenConfig.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-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.
@@ -28,6 +28,7 @@
 import org.onosproject.net.behaviour.ModulationConfig;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.DatastoreId;
 import org.onosproject.netconf.NetconfController;
 import org.onosproject.netconf.NetconfDevice;
 import org.onosproject.netconf.NetconfException;
@@ -35,8 +36,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -60,10 +59,10 @@
 
 
     enum BitRate {
-        GBPS_200(20000000),      // 200 Gbps
-        GBPS_100(10000000),        // 100 Gbps
-        GBPS_40(4000000),          // 40 Gbps
-        GBPS_10(1000000);          // 10 Gbps
+        GBPS_200(200),      // 200 Gbps
+        GBPS_100(100),        // 100 Gbps
+        GBPS_40(40),          // 40 Gbps
+        GBPS_10(10);          // 10 Gbps
 
         private final long value;
 
@@ -229,12 +228,6 @@
 
         CassiniModulationOpenConfig cassini;
 
-        List<PortNumber> getPorts(Object component) {
-            // FIXME
-            log.warn("Not Implemented Yet!");
-            return new ArrayList<PortNumber>();
-        }
-
         /*
          * mirror method in the internal class.
          * @param port port
@@ -257,7 +250,7 @@
             XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
             try {
                 HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/config");
+                        xconf.configurationAt("components/component/optical-channel/config");
 
                 String modulationScheme = String.valueOf(config.getString("modulation"));
                 /*Used for Internal Testing */
@@ -387,7 +380,7 @@
             StringBuilder rpcReq = new StringBuilder();
             rpcReq.append(RPC_TAG_NETCONF_BASE)
                     .append("<edit-config>")
-                    .append("<target><running/></target>")
+                    .append("<target><" + DatastoreId.CANDIDATE + "/></target>")
                     .append("<config>")
                     .append(editConfig)
                     .append("</config>")
@@ -402,9 +395,13 @@
                 log.error("The <edit-config> operation to set target-modulation of Port({}:{}) is failed.",
                         port.toString(), component.toString());
             }
+            try {
+                session.commit();
+            } catch (NetconfException e) {
+                response = false;
+                log.error("error committing modulation changes");
+            }
             return response;
         }
     }
-
-
 }
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDeviceDiscovery.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDeviceDiscovery.java
index eeb885f..ebc1c65 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDeviceDiscovery.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDeviceDiscovery.java
@@ -18,32 +18,30 @@
 
 package org.onosproject.drivers.odtn;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import org.apache.commons.configuration.HierarchicalConfiguration;
 import org.apache.commons.configuration.XMLConfiguration;
 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
 import org.onlab.packet.ChassisId;
 import org.onosproject.drivers.utilities.XmlConfigParser;
+import org.onosproject.net.ChannelSpacing;
 import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port.Type;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalType;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DefaultDeviceDescription;
-import org.onosproject.net.device.DefaultPortDescription;
-import org.onosproject.net.device.DefaultPortDescription.Builder;
 import org.onosproject.net.device.DeviceDescription;
 import org.onosproject.net.device.DeviceDescriptionDiscovery;
 import org.onosproject.net.device.PortDescription;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.optical.device.OchPortHelper;
 import org.onosproject.netconf.NetconfController;
 import org.onosproject.netconf.NetconfDevice;
 import org.onosproject.netconf.NetconfSession;
 import org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery;
-import org.onosproject.net.OchSignal;
-import org.onosproject.net.optical.device.OchPortHelper;
-import org.onosproject.net.OduSignalType;
-import org.onosproject.net.ChannelSpacing;
 import org.slf4j.Logger;
 
 import java.util.HashMap;
@@ -51,35 +49,27 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static org.slf4j.LoggerFactory.getLogger;
 
 
 /**
  * Driver Implementation of the DeviceDescrption discovery for OpenConfig
  * terminal devices.
- *
  */
 public class CassiniTerminalDeviceDiscovery
-    extends AbstractHandlerBehaviour
-    implements OdtnDeviceDescriptionDiscovery, DeviceDescriptionDiscovery {
+        extends AbstractHandlerBehaviour
+        implements OdtnDeviceDescriptionDiscovery, DeviceDescriptionDiscovery {
 
     private static final String RPC_TAG_NETCONF_BASE =
-        "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
+            "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
 
     private static final String RPC_CLOSE_TAG = "</rpc>";
 
-    private static final String OC_PLATFORM_TYPES_TRANSCEIVER =
-        "oc-platform-types:TRANSCEIVER";
-
-    private static final String OC_PLATFORM_TYPES_PORT =
-        "oc-platform-types:PORT";
-
     private static final String OC_TRANSPORT_TYPES_OPTICAL_CHANNEL =
-        "oc-opt-types:OPTICAL_CHANNEL";
+            "OPTICAL_CHANNEL";
 
     private static final Logger log = getLogger(CassiniTerminalDeviceDiscovery.class);
 
@@ -88,7 +78,6 @@
      * Returns the NetconfSession with the device for which the method was called.
      *
      * @param deviceId device indetifier
-     *
      * @return The netconf session or null
      */
     private NetconfSession getNetconfSession(DeviceId deviceId) {
@@ -130,35 +119,23 @@
     }
 
 
-    /**
-     * Builds a request to get Device Components, config and operational data.
-     *
-     * @return A string with the Netconf RPC for a get with subtree rpcing based on
-     *    /components/
-     */
-    private String getTerminalDeviceBuilder() {
-        return filteredGetBuilder("<terminal-device xmlns='http://openconfig.net/yang/terminal-device'/>");
-    }
-
-
     @Override
     public DeviceDescription discoverDeviceDetails() {
         return new DefaultDeviceDescription(handler().data().deviceId().uri(),
-                                            Device.Type.TERMINAL_DEVICE,
-                                            "EDGECORE",
-                                            "Cassini",
-                                            "OcNOS",
-                                            "",
-                                            new ChassisId("1"));
+                Device.Type.TERMINAL_DEVICE,
+                "EDGECORE",
+                "Cassini",
+                "OcNOS",
+                "",
+                new ChassisId("1"));
     }
 
 
-
     /**
      * Returns a list of PortDescriptions for the device.
      *
      * @return a list of descriptions.
-     *
+     * <p>
      * The RPC reply follows the following pattern:
      * //CHECKSTYLE:OFF
      * <pre>{@code
@@ -184,134 +161,124 @@
                 log.error("discoverPortDetails called with null session for {}", did());
                 return ImmutableList.of();
             }
+            CompletableFuture<CharSequence> fut1 = session.asyncGet();
+            String rpcReplyTest = fut1.get().toString();
 
-            CompletableFuture<String> fut = session.rpc(getTerminalDeviceBuilder());
-            String rpcReply = fut.get();
-
-            XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(rpcReply);
+            XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(rpcReplyTest);
             xconf.setExpressionEngine(new XPathExpressionEngine());
 
-            HierarchicalConfiguration logicalChannels = xconf.configurationAt("data/terminal-device/logical-channels");
-            return parseLogicalChannels(logicalChannels);
+            HierarchicalConfiguration logicalChannels = xconf.configurationAt("components");
+            return discoverPorts(logicalChannels);
         } catch (Exception e) {
             log.error("Exception discoverPortDetails() {}", did(), e);
             return ImmutableList.of();
         }
     }
 
-
-
-
     /**
-     * Parses transceiver information from OpenConfig XML configuration.
+     * Parses port information from OpenConfig XML configuration.
      *
-     * @param terminalDevice the XML document with components root.
+     * @param cfg tree where the root node is {@literal <data>}
      * @return List of ports
-     *
-     * //CHECKSTYLE:OFF
-     * <pre>{@code
-     *   <components xmlns="http://openconfig.net/yang/platform">
-     *     <component>....
-     *     </component>
-     *     <component>....
-     *     </component>
-     *   </components>
-     * }</pre>
-     * //CHECKSTYLE:ON
      */
-    protected List<PortDescription> parseLogicalChannels(HierarchicalConfiguration terminalDevice) {
-        return terminalDevice.configurationsAt("channel")
-            .stream()
-            .filter(channel -> !channel.getString("index", "unknown").equals("unknown"))
-            .map(channel -> {
-                try {
-                    // Pass the root document for cross-reference
-                    return parseLogicalChannel(channel);
-                } catch (Exception e) {
-                    return null;
-                }
-                })
-            .filter(Objects::nonNull)
-            .collect(Collectors.toList());
+    @VisibleForTesting
+    private List<PortDescription> discoverPorts(HierarchicalConfiguration cfg) {
+        // If we want to use XPath
+        cfg.setExpressionEngine(new XPathExpressionEngine());
+        // converting components into PortDescription.
+        List<HierarchicalConfiguration> components = cfg.configurationsAt("component");
+        return components.stream()
+                .map(this::toPortDescriptionInternal)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
     }
 
+    /**
+     * Converts Component subtree to PortDescription.
+     *
+     * @param component subtree to parse
+     * @return PortDescription or null if component is not an ONOS Port
+     */
+    private PortDescription toPortDescriptionInternal(HierarchicalConfiguration component) {
+        Map<String, String> annotations = new HashMap<>();
+         /*
+        <components xmlns="http://openconfig.net/yang/platform">
+             <component>
+                <name>oc1/0</name>
+                 <config>
+                    <name>oc1/0</name>
+                 </config>
+                 <state>
+                    <name>oc1/0</name>
+                 <type>OPTICAL_CHANNEL</type>
+                <id/>
+                <description/>
+                <mfg-name/>
+                <hardware-version/>
+                <firmware-version/>
+                <software-version/>
+                <serial-no/>
+                <part-no/>
+                <removable>true</removable>
+                <empty>false</empty>
+                <parent/>
+                <temperature>
+                <instant>0.0</instant>
+                <avg>0.0</avg>
+                <min>0.0</min>
+                <max>0.0</max>
+                <interval>0</interval>
+                <min-time>0</min-time>
+                <max-time>0</max-time>
+                <alarm-status>true</alarm-status>
+                <alarm-threshold>0</alarm-threshold>
+                </temperature>
+                <memory>
+                    <available>0</available>
+                    <utilized>0</utilized>
+                </memory>
+                <allocated-power>0</allocated-power>
+                <used-power>0</used-power>
+            </state>
+            <optical-channel xmlns="http://openconfig.net/yang/terminal-device">
+                <config>
+                    <line-port>port-10101</line-port>
+                </config>
+            <state>
+                <output-power/>
+                <input-power/>
+            </state>
+            </optical-channel>
+        </component>
+        */
+        String name = component.getString("name");
+        String type = component.getString("state/type");
+        checkNotNull(name, "name not found");
+        checkNotNull(type, "state/type not found");
+        annotations.put(OdtnDeviceDescriptionDiscovery.OC_NAME, name);
+        annotations.put(OdtnDeviceDescriptionDiscovery.OC_TYPE, type);
 
-     /**
-      * Parses a component XML doc into a PortDescription.
-      *
-      * @param channel subtree to parse. It must be a component ot type PORT.
-      *  case we need to check transceivers or optical channels.
-      *
-      * @return PortDescription or null if component does not have onos-index
-      */
-     private PortDescription parseLogicalChannel(
-             HierarchicalConfiguration channel) {
+        //TODO this currently support only line-side ports through parsing of optical channels.
+        if (type.equals(OC_TRANSPORT_TYPES_OPTICAL_CHANNEL)) {
+            String portName = component.getString("optical-channel/config/line-port");
+            String portIndex = portName.split("-")[1];
+            annotations.putIfAbsent("name", portName);
+            annotations.putIfAbsent(PORT_TYPE, OdtnPortType.LINE.value());
+            annotations.putIfAbsent(ONOS_PORT_INDEX, portIndex);
+            annotations.putIfAbsent(CONNECTION_ID, "connection-" + portIndex);
 
-         HierarchicalConfiguration config = channel.configurationAt("config");
-         String logicalChannelIndex = config.getString("index");
-         String description = config.getString("description");
-         String rateClass = config.getString("rate-class");
-         log.info("Parsing Component {} type {} rate {}", logicalChannelIndex, description, rateClass);
+            OchSignal signalId = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 1);
+            return OchPortHelper.ochPortDescription(
+                    PortNumber.portNumber(Long.parseLong(portIndex)),
+                    true,
+                    OduSignalType.ODU4, // TODO Client signal to be discovered
+                    true,
+                    signalId,
+                    DefaultAnnotations.builder().putAll(annotations).build());
 
-         Map<String, String> annotations = new HashMap<>();
-         annotations.put(OdtnDeviceDescriptionDiscovery.OC_LOGICAL_CHANNEL, logicalChannelIndex);
-         annotations.put(OdtnDeviceDescriptionDiscovery.OC_NAME, description);
-
-         // Store all properties as port properties
-
-         Pattern clientPattern = Pattern.compile("xe(\\d*)/1"); // e.g. xe1/1
-         Pattern linePattern = Pattern.compile("oe(\\d*)/(\\d*)"); // e.g. oe1
-         Matcher clientMatch = clientPattern.matcher(description);
-         Matcher lineMatch = linePattern.matcher(description);
-
-         Pattern portSpeedPattern = Pattern.compile("TRIB_RATE_([0-9.]*)G");
-         Matcher portSpeedMatch = portSpeedPattern.matcher(rateClass);
-
-
-         Builder builder = DefaultPortDescription.builder();
-
-         if (portSpeedMatch.find()) {
-             Long speed = Long.parseLong(portSpeedMatch.group(1));
-             builder.portSpeed(speed * 1000);
-         }
-
-         if (clientMatch.find()) {
-             Long num = Long.parseLong(clientMatch.group(1));
-             Long portNum = 100 + num;
-             String connectionId = "connection:" + num.toString();
-
-             annotations.putIfAbsent(PORT_TYPE, OdtnPortType.CLIENT.value());
-             annotations.putIfAbsent(ONOS_PORT_INDEX, portNum.toString());
-             annotations.putIfAbsent(CONNECTION_ID, connectionId);
-
-             builder.withPortNumber(PortNumber.portNumber(portNum));
-             builder.type(Type.PACKET);
-
-             builder.annotations(DefaultAnnotations.builder().putAll(annotations).build());
-             return builder.build();
-
-         } else if (lineMatch.find()) {
-             Long num = (Long.parseLong(lineMatch.group(1)) - 1) * 2 + Long.parseLong(lineMatch.group(2));
-             Long portNum = 200 + num;
-             String connectionId = "connection:" + num.toString();
-
-             annotations.putIfAbsent(PORT_TYPE, OdtnPortType.LINE.value());
-             annotations.putIfAbsent(ONOS_PORT_INDEX, portNum.toString());
-             annotations.putIfAbsent(CONNECTION_ID, connectionId);
-
-             OchSignal signalId = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 1);
-             return OchPortHelper.ochPortDescription(
-                     PortNumber.portNumber(portNum),
-                     true,
-                     OduSignalType.ODU4, // TODO Client signal to be discovered
-                     true,
-                     signalId,
-                     DefaultAnnotations.builder().putAll(annotations).build());
-
-         } else {
-             log.warn("Unexpected component description: {}", description);
-             return null;
-         }
-
-     }
+        } else {
+            log.debug("Unknown port component type {}", type);
+            return null;
+        }
+    }
 }
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDeviceDiscoveryOld.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDeviceDiscoveryOld.java
new file mode 100644
index 0000000..19b247e
--- /dev/null
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDeviceDiscoveryOld.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2018-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.
+ *
+ * This work was partially supported by EC H2020 project METRO-HAUL (761727).
+ */
+
+package org.onosproject.drivers.odtn;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
+import org.onlab.packet.ChassisId;
+import org.onosproject.drivers.utilities.XmlConfigParser;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalType;
+import org.onosproject.net.Port.Type;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DefaultPortDescription;
+import org.onosproject.net.device.DefaultPortDescription.Builder;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceDescriptionDiscovery;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.optical.device.OchPortHelper;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfDevice;
+import org.onosproject.netconf.NetconfSession;
+import org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery;
+import org.slf4j.Logger;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+
+/**
+ * Driver Implementation of the DeviceDescrption discovery for OpenConfig
+ * terminal devices.
+ *
+ */
+public class CassiniTerminalDeviceDiscoveryOld
+    extends AbstractHandlerBehaviour
+    implements OdtnDeviceDescriptionDiscovery, DeviceDescriptionDiscovery {
+
+    private static final String RPC_TAG_NETCONF_BASE =
+        "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
+
+    private static final String RPC_CLOSE_TAG = "</rpc>";
+
+    private static final String OC_PLATFORM_TYPES_TRANSCEIVER =
+        "oc-platform-types:TRANSCEIVER";
+
+    private static final String OC_PLATFORM_TYPES_PORT =
+        "oc-platform-types:PORT";
+
+    private static final String OC_TRANSPORT_TYPES_OPTICAL_CHANNEL =
+        "oc-opt-types:OPTICAL_CHANNEL";
+
+    private static final Logger log = getLogger(CassiniTerminalDeviceDiscoveryOld.class);
+
+
+    /**
+     * Returns the NetconfSession with the device for which the method was called.
+     *
+     * @param deviceId device indetifier
+     *
+     * @return The netconf session or null
+     */
+    private NetconfSession getNetconfSession(DeviceId deviceId) {
+        NetconfController controller = handler().get(NetconfController.class);
+        NetconfDevice ncdev = controller.getDevicesMap().get(deviceId);
+        if (ncdev == null) {
+            log.trace("No netconf device, returning null session");
+            return null;
+        }
+        return ncdev.getSession();
+    }
+
+
+    /**
+     * Get the deviceId for which the methods apply.
+     *
+     * @return The deviceId as contained in the handler data
+     */
+    private DeviceId did() {
+        return handler().data().deviceId();
+    }
+
+
+    /**
+     * Construct a String with a Netconf filtered get RPC Message.
+     *
+     * @param filter A valid XML tree with the filter to apply in the get
+     * @return a String containing the RPC XML Document
+     */
+    private String filteredGetBuilder(String filter) {
+        StringBuilder rpc = new StringBuilder(RPC_TAG_NETCONF_BASE);
+        rpc.append("<get>");
+        rpc.append("<filter type='subtree'>");
+        rpc.append(filter);
+        rpc.append("</filter>");
+        rpc.append("</get>");
+        rpc.append(RPC_CLOSE_TAG);
+        return rpc.toString();
+    }
+
+
+    /**
+     * Builds a request to get Device Components, config and operational data.
+     *
+     * @return A string with the Netconf RPC for a get with subtree rpcing based on
+     *    /components/
+     */
+    private String getTerminalDeviceBuilder() {
+        return filteredGetBuilder("<terminal-device xmlns='http://openconfig.net/yang/terminal-device'/>");
+    }
+
+
+    @Override
+    public DeviceDescription discoverDeviceDetails() {
+        return new DefaultDeviceDescription(handler().data().deviceId().uri(),
+                                            Device.Type.TERMINAL_DEVICE,
+                                            "EDGECORE",
+                                            "Cassini",
+                                            "OcNOS",
+                                            "",
+                                            new ChassisId("1"));
+    }
+
+
+
+    /**
+     * Returns a list of PortDescriptions for the device.
+     *
+     * @return a list of descriptions.
+     *
+     * The RPC reply follows the following pattern:
+     * //CHECKSTYLE:OFF
+     * <pre>{@code
+     * <?xml version="1.0" encoding="UTF-8"?>
+     * <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="7">
+     * <data>
+     *   <components xmlns="http://openconfig.net/yang/platform">
+     *     <component>....
+     *     </component>
+     *     <component>....
+     *     </component>
+     *   </components>
+     * </data>
+     * </rpc-reply>
+     * }</pre>
+     * //CHECKSTYLE:ON
+     */
+    @Override
+    public List<PortDescription> discoverPortDetails() {
+        try {
+            NetconfSession session = getNetconfSession(did());
+            if (session == null) {
+                log.error("discoverPortDetails called with null session for {}", did());
+                return ImmutableList.of();
+            }
+
+            CompletableFuture<String> fut = session.rpc(getTerminalDeviceBuilder());
+            String rpcReply = fut.get();
+
+            XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(rpcReply);
+            xconf.setExpressionEngine(new XPathExpressionEngine());
+
+            HierarchicalConfiguration logicalChannels = xconf.configurationAt("data/terminal-device/logical-channels");
+            return parseLogicalChannels(logicalChannels);
+        } catch (Exception e) {
+            log.error("Exception discoverPortDetails() {}", did(), e);
+            return ImmutableList.of();
+        }
+    }
+
+
+
+
+    /**
+     * Parses transceiver information from OpenConfig XML configuration.
+     *
+     * @param terminalDevice the XML document with components root.
+     * @return List of ports
+     *
+     * //CHECKSTYLE:OFF
+     * <pre>{@code
+     *   <components xmlns="http://openconfig.net/yang/platform">
+     *     <component>....
+     *     </component>
+     *     <component>....
+     *     </component>
+     *   </components>
+     * }</pre>
+     * //CHECKSTYLE:ON
+     */
+    protected List<PortDescription> parseLogicalChannels(HierarchicalConfiguration terminalDevice) {
+        return terminalDevice.configurationsAt("channel")
+            .stream()
+            .filter(channel -> !channel.getString("index", "unknown").equals("unknown"))
+            .map(channel -> {
+                try {
+                    // Pass the root document for cross-reference
+                    return parseLogicalChannel(channel);
+                } catch (Exception e) {
+                    return null;
+                }
+                })
+            .filter(Objects::nonNull)
+            .collect(Collectors.toList());
+    }
+
+
+     /**
+      * Parses a component XML doc into a PortDescription.
+      *
+      * @param channel subtree to parse. It must be a component ot type PORT.
+      *  case we need to check transceivers or optical channels.
+      *
+      * @return PortDescription or null if component does not have onos-index
+      */
+     private PortDescription parseLogicalChannel(
+             HierarchicalConfiguration channel) {
+
+         HierarchicalConfiguration config = channel.configurationAt("config");
+         String logicalChannelIndex = config.getString("index");
+         String description = config.getString("description");
+         String rateClass = config.getString("rate-class");
+         log.info("Parsing Component {} type {} rate {}", logicalChannelIndex, description, rateClass);
+
+         Map<String, String> annotations = new HashMap<>();
+         annotations.put(OdtnDeviceDescriptionDiscovery.OC_LOGICAL_CHANNEL, logicalChannelIndex);
+         annotations.put(OdtnDeviceDescriptionDiscovery.OC_NAME, description);
+
+         // Store all properties as port properties
+
+         Pattern clientPattern = Pattern.compile("xe(\\d*)/1"); // e.g. xe1/1
+         Pattern linePattern = Pattern.compile("oe(\\d*)/(\\d*)"); // e.g. oe1
+         Matcher clientMatch = clientPattern.matcher(description);
+         Matcher lineMatch = linePattern.matcher(description);
+
+         Pattern portSpeedPattern = Pattern.compile("TRIB_RATE_([0-9.]*)G");
+         Matcher portSpeedMatch = portSpeedPattern.matcher(rateClass);
+
+
+         Builder builder = DefaultPortDescription.builder();
+
+         if (portSpeedMatch.find()) {
+             Long speed = Long.parseLong(portSpeedMatch.group(1));
+             builder.portSpeed(speed * 1000);
+         }
+
+         if (clientMatch.find()) {
+             Long num = Long.parseLong(clientMatch.group(1));
+             Long portNum = 100 + num;
+             String connectionId = "connection:" + num.toString();
+
+             annotations.putIfAbsent(PORT_TYPE, OdtnPortType.CLIENT.value());
+             annotations.putIfAbsent(ONOS_PORT_INDEX, portNum.toString());
+             annotations.putIfAbsent(CONNECTION_ID, connectionId);
+
+             builder.withPortNumber(PortNumber.portNumber(portNum));
+             builder.type(Type.PACKET);
+
+             builder.annotations(DefaultAnnotations.builder().putAll(annotations).build());
+             return builder.build();
+
+         } else if (lineMatch.find()) {
+             Long num = (Long.parseLong(lineMatch.group(1)) - 1) * 2 + Long.parseLong(lineMatch.group(2));
+             Long portNum = 200 + num;
+             String connectionId = "connection:" + num.toString();
+
+             annotations.putIfAbsent(PORT_TYPE, OdtnPortType.LINE.value());
+             annotations.putIfAbsent(ONOS_PORT_INDEX, portNum.toString());
+             annotations.putIfAbsent(CONNECTION_ID, connectionId);
+
+             OchSignal signalId = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 1);
+             return OchPortHelper.ochPortDescription(
+                     PortNumber.portNumber(portNum),
+                     true,
+                     OduSignalType.ODU4, // TODO Client signal to be discovered
+                     true,
+                     signalId,
+                     DefaultAnnotations.builder().putAll(annotations).build());
+
+         } else {
+             log.warn("Unexpected component description: {}", description);
+             return null;
+         }
+
+     }
+}
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDevicePowerConfig.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDevicePowerConfig.java
index 564686e..33dc66b 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDevicePowerConfig.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDevicePowerConfig.java
@@ -29,6 +29,7 @@
 import org.onosproject.net.behaviour.PowerConfig;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.DatastoreId;
 import org.onosproject.netconf.NetconfController;
 import org.onosproject.netconf.NetconfDevice;
 import org.onosproject.netconf.NetconfException;
@@ -240,7 +241,7 @@
             XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
             try {
                 HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/config");
+                        xconf.configurationAt("components/component/optical-channel/state");
                 long power = Float.valueOf(config.getString("target-output-power")).longValue();
                 return Optional.of(power);
             } catch (IllegalArgumentException e) {
@@ -261,18 +262,24 @@
             StringBuilder rpcReq = new StringBuilder();
             rpcReq.append(RPC_TAG_NETCONF_BASE)
                     .append("<edit-config>")
-                    .append("<target><running/></target>")
+                    .append("<target><" + DatastoreId.CANDIDATE + "/></target>")
                     .append("<config>")
                     .append(editConfig)
                     .append("</config>")
                     .append("</edit-config>")
                     .append(RPC_CLOSE_TAG);
+            log.info("Setting power {}", rpcReq.toString());
             XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
             // The successful reply should be "<rpc-reply ...><ok /></rpc-reply>"
             if (!xconf.getRoot().getChild(0).getName().equals("ok")) {
                 log.error("The <edit-config> operation to set target-output-power of Port({}:{}) is failed.",
                         port.toString(), component.toString());
             }
+            try {
+                session.commit();
+            } catch (NetconfException e) {
+                log.error("error committing channel power");
+            }
         }
 
         /**
@@ -286,7 +293,7 @@
                                     cassini, port, "<output-power><instant/></output-power>");
             try {
                 HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/state/output-power");
+                        xconf.configurationAt("components/component/optical-channel/state/output-power");
                 long currentPower = Float.valueOf(config.getString("instant")).longValue();
                 return Optional.of(currentPower);
             } catch (IllegalArgumentException e) {
@@ -305,7 +312,7 @@
                     cassini, port, "<input-power><instant/></input-power>");
             try {
                 HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/state/input-power");
+                        xconf.configurationAt("components/component/optical-channel/state/input-power");
                 long currentPower = Float.valueOf(config.getString("instant")).longValue();
                 return Optional.of(currentPower);
             } catch (IllegalArgumentException e) {
@@ -314,32 +321,15 @@
         }
 
         Optional<Range<Long>> getTargetPowerRange(PortNumber port, Object component) {
-            XMLConfiguration xconf = getOpticalChannelState(
-                    cassini, port, "<target-power-range/>");
-            try {
-                HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/state/target-power-range");
-                long targetMin = Float.valueOf(config.getString("min")).longValue();
-                long targetMax = Float.valueOf(config.getString("max")).longValue();
+                long targetMin = -30;
+                long targetMax = 1;
                 return Optional.of(Range.open(targetMin, targetMax));
-            } catch (IllegalArgumentException e) {
-                return Optional.empty();
-            }
-
         }
 
         Optional<Range<Long>> getInputPowerRange(PortNumber port, Object component) {
-            XMLConfiguration xconf = getOpticalChannelState(
-                    cassini, port, "<input-power-range/>");
-            try {
-                HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/state/input-power-range");
-                long inputMin = Float.valueOf(config.getString("min")).longValue();
-                long inputMax = Float.valueOf(config.getString("max")).longValue();
-                return Optional.of(Range.open(inputMin, inputMax));
-            } catch (IllegalArgumentException e) {
-                return Optional.empty();
-            }
+            long targetMin = -30;
+            long targetMax = 1;
+            return Optional.of(Range.open(targetMin, targetMax));
         }
 
         List<PortNumber> getPorts(Object component) {
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDevicePowerConfigExt.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDevicePowerConfigExt.java
new file mode 100644
index 0000000..0029fff
--- /dev/null
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniTerminalDevicePowerConfigExt.java
@@ -0,0 +1,421 @@
+/*
+ * Copyright 2018-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.
+ *
+ * This work was partially supported by EC H2020 project METRO-HAUL (761727).
+ */
+
+package org.onosproject.drivers.odtn;
+
+import com.google.common.collect.Range;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onosproject.drivers.utilities.XmlConfigParser;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.PowerConfig;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfDevice;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Driver Implementation of the PowerConfig for OpenConfig terminal devices.
+ *
+ */
+public class CassiniTerminalDevicePowerConfigExt<T>
+        extends AbstractHandlerBehaviour implements PowerConfig<T> {
+
+    private static final String RPC_TAG_NETCONF_BASE =
+            "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
+
+    private static final String RPC_CLOSE_TAG = "</rpc>";
+
+    private static final long NO_POWER = -50;
+
+    private static final Logger log = getLogger(CassiniTerminalDevicePowerConfigExt.class);
+
+    private ComponentType state = ComponentType.DIRECTION;
+
+    /**
+     * Returns the NetconfSession with the device for which the method was called.
+     *
+     * @param deviceId device indetifier
+     *
+     * @return The netconf session or null
+     */
+    private NetconfSession getNetconfSession(DeviceId deviceId) {
+        NetconfController controller = handler().get(NetconfController.class);
+        NetconfDevice ncdev = controller.getDevicesMap().get(deviceId);
+        if (ncdev == null) {
+            log.trace("No netconf device, returning null session");
+            return null;
+        }
+        return ncdev.getSession();
+    }
+
+    /**
+     * Get the deviceId for which the methods apply.
+     *
+     * @return The deviceId as contained in the handler data
+     */
+    private DeviceId did() {
+        return handler().data().deviceId();
+    }
+
+    /**
+     * Execute RPC request.
+     * @param session Netconf session
+     * @param message Netconf message in XML format
+     * @return XMLConfiguration object
+     */
+    private XMLConfiguration executeRpc(NetconfSession session, String message) {
+        try {
+            CompletableFuture<String> fut = session.rpc(message);
+            String rpcReply = fut.get();
+            XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(rpcReply);
+            xconf.setExpressionEngine(new XPathExpressionEngine());
+            return xconf;
+        } catch (NetconfException ne) {
+            log.error("Exception on Netconf protocol: {}.", ne);
+        } catch (InterruptedException ie) {
+            log.error("Interrupted Exception: {}.", ie);
+        } catch (ExecutionException ee) {
+            log.error("Concurrent Exception while executing Netconf operation: {}.", ee);
+        }
+        return null;
+    }
+
+    /**
+     * Get the target-output-power value on specific optical-channel.
+     * @param port the port
+     * @param component the port component. It should be 'oc-name' in the Annotations of Port.
+     *                  'oc-name' could be mapped to '/component/name' in openconfig yang.
+     * @return target power value
+     */
+    @Override
+    public Optional<Long> getTargetPower(PortNumber port, T component) {
+        checkState(component);
+        return state.getTargetPower(port, component);
+    }
+
+    @Override
+    public void setTargetPower(PortNumber port, T component, long power) {
+        checkState(component);
+        state.setTargetPower(port, component, power);
+    }
+
+    @Override
+    public Optional<Long> currentPower(PortNumber port, T component) {
+        checkState(component);
+        return state.currentPower(port, component);
+    }
+
+    @Override
+    public Optional<Long> currentInputPower(PortNumber port, T component) {
+        checkState(component);
+        return state.currentInputPower(port, component);
+    }
+
+    @Override
+    public Optional<Range<Long>> getTargetPowerRange(PortNumber port, T component) {
+        checkState(component);
+        return state.getTargetPowerRange(port, component);
+    }
+
+    @Override
+    public Optional<Range<Long>> getInputPowerRange(PortNumber port, T component) {
+        checkState(component);
+        return state.getInputPowerRange(port, component);
+    }
+
+    @Override
+    public List<PortNumber> getPorts(T component) {
+        checkState(component);
+        return state.getPorts(component);
+    }
+
+
+    /**
+     * Set the ComponentType to invoke proper methods for different template T.
+     * @param component the component.
+     */
+    void checkState(Object component) {
+        String clsName = component.getClass().getName();
+        switch (clsName) {
+            case "org.onosproject.net.Direction":
+                state = ComponentType.DIRECTION;
+                break;
+            case "org.onosproject.net.OchSignal":
+                state = ComponentType.OCHSIGNAL;
+                break;
+            default:
+                log.error("Cannot parse the component type {}.", clsName);
+                log.info("The component content is {}.", component.toString());
+        }
+        state.cassini = this;
+    }
+
+    /**
+     * Component type.
+     */
+    enum ComponentType {
+
+        /**
+         * Direction.
+         */
+        DIRECTION() {
+            @Override
+            public Optional<Long> getTargetPower(PortNumber port, Object component) {
+                return super.getTargetPower(port, component);
+            }
+            @Override
+            public void setTargetPower(PortNumber port, Object component, long power) {
+                super.setTargetPower(port, component, power);
+            }
+        },
+
+        /**
+         * OchSignal.
+         */
+        OCHSIGNAL() {
+            @Override
+            public Optional<Long> getTargetPower(PortNumber port, Object component) {
+                return super.getTargetPower(port, component);
+            }
+
+            @Override
+            public void setTargetPower(PortNumber port, Object component, long power) {
+                super.setTargetPower(port, component, power);
+            }
+        };
+
+
+
+        CassiniTerminalDevicePowerConfigExt cassini;
+
+        /**
+         * mirror method in the internal class.
+         * @param port port
+         * @param component component
+         * @return target power
+         */
+        Optional<Long> getTargetPower(PortNumber port, Object component) {
+            NetconfSession session = cassini.getNetconfSession(cassini.did());
+            checkNotNull(session);
+            String filter = parsePort(cassini, port, null, null);
+            StringBuilder rpcReq = new StringBuilder();
+            rpcReq.append(RPC_TAG_NETCONF_BASE)
+                    .append("<get>")
+                    .append("<filter type='subtree'>")
+                    .append(filter)
+                    .append("</filter>")
+                    .append("</get>")
+                    .append(RPC_CLOSE_TAG);
+            XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
+            try {
+                HierarchicalConfiguration config =
+                        xconf.configurationAt("data/components/component/optical-channel/config");
+                long power = Float.valueOf(config.getString("target-output-power")).longValue();
+                return Optional.of(power);
+            } catch (IllegalArgumentException e) {
+                return Optional.empty();
+            }
+        }
+
+        /**
+         * mirror method in the internal class.
+         * @param port port
+         * @param component component
+         * @param power target value
+         */
+        void setTargetPower(PortNumber port, Object component, long power) {
+            NetconfSession session = cassini.getNetconfSession(cassini.did());
+            checkNotNull(session);
+            String editConfig = parsePort(cassini, port, null, power);
+            StringBuilder rpcReq = new StringBuilder();
+            rpcReq.append(RPC_TAG_NETCONF_BASE)
+                    .append("<edit-config>")
+                    .append("<target><running/></target>")
+                    .append("<config>")
+                    .append(editConfig)
+                    .append("</config>")
+                    .append("</edit-config>")
+                    .append(RPC_CLOSE_TAG);
+            XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
+            // The successful reply should be "<rpc-reply ...><ok /></rpc-reply>"
+            if (!xconf.getRoot().getChild(0).getName().equals("ok")) {
+                log.error("The <edit-config> operation to set target-output-power of Port({}:{}) is failed.",
+                        port.toString(), component.toString());
+            }
+        }
+
+        /**
+         * mirror method in the internal class.
+         * @param port port
+         * @param component the component.
+         * @return current output power.
+         */
+        Optional<Long> currentPower(PortNumber port, Object component) {
+            XMLConfiguration xconf = getOpticalChannelState(
+                                    cassini, port, "<output-power><instant/></output-power>");
+            try {
+                HierarchicalConfiguration config =
+                        xconf.configurationAt("data/components/component/optical-channel/state/output-power");
+                long currentPower = Float.valueOf(config.getString("instant")).longValue();
+                return Optional.of(currentPower);
+            } catch (IllegalArgumentException e) {
+                return Optional.empty();
+            }
+        }
+
+        /**
+         * mirror method in the internal class.
+         * @param port port
+         * @param component the component
+         * @return current input power
+         */
+        Optional<Long> currentInputPower(PortNumber port, Object component) {
+            XMLConfiguration xconf = getOpticalChannelState(
+                    cassini, port, "<input-power><instant/></input-power>");
+            try {
+                HierarchicalConfiguration config =
+                        xconf.configurationAt("data/components/component/optical-channel/state/input-power");
+                long currentPower = Float.valueOf(config.getString("instant")).longValue();
+                return Optional.of(currentPower);
+            } catch (IllegalArgumentException e) {
+                return Optional.empty();
+            }
+        }
+
+        Optional<Range<Long>> getTargetPowerRange(PortNumber port, Object component) {
+            XMLConfiguration xconf = getOpticalChannelState(
+                    cassini, port, "<target-power-range/>");
+            try {
+                HierarchicalConfiguration config =
+                        xconf.configurationAt("data/components/component/optical-channel/state/target-power-range");
+                long targetMin = Float.valueOf(config.getString("min")).longValue();
+                long targetMax = Float.valueOf(config.getString("max")).longValue();
+                return Optional.of(Range.open(targetMin, targetMax));
+            } catch (IllegalArgumentException e) {
+                return Optional.empty();
+            }
+
+        }
+
+        Optional<Range<Long>> getInputPowerRange(PortNumber port, Object component) {
+            XMLConfiguration xconf = getOpticalChannelState(
+                    cassini, port, "<input-power-range/>");
+            try {
+                HierarchicalConfiguration config =
+                        xconf.configurationAt("data/components/component/optical-channel/state/input-power-range");
+                long inputMin = Float.valueOf(config.getString("min")).longValue();
+                long inputMax = Float.valueOf(config.getString("max")).longValue();
+                return Optional.of(Range.open(inputMin, inputMax));
+            } catch (IllegalArgumentException e) {
+                return Optional.empty();
+            }
+        }
+
+        List<PortNumber> getPorts(Object component) {
+            // FIXME
+            log.warn("Not Implemented Yet!");
+            return new ArrayList<PortNumber>();
+        }
+
+        /**
+         * Get filtered content under <optical-channel><state>.
+         * @param pc power config instance
+         * @param port the port number
+         * @param underState the filter condition
+         * @return RPC reply
+         */
+        private static XMLConfiguration getOpticalChannelState(CassiniTerminalDevicePowerConfigExt pc,
+                                                               PortNumber port, String underState) {
+            NetconfSession session = pc.getNetconfSession(pc.did());
+            checkNotNull(session);
+            String name = ocName(pc, port);
+            StringBuilder rpcReq = new StringBuilder(RPC_TAG_NETCONF_BASE);
+            rpcReq.append("<get><filter><components xmlns=\"http://openconfig.net/yang/platform\"><component>")
+                    .append("<name>").append(name).append("</name>")
+                    .append("<optical-channel xmlns=\"http://openconfig.net/yang/terminal-device\">")
+                    .append("<state>")
+                    .append(underState)
+                    .append("</state></optical-channel></component></components></filter></get>")
+                    .append(RPC_CLOSE_TAG);
+            XMLConfiguration xconf = pc.executeRpc(session, rpcReq.toString());
+            return xconf;
+        }
+
+
+        /**
+         * Extract component name from portNumber's annotations.
+         * @param pc power config instance
+         * @param portNumber the port number
+         * @return the component name
+         */
+        private static String ocName(CassiniTerminalDevicePowerConfigExt pc, PortNumber portNumber) {
+            DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
+            DeviceId deviceId = pc.handler().data().deviceId();
+            return deviceService.getPort(deviceId, portNumber).annotations().value("oc-name");
+        }
+
+
+
+        /**
+         * Parse filtering string from port and component.
+         * @param portNumber Port Number
+         * @param component port component (optical-channel)
+         * @param power power value set.
+         * @return filtering string in xml format
+         */
+        private static String parsePort(CassiniTerminalDevicePowerConfigExt pc, PortNumber portNumber,
+                                        Object component, Long power) {
+            if (component == null) {
+                String name = ocName(pc, portNumber);
+                StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
+                sb.append("<component>").append("<name>").append(name).append("</name>");
+                if (power != null) {
+                    // This is an edit-config operation.
+                    sb.append("<optical-channel xmlns=\"http://openconfig.net/yang/terminal-device\">")
+                            .append("<config>")
+                            .append("<target-output-power>")
+                            .append(power)
+                            .append("</target-output-power>")
+                            .append("</config>")
+                            .append("</optical-channel>");
+                }
+                sb.append("</component>").append("</components>");
+                return sb.toString();
+            } else {
+                log.error("Cannot process the component {}.", component.getClass());
+                return null;
+            }
+        }
+    }
+}
diff --git a/drivers/odtn-driver/src/main/resources/odtn-drivers.xml b/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
index 7acd67f..811ea42 100644
--- a/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
+++ b/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
@@ -80,6 +80,22 @@
         <behaviour api="org.onosproject.net.behaviour.ModulationConfig"
                    impl="org.onosproject.drivers.odtn.CassiniModulationOpenConfig"/>
     </driver>
+    <driver name="cassini-ocnos-old" manufacturer="Edgecore" hwVersion="cassini" swVersion="OcNOS">
+        <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
+                   impl="org.onosproject.drivers.odtn.CassiniTerminalDeviceDiscoveryOld"/>
+        <behaviour api="org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery"
+                   impl="org.onosproject.drivers.odtn.CassiniTerminalDeviceDiscoveryOld"/>
+        <behaviour api="org.onosproject.odtn.behaviour.ConfigurableTransceiver"
+                   impl="org.onosproject.odtn.behaviour.CassiniTransceiver"/>
+        <behaviour api ="org.onosproject.net.optical.OpticalDevice"
+                   impl="org.onosproject.net.optical.DefaultOpticalDevice"/>
+        <behaviour api ="org.onosproject.net.behaviour.LambdaQuery"
+                   impl="org.onosproject.drivers.odtn.openconfig.TerminalDeviceLambdaQuery"/>
+        <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
+                   impl="org.onosproject.drivers.odtn.CassiniFlowRuleProgrammable"/>
+        <behaviour api="org.onosproject.net.behaviour.PowerConfig"
+                   impl="org.onosproject.drivers.odtn.CassiniTerminalDevicePowerConfig"/>
+    </driver>
     <driver name="cassini-ocnos-ipi-model" manufacturer="Edgecore" hwVersion="cassini" swVersion="OcNOS">
         <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
                    impl="org.onosproject.drivers.odtn.CassiniTerminalDeviceDiscovery"/>
@@ -100,9 +116,9 @@
     </driver>
     <driver name="cassini-openconfig" manufacturer="Edgecore" hwVersion="cassini" swVersion="OcNOS">
         <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
-                   impl="org.onosproject.drivers.odtn.CassiniTerminalDeviceDiscovery"/>
+                   impl="org.onosproject.drivers.odtn.CassiniTerminalDeviceDiscoveryOld"/>
         <behaviour api="org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery"
-                   impl="org.onosproject.drivers.odtn.CassiniTerminalDeviceDiscovery"/>
+                   impl="org.onosproject.drivers.odtn.CassiniTerminalDeviceDiscoveryOld"/>
         <behaviour api="org.onosproject.odtn.behaviour.ConfigurableTransceiver"
                    impl="org.onosproject.odtn.behaviour.CassiniTransceiver"/>
         <behaviour api ="org.onosproject.net.optical.OpticalDevice"
@@ -112,11 +128,9 @@
         <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
                    impl="org.onosproject.drivers.odtn.CassiniFlowRuleProgrammable"/>
         <behaviour api="org.onosproject.net.behaviour.PowerConfig"
-                   impl="org.onosproject.drivers.odtn.CassiniTerminalDevicePowerConfig"/>
+                   impl="org.onosproject.drivers.odtn.CassiniTerminalDevicePowerConfigExt"/>
         <behaviour api="org.onosproject.net.behaviour.ModulationConfig"
                    impl="org.onosproject.drivers.odtn.CassiniModulationConfig"/>
->>>>>>> 0a7175b7ad... Adding modulation config with OcNos custom Behaviour and Cli command
->>>>>>> Adding modulation config with OcNos custom Behaviour and Cli command
     </driver>
     <driver name="nokia-1830" manufacturer="nokia" hwVersion="1830" swVersion="R10.1.1">
         <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
diff --git a/protocols/netconf/api/src/main/java/org/onosproject/netconf/AbstractNetconfSession.java b/protocols/netconf/api/src/main/java/org/onosproject/netconf/AbstractNetconfSession.java
index 7843f7d..359b04c 100644
--- a/protocols/netconf/api/src/main/java/org/onosproject/netconf/AbstractNetconfSession.java
+++ b/protocols/netconf/api/src/main/java/org/onosproject/netconf/AbstractNetconfSession.java
@@ -331,6 +331,16 @@
     }
 
     @Override
+    public boolean commit() throws NetconfException {
+        String rpc = "<rpc message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"> <commit/></rpc>";
+        String reply = requestSync(rpc);
+        if (!checkReply(reply)) {
+            throw new NetconfException("Request not successful, with reply " + reply);
+        }
+        return true;
+    }
+
+    @Override
     public boolean close() throws NetconfException {
         StringBuilder rpc = new StringBuilder();
         rpc.append(RPC_OPEN);
diff --git a/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfSession.java b/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfSession.java
index d0c80de..41ec065 100644
--- a/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfSession.java
+++ b/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfSession.java
@@ -302,6 +302,17 @@
     }
 
     /**
+     * Commits the candidate configuration the running configuration.
+     *
+     * @return true if successful.
+     * @throws NetconfException when there is a problem in the communication process on
+     * the underlying connection
+     */
+    default boolean commit() throws NetconfException {
+        return false;
+    }
+
+    /**
      * Closes the Netconf session with the device.
      * the first time it tries gracefully, then kills it forcefully
      *
diff --git a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfSessionMinaImpl.java b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfSessionMinaImpl.java
index 0a9f1aa..e89449e 100644
--- a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfSessionMinaImpl.java
+++ b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/impl/NetconfSessionMinaImpl.java
@@ -210,11 +210,11 @@
 
     private void startConnection() throws NetconfException {
         connectTimeout = deviceInfo.getConnectTimeoutSec().orElse(
-                                NetconfControllerImpl.netconfConnectTimeout);
+                NetconfControllerImpl.netconfConnectTimeout);
         replyTimeout = deviceInfo.getReplyTimeoutSec().orElse(
-                                NetconfControllerImpl.netconfReplyTimeout);
+                NetconfControllerImpl.netconfReplyTimeout);
         idleTimeout = deviceInfo.getIdleTimeoutSec().orElse(
-                                NetconfControllerImpl.netconfIdleTimeout);
+                NetconfControllerImpl.netconfIdleTimeout);
         log.info("Connecting to {} with timeouts C:{}, R:{}, I:{}", deviceInfo,
                 connectTimeout, replyTimeout, idleTimeout);
 
@@ -228,7 +228,7 @@
 
     private void startClient() throws IOException {
         log.info("Creating NETCONF session to {}",
-                 deviceInfo.getDeviceId());
+                deviceInfo.getDeviceId());
 
         client = SshClient.setUpDefaultClient();
         if (idleTimeout != NetconfControllerImpl.netconfIdleTimeout) {
@@ -514,13 +514,14 @@
         String reply = sendRequest(request, timeout);
         if (!checkReply(reply)) {
             throw new NetconfException("Request not successful with device "
-                                               + deviceInfo + " with reply " + reply);
+                    + deviceInfo + " with reply " + reply);
         }
         return reply;
     }
 
 
     // FIXME rename to align with what it actually do
+
     /**
      * Validate and format netconf message.
      * - NC1.0 if no EOM sequence present on {@code message}, append.
@@ -591,21 +592,21 @@
 
         log.debug("Sending {} to {}", rpc, this.deviceInfo.getDeviceId());
         return streamHandler.sendMessage(rpc, msgId)
-                    .handleAsync((reply, t) -> {
-                        if (t != null) {
-                            // secure transport-layer error
-                            // cannot use NetconfException, which is
-                            // checked Exception.
-                            throw new NetconfTransportException(t);
-                        } else {
-                            // FIXME avoid using checkReply, error handling is weird
-                            if (!checkReply(reply)) {
-                                throw new NetconfTransportException("rpc-request not successful with device "
-                                        + deviceInfo + " with reply " + reply);
-                            }
-                            return reply;
+                .handleAsync((reply, t) -> {
+                    if (t != null) {
+                        // secure transport-layer error
+                        // cannot use NetconfException, which is
+                        // checked Exception.
+                        throw new NetconfTransportException(t);
+                    } else {
+                        // FIXME avoid using checkReply, error handling is weird
+                        if (!checkReply(reply)) {
+                            throw new NetconfTransportException("rpc-request not successful with device "
+                                    + deviceInfo + " with reply " + reply);
                         }
-                    }, SharedExecutors.getPoolThreadExecutor());
+                        return reply;
+                    }
+                }, SharedExecutors.getPoolThreadExecutor());
     }
 
     @Override
@@ -653,7 +654,7 @@
         request = formatXmlHeader(request);
         request = formatRequestMessageId(request, messageId);
         log.debug("Sending request to NETCONF with timeout {} for {}",
-                  replyTimeout, deviceInfo.name());
+                replyTimeout, deviceInfo.name());
         CompletableFuture<String> futureReply = request(request, messageId);
         String rp;
         try {
@@ -714,6 +715,7 @@
 
     /**
      * Ensures xml start directive/declaration appears in the {@code request}.
+     *
      * @param request RPC request message
      * @return XML RPC message
      */