CLI to add ProtectedTransportIntent

+ debug tool to install ProtectionEndpointIntent (installable Intent)

Change-Id: Ib9d5b37e624db497c1aa76d4cfa08af971002c7e
diff --git a/cli/src/main/java/org/onosproject/cli/net/AddProtectedTransportIntentCommand.java b/cli/src/main/java/org/onosproject/cli/net/AddProtectedTransportIntentCommand.java
new file mode 100644
index 0000000..faa3405
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/AddProtectedTransportIntentCommand.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.cli.net;
+
+import java.util.Optional;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.ProtectedTransportIntent;
+
+/**
+ * Installs ProtectedTransportIntent.
+ */
+@Command(scope = "onos", name = "add-protected-transport",
+         description = "Adds ProtectedTransportIntent")
+public class AddProtectedTransportIntentCommand
+    extends AbstractShellCommand {
+
+    @Option(name = "--key", aliases = "-k",
+            description = "Intent key",
+            required = false, multiValued = false)
+    private String keyStr = null;
+
+    @Argument(index = 0, name = "deviceId1",
+            description = "First Device ID of protected path",
+            required = true, multiValued = false)
+    private String deviceId1Str = null;
+
+    @Argument(index = 1, name = "deviceId2",
+            description = "Second Device ID of protected path",
+            required = true, multiValued = false)
+    private String deviceId2Str = null;
+
+    private IntentService intentService;
+
+    @Override
+    protected void execute() {
+        intentService = get(IntentService.class);
+
+        DeviceId did1 = DeviceId.deviceId(deviceId1Str);
+        DeviceId did2 = DeviceId.deviceId(deviceId2Str);
+
+        Intent intent;
+        intent = ProtectedTransportIntent.builder()
+                .key(key())
+                .appId(appId())
+                .one(did1)
+                .two(did2)
+                .build();
+
+        print("Submitting: %s", intent);
+        intentService.submit(intent);
+    }
+
+    /**
+     * Returns Key if specified in the option.
+     *
+     * @return Key instance or null
+     */
+    protected Key key() {
+        return Optional.ofNullable(keyStr)
+                    .map(s -> Key.of(s, appId()))
+                    .orElse(null);
+    }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/TestProtectionEndpointIntentCommand.java b/cli/src/main/java/org/onosproject/cli/net/TestProtectionEndpointIntentCommand.java
new file mode 100644
index 0000000..8189990
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/TestProtectionEndpointIntentCommand.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.cli.net;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.VlanId;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointDescription;
+import org.onosproject.net.behaviour.protection.TransportEndpointDescription;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.ProtectionEndpointIntent;
+
+/**
+ * Test tool to add ProtectionEndpointIntent.
+ */
+@Command(scope = "onos", name = "test-add-protection-endpoint",
+         description = "Test tool to add ProtectionEndpointIntent")
+public class TestProtectionEndpointIntentCommand extends AbstractShellCommand {
+
+    private static final String DEFAULT_FINGERPRINT = "[fingerprint]";
+
+    @Option(name = "--fingerprint",
+            description = "Fingerprint to identify the protected transport entity",
+            valueToShowInHelp = DEFAULT_FINGERPRINT)
+    private String fingerprint = DEFAULT_FINGERPRINT;
+
+    @Argument(index = 0, name = "deviceId",
+            description = "Device ID to configure",
+            required = true)
+    private String deviceIdStr = null;
+
+    @Argument(index = 1, name = "peerDeviceId",
+            description = "Device ID of remote peer",
+            required = true)
+    private String peerStr = null;
+
+    @Argument(index = 2, name = "portNumber1",
+            description = "PortNumber leading to working path on deviceId",
+            required = true)
+    private String portNumber1Str = null;
+
+    @Argument(index = 3, name = "portNumber2",
+            description = "PortNumber leading to standby path on deviceId",
+            required = true)
+    private String portNumber2Str = null;
+
+    @Option(name = "--vlan1",
+            description = "VLAN ID to push on portNumber1 expressed in decimal")
+    private String vlan1Str = null;
+
+    @Option(name = "--vlan2",
+            description = "VLAN ID to push on portNumber2 expressed in decimal")
+    private String vlan2Str = null;
+
+    private IntentService intentService;
+    private DeviceService deviceService;
+
+    @Override
+    protected void execute() {
+        fingerprint = Optional.ofNullable(fingerprint)
+                              .orElse(DEFAULT_FINGERPRINT);
+
+        intentService = get(IntentService.class);
+        deviceService = get(DeviceService.class);
+
+        DeviceId did = DeviceId.deviceId(deviceIdStr);
+        DeviceId peer = DeviceId.deviceId(peerStr);
+
+        ProtectedTransportEndpointDescription description;
+        List<TransportEndpointDescription> paths = new ArrayList<>();
+
+        paths.add(TransportEndpointDescription.builder()
+                  .withOutput(output(did, portNumber1Str, vlan1Str))
+                  .build());
+        paths.add(TransportEndpointDescription.builder()
+                  .withOutput(output(did, portNumber2Str, vlan2Str))
+                  .build());
+
+        description = ProtectedTransportEndpointDescription.of(paths, peer, fingerprint);
+
+        ProtectionEndpointIntent intent;
+        intent = ProtectionEndpointIntent.builder()
+                .key(Key.of(fingerprint, appId()))
+                .appId(appId())
+                .deviceId(did)
+                .description(description)
+                .build();
+        print("Submitting: %s", intent);
+        intentService.submit(intent);
+    }
+
+    private FilteredConnectPoint output(DeviceId did, String portNumberStr, String vlanStr) {
+        ConnectPoint cp = new ConnectPoint(did,
+                                           PortNumber.fromString(portNumberStr));
+        if (deviceService.getPort(cp) == null) {
+            print("Unknown port: %s", cp);
+        }
+
+        if (vlanStr == null) {
+            return new FilteredConnectPoint(cp);
+        } else {
+            VlanId vlan = VlanId.vlanId(vlanStr);
+            TrafficSelector sel = DefaultTrafficSelector.builder()
+                    .matchVlanId(vlan)
+                    .build();
+
+            return new FilteredConnectPoint(cp, sel);
+
+        }
+    }
+
+}
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 03eede3..ad54204 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -394,6 +394,24 @@
         </command>
 
         <command>
+            <action class="org.onosproject.cli.net.TestProtectionEndpointIntentCommand"/>
+            <completers>
+                <ref component-id="deviceIdCompleter"/>
+                <ref component-id="deviceIdCompleter"/>
+                <null/>
+            </completers>
+        </command>
+
+        <command>
+            <action class="org.onosproject.cli.net.AddProtectedTransportIntentCommand"/>
+            <completers>
+                <ref component-id="deviceIdCompleter"/>
+                <ref component-id="deviceIdCompleter"/>
+                <null/>
+            </completers>
+        </command>
+
+        <command>
             <action class="org.onosproject.cli.net.ClustersListCommand"/>
         </command>
         <command>