Thomas Vachuska

Added CLI support for showing key/value annotations for devices, ports, links & hosts.

......@@ -18,10 +18,13 @@
*/
package org.onlab.onos.cli;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Option;
import org.apache.karaf.shell.console.OsgiCommandSupport;
import org.onlab.onos.ApplicationId;
import org.onlab.onos.CoreService;
import org.onlab.onos.net.Annotations;
import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.osgi.ServiceNotFoundException;
......@@ -76,6 +79,34 @@ public abstract class AbstractShellCommand extends OsgiCommandSupport {
}
/**
* Produces a string image of the specified key/value annotations.
*
* @param annotations key/value annotations
* @return string image with ", k1=v1, k2=v2, ..." pairs
*/
public static String annotations(Annotations annotations) {
StringBuilder sb = new StringBuilder();
for (String key : annotations.keys()) {
sb.append(", ").append(key).append('=').append(annotations.value(key));
}
return sb.toString();
}
/**
* Produces a JSON object from the specified key/value annotations.
*
* @param annotations key/value annotations
* @return JSON object
*/
public static ObjectNode annotations(ObjectMapper mapper, Annotations annotations) {
ObjectNode result = mapper.createObjectNode();
for (String key : annotations.keys()) {
result.put(key, annotations.value(key));
}
return result;
}
/**
* Executes this command.
*/
protected abstract void execute();
......
......@@ -43,7 +43,7 @@ import static org.onlab.onos.net.DeviceId.deviceId;
description = "Lists all ports or all ports of a device")
public class DevicePortsListCommand extends DevicesListCommand {
private static final String FMT = " port=%s, state=%s";
private static final String FMT = " port=%s, state=%s%s";
@Option(name = "-e", aliases = "--enabled", description = "Show only enabled ports",
required = false, multiValued = false)
......@@ -112,7 +112,8 @@ public class DevicePortsListCommand extends DevicesListCommand {
if (isIncluded(port)) {
ports.add(mapper.createObjectNode()
.put("port", port.number().toString())
.put("isEnabled", port.isEnabled()));
.put("isEnabled", port.isEnabled())
.set("annotations", annotations(mapper, port.annotations())));
}
}
return result.put("device", device.id().toString()).set("ports", ports);
......@@ -131,7 +132,8 @@ public class DevicePortsListCommand extends DevicesListCommand {
Collections.sort(ports, Comparators.PORT_COMPARATOR);
for (Port port : ports) {
if (isIncluded(port)) {
print(FMT, port.number(), port.isEnabled() ? "enabled" : "disabled");
print(FMT, port.number(), port.isEnabled() ? "enabled" : "disabled",
annotations(port.annotations()));
}
}
}
......
......@@ -41,7 +41,7 @@ import static com.google.common.collect.Lists.newArrayList;
public class DevicesListCommand extends AbstractShellCommand {
private static final String FMT =
"id=%s, available=%s, role=%s, type=%s, mfr=%s, hw=%s, sw=%s, serial=%s";
"id=%s, available=%s, role=%s, type=%s, mfr=%s, hw=%s, sw=%s, serial=%s%s";
@Override
protected void execute() {
......@@ -89,7 +89,8 @@ public class DevicesListCommand extends AbstractShellCommand {
.put("mfr", device.manufacturer())
.put("hw", device.hwVersion())
.put("sw", device.swVersion())
.put("serial", device.serialNumber());
.put("serial", device.serialNumber())
.set("annotations", annotations(mapper, device.annotations()));
}
return result;
}
......@@ -117,7 +118,7 @@ public class DevicesListCommand extends AbstractShellCommand {
print(FMT, device.id(), service.isAvailable(device.id()),
service.getRole(device.id()), device.type(),
device.manufacturer(), device.hwVersion(), device.swVersion(),
device.serialNumber());
device.serialNumber(), annotations(device.annotations()));
}
}
......
......@@ -42,7 +42,7 @@ import static com.google.common.collect.Lists.newArrayList;
public class HostsListCommand extends AbstractShellCommand {
private static final String FMT =
"id=%s, mac=%s, location=%s/%s, vlan=%s, ip(s)=%s";
"id=%s, mac=%s, location=%s/%s, vlan=%s, ip(s)=%s%s";
@Override
protected void execute() {
......@@ -80,6 +80,7 @@ public class HostsListCommand extends AbstractShellCommand {
.put("vlan", host.vlan().toString());
result.set("location", loc);
result.set("ips", ips);
result.set("annotations", annotations(mapper, host.annotations()));
return result;
}
......@@ -105,7 +106,8 @@ public class HostsListCommand extends AbstractShellCommand {
print(FMT, host.id(), host.mac(),
host.location().deviceId(),
host.location().port(),
host.vlan(), host.ipAddresses());
host.vlan(), host.ipAddresses(),
annotations(host.annotations()));
}
}
}
......
......@@ -38,7 +38,7 @@ import static org.onlab.onos.net.DeviceId.deviceId;
description = "Lists all infrastructure links")
public class LinksListCommand extends AbstractShellCommand {
private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s";
private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s";
private static final String COMPACT = "%s/%s-%s/%s";
@Argument(index = 0, name = "uri", description = "Device ID",
......@@ -85,6 +85,7 @@ public class LinksListCommand extends AbstractShellCommand {
ObjectNode result = mapper.createObjectNode();
result.set("src", json(mapper, link.src()));
result.set("dst", json(mapper, link.dst()));
result.set("annotations", annotations(mapper, link.annotations()));
return result;
}
......@@ -109,7 +110,8 @@ public class LinksListCommand extends AbstractShellCommand {
*/
public static String linkString(Link link) {
return String.format(FMT, link.src().deviceId(), link.src().port(),
link.dst().deviceId(), link.dst().port(), link.type());
link.dst().deviceId(), link.dst().port(), link.type(),
annotations(link.annotations()));
}
/**
......