tom

Added commands to list paths.

Added protection against bad input on some command-lines.
...@@ -31,4 +31,14 @@ public abstract class AbstractShellCommand extends OsgiCommandSupport { ...@@ -31,4 +31,14 @@ public abstract class AbstractShellCommand extends OsgiCommandSupport {
31 System.out.println(String.format(format, args)); 31 System.out.println(String.format(format, args));
32 } 32 }
33 33
34 + /**
35 + * Prints the arguments using the specified format to error stream.
36 + *
37 + * @param format format string; see {@link String#format}
38 + * @param args arguments
39 + */
40 + public static void error(String format, Object... args) {
41 + System.err.println(String.format(format, args));
42 + }
43 +
34 } 44 }
......
...@@ -35,11 +35,16 @@ public class ClusterDevicesCommand extends ClustersListCommand { ...@@ -35,11 +35,16 @@ public class ClusterDevicesCommand extends ClustersListCommand {
35 int cid = Integer.parseInt(id); 35 int cid = Integer.parseInt(id);
36 init(); 36 init();
37 TopologyCluster cluster = service.getCluster(topology, clusterId(cid)); 37 TopologyCluster cluster = service.getCluster(topology, clusterId(cid));
38 - List<DeviceId> ids = Lists.newArrayList(service.getClusterDevices(topology, cluster)); 38 + if (cluster == null) {
39 - Collections.sort(ids, ID_COMPARATOR); 39 + error("No such cluster %s", cid);
40 - for (DeviceId deviceId : ids) { 40 + } else {
41 - print("%s", deviceId); 41 + List<DeviceId> ids = Lists.newArrayList(service.getClusterDevices(topology, cluster));
42 + Collections.sort(ids, ID_COMPARATOR);
43 + for (DeviceId deviceId : ids) {
44 + print("%s", deviceId);
45 + }
42 } 46 }
47 +
43 return null; 48 return null;
44 } 49 }
45 50
......
...@@ -24,8 +24,12 @@ public class ClusterLinksCommand extends ClustersListCommand { ...@@ -24,8 +24,12 @@ public class ClusterLinksCommand extends ClustersListCommand {
24 int cid = Integer.parseInt(id); 24 int cid = Integer.parseInt(id);
25 init(); 25 init();
26 TopologyCluster cluster = service.getCluster(topology, clusterId(cid)); 26 TopologyCluster cluster = service.getCluster(topology, clusterId(cid));
27 - for (Link link : service.getClusterLinks(topology, cluster)) { 27 + if (cluster == null) {
28 - print(linkString(link)); 28 + error("No such cluster %s", cid);
29 + } else {
30 + for (Link link : service.getClusterLinks(topology, cluster)) {
31 + print(linkString(link));
32 + }
29 } 33 }
30 return null; 34 return null;
31 } 35 }
......
...@@ -42,7 +42,12 @@ public class DevicePortsListCommand extends DevicesListCommand { ...@@ -42,7 +42,12 @@ public class DevicePortsListCommand extends DevicesListCommand {
42 printDevice(service, device); 42 printDevice(service, device);
43 } 43 }
44 } else { 44 } else {
45 - printDevice(service, service.getDevice(deviceId(uri))); 45 + Device device = service.getDevice(deviceId(uri));
46 + if (device == null) {
47 + error("No such device %s", uri);
48 + } else {
49 + printDevice(service, device);
50 + }
46 } 51 }
47 return null; 52 return null;
48 } 53 }
......
...@@ -56,10 +56,12 @@ public class DevicesListCommand extends AbstractShellCommand { ...@@ -56,10 +56,12 @@ public class DevicesListCommand extends AbstractShellCommand {
56 * @param device infrastructure device 56 * @param device infrastructure device
57 */ 57 */
58 protected void printDevice(DeviceService service, Device device) { 58 protected void printDevice(DeviceService service, Device device) {
59 - print(FMT, device.id(), service.isAvailable(device.id()), 59 + if (device != null) {
60 - service.getRole(device.id()), device.type(), 60 + print(FMT, device.id(), service.isAvailable(device.id()),
61 - device.manufacturer(), device.hwVersion(), device.swVersion(), 61 + service.getRole(device.id()), device.type(),
62 - device.serialNumber()); 62 + device.manufacturer(), device.hwVersion(), device.swVersion(),
63 + device.serialNumber());
64 + }
63 } 65 }
64 66
65 } 67 }
......
...@@ -16,6 +16,7 @@ import static org.onlab.onos.net.DeviceId.deviceId; ...@@ -16,6 +16,7 @@ import static org.onlab.onos.net.DeviceId.deviceId;
16 public class LinksListCommand extends AbstractShellCommand { 16 public class LinksListCommand extends AbstractShellCommand {
17 17
18 private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s"; 18 private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s";
19 + private static final String COMPACT = "%s/%s-%s/%s";
19 20
20 @Argument(index = 0, name = "uri", description = "Device ID", 21 @Argument(index = 0, name = "uri", description = "Device ID",
21 required = false, multiValued = false) 22 required = false, multiValued = false)
...@@ -43,4 +44,16 @@ public class LinksListCommand extends AbstractShellCommand { ...@@ -43,4 +44,16 @@ public class LinksListCommand extends AbstractShellCommand {
43 link.dst().deviceId(), link.dst().port(), link.type()); 44 link.dst().deviceId(), link.dst().port(), link.type());
44 45
45 } 46 }
47 +
48 + /**
49 + * Returns a compact string representing the given link.
50 + *
51 + * @param link infrastructure link
52 + * @return formatted link string
53 + */
54 + public static String compactLinkString(Link link) {
55 + return String.format(COMPACT, link.src().deviceId(), link.src().port(),
56 + link.dst().deviceId(), link.dst().port());
57 + }
58 +
46 } 59 }
......
...@@ -2,10 +2,12 @@ package org.onlab.onos.cli.net; ...@@ -2,10 +2,12 @@ package org.onlab.onos.cli.net;
2 2
3 import org.apache.karaf.shell.commands.Argument; 3 import org.apache.karaf.shell.commands.Argument;
4 import org.apache.karaf.shell.commands.Command; 4 import org.apache.karaf.shell.commands.Command;
5 +import org.onlab.onos.net.Link;
5 import org.onlab.onos.net.Path; 6 import org.onlab.onos.net.Path;
6 7
7 import java.util.Set; 8 import java.util.Set;
8 9
10 +import static org.onlab.onos.cli.net.LinksListCommand.compactLinkString;
9 import static org.onlab.onos.net.DeviceId.deviceId; 11 import static org.onlab.onos.net.DeviceId.deviceId;
10 12
11 /** 13 /**
...@@ -16,13 +18,13 @@ import static org.onlab.onos.net.DeviceId.deviceId; ...@@ -16,13 +18,13 @@ import static org.onlab.onos.net.DeviceId.deviceId;
16 description = "Lists all shortest-paths paths between the specified source and destination devices") 18 description = "Lists all shortest-paths paths between the specified source and destination devices")
17 public class PathListCommand extends TopologyCommand { 19 public class PathListCommand extends TopologyCommand {
18 20
19 - private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s"; 21 + private static final String SEP = "==>";
20 22
21 @Argument(index = 0, name = "src", description = "Source device ID", 23 @Argument(index = 0, name = "src", description = "Source device ID",
22 required = true, multiValued = false) 24 required = true, multiValued = false)
23 String src = null; 25 String src = null;
24 26
25 - @Argument(index = 0, name = "dst", description = "Destination device ID", 27 + @Argument(index = 1, name = "dst", description = "Destination device ID",
26 required = true, multiValued = false) 28 required = true, multiValued = false)
27 String dst = null; 29 String dst = null;
28 30
...@@ -36,8 +38,20 @@ public class PathListCommand extends TopologyCommand { ...@@ -36,8 +38,20 @@ public class PathListCommand extends TopologyCommand {
36 return null; 38 return null;
37 } 39 }
38 40
39 - private String pathString(Path path) { 41 + /**
40 - return path.toString(); 42 + * Produces a formatted string representing the specified path.
43 + *
44 + * @param path network path
45 + * @return formatted path string
46 + */
47 + protected String pathString(Path path) {
48 + StringBuilder sb = new StringBuilder();
49 + for (Link link : path.links()) {
50 + sb.append(compactLinkString(link)).append(SEP);
51 + }
52 + sb.delete(sb.lastIndexOf(SEP), sb.length());
53 + sb.append("; cost=").append(path.cost());
54 + return sb.toString();
41 } 55 }
42 56
43 } 57 }
......
...@@ -35,6 +35,12 @@ ...@@ -35,6 +35,12 @@
35 <action class="org.onlab.onos.cli.net.TopologyCommand"/> 35 <action class="org.onlab.onos.cli.net.TopologyCommand"/>
36 </command> 36 </command>
37 <command> 37 <command>
38 + <action class="org.onlab.onos.cli.net.PathListCommand"/>
39 + <completers>
40 + <ref component-id="deviceIdCompleter"/>
41 + </completers>
42 + </command>
43 + <command>
38 <action class="org.onlab.onos.cli.net.ClustersListCommand"/> 44 <action class="org.onlab.onos.cli.net.ClustersListCommand"/>
39 </command> 45 </command>
40 <command> 46 <command>
......