blob: 78d5c46bd11cae76f067ea7df75a0729cc78af94 [file] [log] [blame]
Thomas Vachuska7d693f52014-10-21 19:17:57 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska7d693f52014-10-21 19:17:57 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska7d693f52014-10-21 19:17:57 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska7d693f52014-10-21 19:17:57 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.cli.net;
tom613d8142014-09-11 15:09:37 -070017
tomc65fa112014-10-16 07:48:47 -070018import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.ObjectMapper;
20import com.fasterxml.jackson.databind.node.ArrayNode;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070021import org.apache.karaf.shell.api.action.Argument;
22import org.apache.karaf.shell.api.action.Command;
23import org.apache.karaf.shell.api.action.lifecycle.Service;
24import org.apache.karaf.shell.api.action.Option;
Ray Milkey3078fc02015-05-06 16:14:14 -070025import org.onosproject.cli.AbstractShellCommand;
Yuta HIGUCHI33485fb2017-01-25 20:13:30 -080026import org.onosproject.net.DeviceId;
27import org.onosproject.net.DisjointPath;
Brian O'Connorabafb502014-12-02 22:26:20 -080028import org.onosproject.net.Link;
29import org.onosproject.net.Path;
Yuta HIGUCHI33485fb2017-01-25 20:13:30 -080030import org.onosproject.net.device.DeviceService;
tom613d8142014-09-11 15:09:37 -070031
32import java.util.Set;
33
Brian O'Connorabafb502014-12-02 22:26:20 -080034import static org.onosproject.cli.net.LinksListCommand.compactLinkString;
35import static org.onosproject.net.DeviceId.deviceId;
tom613d8142014-09-11 15:09:37 -070036
37/**
38 * Lists all shortest-paths paths between the specified source and
39 * destination devices.
40 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070041@Service
tom613d8142014-09-11 15:09:37 -070042@Command(scope = "onos", name = "paths",
43 description = "Lists all shortest-paths paths between the specified source and destination devices")
44public class PathListCommand extends TopologyCommand {
45
tom9eb57fb2014-09-11 19:42:38 -070046 private static final String SEP = "==>";
tom613d8142014-09-11 15:09:37 -070047
48 @Argument(index = 0, name = "src", description = "Source device ID",
49 required = true, multiValued = false)
50 String src = null;
51
tom9eb57fb2014-09-11 19:42:38 -070052 @Argument(index = 1, name = "dst", description = "Destination device ID",
tom613d8142014-09-11 15:09:37 -070053 required = true, multiValued = false)
54 String dst = null;
55
Yuta HIGUCHI33485fb2017-01-25 20:13:30 -080056 @Option(name = "--disjoint", description = "Show disjoint Paths")
57 boolean disjoint = false;
58
tom613d8142014-09-11 15:09:37 -070059 @Override
Ray Milkeyd84f89b2018-08-17 14:54:17 -070060 protected void doExecute() {
tom613d8142014-09-11 15:09:37 -070061 init();
Yuta HIGUCHI33485fb2017-01-25 20:13:30 -080062 DeviceService deviceService = get(DeviceService.class);
63 DeviceId srcDid = deviceId(src);
64 if (deviceService.getDevice(srcDid) == null) {
65 print("Unknown device %s", src);
Ayaka Koshibee018a922016-01-19 15:53:37 -080066 return;
67 }
Yuta HIGUCHI33485fb2017-01-25 20:13:30 -080068 DeviceId dstDid = deviceId(dst);
69 if (deviceService.getDevice(dstDid) == null) {
70 print("Unknown device %s", dst);
71 return;
72 }
73 Set<? extends Path> paths;
74 if (disjoint) {
75 paths = service.getDisjointPaths(topology, srcDid, dstDid);
76 } else {
77 paths = service.getPaths(topology, srcDid, dstDid);
78 }
tomc65fa112014-10-16 07:48:47 -070079 if (outputJson()) {
Ray Milkey3078fc02015-05-06 16:14:14 -070080 print("%s", json(this, paths));
tomc65fa112014-10-16 07:48:47 -070081 } else {
82 for (Path path : paths) {
83 print(pathString(path));
Yuta HIGUCHI33485fb2017-01-25 20:13:30 -080084 if (path instanceof DisjointPath) {
85 // print backup right after primary
86 print(pathString(((DisjointPath) path).backup()));
87 }
tomc65fa112014-10-16 07:48:47 -070088 }
tom613d8142014-09-11 15:09:37 -070089 }
tom613d8142014-09-11 15:09:37 -070090 }
91
tom9eb57fb2014-09-11 19:42:38 -070092 /**
tomc65fa112014-10-16 07:48:47 -070093 * Produces a JSON array containing the specified paths.
94 *
Ray Milkey3078fc02015-05-06 16:14:14 -070095 * @param context context to use for looking up codecs
tomc65fa112014-10-16 07:48:47 -070096 * @param paths collection of paths
97 * @return JSON array
98 */
Yuta HIGUCHI33485fb2017-01-25 20:13:30 -080099 public static JsonNode json(AbstractShellCommand context,
100 Iterable<? extends Path> paths) {
101 ObjectMapper mapper = context.mapper();
tomc65fa112014-10-16 07:48:47 -0700102 ArrayNode result = mapper.createArrayNode();
103 for (Path path : paths) {
Ray Milkey3078fc02015-05-06 16:14:14 -0700104 result.add(LinksListCommand.json(context, path)
105 .put("cost", path.cost())
106 .set("links", LinksListCommand.json(context, path.links())));
Yuta HIGUCHI33485fb2017-01-25 20:13:30 -0800107
108 if (path instanceof DisjointPath) {
109 // [ (primay), (backup), ...]
110 DisjointPath backup = (DisjointPath) path;
111 result.add(LinksListCommand.json(context, backup.backup())
112 .put("cost", backup.cost())
113 .set("links", LinksListCommand.json(context, backup.links())));
114 }
tomc65fa112014-10-16 07:48:47 -0700115 }
116 return result;
117 }
118
119 /**
tom9eb57fb2014-09-11 19:42:38 -0700120 * Produces a formatted string representing the specified path.
121 *
122 * @param path network path
123 * @return formatted path string
124 */
125 protected String pathString(Path path) {
126 StringBuilder sb = new StringBuilder();
127 for (Link link : path.links()) {
128 sb.append(compactLinkString(link)).append(SEP);
129 }
130 sb.delete(sb.lastIndexOf(SEP), sb.length());
131 sb.append("; cost=").append(path.cost());
132 return sb.toString();
tom613d8142014-09-11 15:09:37 -0700133 }
134
135}