CORD-613 Adding ability to administratively enable or disable a port via CLI.
Currently uses the OpenFlow device provider to change portState.
Also fixes a bug in PortNumberCompleter.
Adds completion options to portstats for deviceId and portNumber.
Change-Id: Idcce775fe8bc5484fdd0e630bcb5026b85125478
diff --git a/cli/src/main/java/org/onosproject/cli/net/AnnotateDeviceCommand.java b/cli/src/main/java/org/onosproject/cli/net/AnnotateDeviceCommand.java
index 113fe31..9e89ff0 100644
--- a/cli/src/main/java/org/onosproject/cli/net/AnnotateDeviceCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/AnnotateDeviceCommand.java
@@ -22,6 +22,7 @@
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceProvider;
@@ -100,5 +101,10 @@
public boolean isReachable(DeviceId deviceId) {
return false;
}
+
+ @Override
+ public void changePortState(DeviceId deviceId, PortNumber portNumber,
+ boolean enable) {
+ }
}
}
diff --git a/cli/src/main/java/org/onosproject/cli/net/DevicePortStateCommand.java b/cli/src/main/java/org/onosproject/cli/net/DevicePortStateCommand.java
new file mode 100644
index 0000000..3962266
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/DevicePortStateCommand.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 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 org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceAdminService;
+import org.onosproject.net.device.DeviceService;
+
+/**
+ * Administratively enables or disabled a port on a device.
+ */
+@Command(scope = "onos", name = "portstate",
+ description = "Administratively enables or disabled a port on a device")
+public class DevicePortStateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "uri", description = "Device ID",
+ required = true, multiValued = false)
+ String uri = null;
+
+ @Argument(index = 1, name = "portNumber", description = "Port Number",
+ required = true, multiValued = false)
+ Integer portNumber = null;
+
+ @Argument(index = 2, name = "portState", description = "Desired State",
+ required = true, multiValued = false)
+ String portState = null;
+
+ @Override
+ protected void execute() {
+ DeviceService deviceService = get(DeviceService.class);
+ DeviceAdminService deviceAdminService = get(DeviceAdminService.class);
+ Device dev = deviceService.getDevice(DeviceId.deviceId(uri));
+ if (dev == null) {
+ print(" %s", "Device does not exist");
+ return;
+ }
+ PortNumber pnum = PortNumber.portNumber(portNumber);
+ Port p = deviceService.getPort(dev.id(), pnum);
+ if (p == null) {
+ print(" %s", "Port does not exist");
+ return;
+ }
+ if (portState.equals("enable")) {
+ deviceAdminService.changePortState(dev.id(), pnum, true);
+ } else if (portState.equals("disable")) {
+ deviceAdminService.changePortState(dev.id(), pnum, false);
+ } else {
+ print(" %s", "State must be enable or disable");
+ }
+ }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/DevicePortStatsCommand.java b/cli/src/main/java/org/onosproject/cli/net/DevicePortStatsCommand.java
index f9a8237..33ac366 100644
--- a/cli/src/main/java/org/onosproject/cli/net/DevicePortStatsCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/DevicePortStatsCommand.java
@@ -50,6 +50,10 @@
required = false, multiValued = false)
String uri = null;
+ @Argument(index = 1, name = "portNumber", description = "Port Number",
+ required = false, multiValued = false)
+ Integer portNumber = null;
+
private static final String FORMAT =
" port=%s, pktRx=%s, pktTx=%s, bytesRx=%s, bytesTx=%s, pktRxDrp=%s, pktTxDrp=%s, Dur=%s";
@@ -94,6 +98,9 @@
private void printPortStats(DeviceId deviceId, Iterable<PortStatistics> portStats) {
print("deviceId=%s", deviceId);
for (PortStatistics stat : sortByPort(portStats)) {
+ if (portNumber != null && stat.port() != portNumber) {
+ continue;
+ }
print(FORMAT, stat.port(), stat.packetsReceived(), stat.packetsSent(), stat.bytesReceived(),
stat.bytesSent(), stat.packetsRxDropped(), stat.packetsTxDropped(), stat.durationSec());
}
@@ -109,6 +116,9 @@
+ " rateRx=%s, rateTx=%s, pktRxDrp=%s, pktTxDrp=%s, interval=%s";
print("deviceId=%s", deviceId);
for (PortStatistics stat : sortByPort(portStats)) {
+ if (portNumber != null && stat.port() != portNumber) {
+ continue;
+ }
float duration = ((float) stat.durationSec()) +
(((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1));
float rateRx = stat.bytesReceived() * 8 / duration;
@@ -142,21 +152,24 @@
print("|---------------------------------------------------------------------------------------------------|");
for (PortStatistics stat : sortByPort(portStats)) {
- float duration = ((float) stat.durationSec()) +
- (((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1));
- float rateRx = stat.bytesReceived() * 8 / duration;
- float rateTx = stat.bytesSent() * 8 / duration;
- print(formatDeltaTable, stat.port(),
- humanReadable(stat.packetsReceived()),
- humanReadable(stat.bytesReceived()),
- humanReadableBps(rateRx),
- humanReadable(stat.packetsRxDropped()),
- humanReadable(stat.packetsSent()),
- humanReadable(stat.bytesSent()),
- humanReadableBps(rateTx),
- humanReadable(stat.packetsTxDropped()),
- String.format("%.3f", duration));
+ if (portNumber != null && stat.port() != portNumber) {
+ continue;
}
+ float duration = ((float) stat.durationSec()) +
+ (((float) stat.durationNano()) / TimeUnit.SECONDS.toNanos(1));
+ float rateRx = stat.bytesReceived() * 8 / duration;
+ float rateTx = stat.bytesSent() * 8 / duration;
+ print(formatDeltaTable, stat.port(),
+ humanReadable(stat.packetsReceived()),
+ humanReadable(stat.bytesReceived()),
+ humanReadableBps(rateRx),
+ humanReadable(stat.packetsRxDropped()),
+ humanReadable(stat.packetsSent()),
+ humanReadable(stat.bytesSent()),
+ humanReadableBps(rateTx),
+ humanReadable(stat.packetsTxDropped()),
+ String.format("%.3f", duration));
+ }
print("+---------------------------------------------------------------------------------------------------+");
}
diff --git a/cli/src/main/java/org/onosproject/cli/net/PortNumberCompleter.java b/cli/src/main/java/org/onosproject/cli/net/PortNumberCompleter.java
index 0a05d31..949f4f8 100644
--- a/cli/src/main/java/org/onosproject/cli/net/PortNumberCompleter.java
+++ b/cli/src/main/java/org/onosproject/cli/net/PortNumberCompleter.java
@@ -15,15 +15,16 @@
*/
package org.onosproject.cli.net;
-import static com.google.common.base.Preconditions.checkArgument;
import static org.onlab.osgi.DefaultServiceDirectory.getService;
+import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.karaf.shell.console.completer.ArgumentCompleter.ArgumentList;
import org.onosproject.cli.AbstractChoicesCompleter;
+import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
@@ -37,13 +38,22 @@
@Override
protected List<String> choices() {
ArgumentList args = getArgumentList();
- checkArgument(args.getCursorArgumentIndex() >= 1,
- "Expects DeviceId as previous argument");
-
- String deviceIdStr = args.getArguments()[args.getCursorArgumentIndex() - 1];
- DeviceId deviceId = DeviceId.deviceId(deviceIdStr);
-
+ //parse argument list for deviceId
DeviceService deviceService = getService(DeviceService.class);
+ Device dev = null;
+ for (String str : args.getArguments()) {
+ if (str.contains(":")) {
+ dev = deviceService.getDevice(DeviceId.deviceId(str));
+ if (dev != null) {
+ break;
+ }
+ }
+ }
+ if (dev == null) {
+ return Collections.singletonList("Missing device");
+ }
+ DeviceId deviceId = dev.id();
+
return StreamSupport.stream(deviceService.getPorts(deviceId).spliterator(), false)
.map(port -> port.number().toString())
.collect(Collectors.toList());
diff --git a/cli/src/main/java/org/onosproject/cli/net/PortStateCompleter.java b/cli/src/main/java/org/onosproject/cli/net/PortStateCompleter.java
new file mode 100644
index 0000000..e9accbe
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/PortStateCompleter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 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.List;
+
+import org.onosproject.cli.AbstractChoicesCompleter;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * PortState completer.
+ *
+ * Assumes argument right before the one being completed is PortNumber.
+ */
+public class PortStateCompleter extends AbstractChoicesCompleter {
+
+ @Override
+ protected List<String> choices() {
+ return ImmutableList.of("enable", "disable");
+ }
+}