blob: 0a4329f9dab42ada9e5b9ac60ea50f06ea231896 [file] [log] [blame]
HIGUCHI Yuta9092db82016-01-03 18:45:01 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
HIGUCHI Yuta9092db82016-01-03 18:45:01 -08003 *
4 * 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
7 *
8 * 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.
15 */
16package org.onosproject.events;
17
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080018import java.io.PrintWriter;
19import java.io.StringWriter;
20import java.util.List;
21import java.util.function.Predicate;
22import java.util.stream.Collector;
23import java.util.stream.Stream;
24
Ray Milkey86ad7bb2018-09-27 12:32:28 -070025import org.apache.karaf.shell.api.action.Command;
26import org.apache.karaf.shell.api.action.Option;
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -070027import org.onlab.util.Tools;
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080028import org.onosproject.cli.AbstractShellCommand;
29import org.onosproject.cluster.ClusterEvent;
30import org.onosproject.event.Event;
31import org.onosproject.mastership.MastershipEvent;
32import org.onosproject.net.Link;
33import org.onosproject.net.device.DeviceEvent;
34import org.onosproject.net.host.HostEvent;
Jon Halld66228c2017-08-09 11:24:24 -070035import org.onosproject.net.intent.IntentEvent;
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080036import org.onosproject.net.link.LinkEvent;
37import org.onosproject.net.topology.Topology;
38import org.onosproject.net.topology.TopologyEvent;
39
40import com.fasterxml.jackson.core.JsonProcessingException;
41import com.fasterxml.jackson.databind.JsonNode;
42import com.fasterxml.jackson.databind.node.ArrayNode;
43import com.fasterxml.jackson.databind.node.ObjectNode;
44import com.google.common.base.MoreObjects;
45import com.google.common.collect.ImmutableList;
46
Ray Milkey9f87e512016-01-05 10:00:22 -080047import static java.util.stream.Collectors.toList;
Ray Milkey9f87e512016-01-05 10:00:22 -080048
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080049/**
50 * Command to print history of instance local ONOS Events.
51 */
52@Command(scope = "onos", name = "events",
53 description = "Command to print history of instance local ONOS Events")
54public class EventsCommand
55 extends AbstractShellCommand {
56
57 @Option(name = "--all", aliases = "-a",
58 description = "Include all Events (default behavior)",
59 required = false)
60 private boolean all = false;
61
62 @Option(name = "--mastership", aliases = "-m",
63 description = "Include MastershipEvent",
64 required = false)
65 private boolean mastership = false;
66
67 @Option(name = "--device", aliases = "-d",
68 description = "Include DeviceEvent",
69 required = false)
70 private boolean device = false;
71
72 @Option(name = "--link", aliases = "-l",
73 description = "Include LinkEvent",
74 required = false)
75 private boolean link = false;
76
77 @Option(name = "--topology", aliases = "-t",
78 description = "Include TopologyEvent",
79 required = false)
80 private boolean topology = false;
81
Jon Halld66228c2017-08-09 11:24:24 -070082 @Option(name = "--host", aliases = "-h",
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080083 description = "Include HostEvent",
84 required = false)
85 private boolean host = false;
86
87 @Option(name = "--cluster", aliases = "-c",
88 description = "Include ClusterEvent",
89 required = false)
90 private boolean cluster = false;
91
Jon Halld66228c2017-08-09 11:24:24 -070092 @Option(name = "--intent", aliases = "-i",
93 description = "Include IntentEvent",
94 required = false)
95 private boolean intent = false;
96
HIGUCHI Yuta9092db82016-01-03 18:45:01 -080097 @Option(name = "--max-events", aliases = "-n",
98 description = "Maximum number of events to print",
99 required = false,
100 valueToShowInHelp = "-1 [no limit]")
101 private long maxSize = -1;
102
103 @Override
Ray Milkey86ad7bb2018-09-27 12:32:28 -0700104 protected void doExecute() {
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800105 EventHistoryService eventHistoryService = get(EventHistoryService.class);
106
107 Stream<Event<?, ?>> events = eventHistoryService.history().stream();
108
Jon Halld66228c2017-08-09 11:24:24 -0700109 boolean dumpAll = all || !(mastership || device || link || topology || host || cluster || intent);
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800110
111 if (!dumpAll) {
112 Predicate<Event<?, ?>> filter = (defaultIs) -> false;
113
114 if (mastership) {
115 filter = filter.or(evt -> evt instanceof MastershipEvent);
116 }
117 if (device) {
118 filter = filter.or(evt -> evt instanceof DeviceEvent);
119 }
120 if (link) {
121 filter = filter.or(evt -> evt instanceof LinkEvent);
122 }
123 if (topology) {
124 filter = filter.or(evt -> evt instanceof TopologyEvent);
125 }
126 if (host) {
127 filter = filter.or(evt -> evt instanceof HostEvent);
128 }
129 if (cluster) {
130 filter = filter.or(evt -> evt instanceof ClusterEvent);
131 }
Jon Halld66228c2017-08-09 11:24:24 -0700132 if (intent) {
133 filter = filter.or(evt -> evt instanceof IntentEvent);
134 }
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800135
136 events = events.filter(filter);
137 }
138
139 if (maxSize > 0) {
140 events = events.limit(maxSize);
141 }
142
143 if (outputJson()) {
144 ArrayNode jsonEvents = events.map(this::json).collect(toArrayNode());
145 printJson(jsonEvents);
146 } else {
147 events.forEach(this::printEvent);
148 }
149
150 }
151
152 private Collector<JsonNode, ArrayNode, ArrayNode> toArrayNode() {
153 return Collector.of(() -> mapper().createArrayNode(),
154 ArrayNode::add,
155 ArrayNode::addAll);
156 }
157
158 private ObjectNode json(Event<?, ?> event) {
159 ObjectNode result = mapper().createObjectNode();
160
161 result.put("time", event.time())
162 .put("type", event.type().toString())
163 .put("event", event.toString());
164
165 return result;
166 }
167
168 /**
169 * Print JsonNode using default pretty printer.
170 *
171 * @param json JSON node to print
172 */
Ray Milkeyaef45852016-01-11 17:13:19 -0800173 @java.lang.SuppressWarnings("squid:S1148")
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800174 private void printJson(JsonNode json) {
175 try {
176 print("%s", mapper().writerWithDefaultPrettyPrinter().writeValueAsString(json));
177 } catch (JsonProcessingException e) {
178 StringWriter sw = new StringWriter();
179 e.printStackTrace(new PrintWriter(sw));
180 print("[ERROR] %s\n%s", e.getMessage(), sw.toString());
181 }
182 }
183
184 private void printEvent(Event<?, ?> event) {
185 if (event instanceof DeviceEvent) {
186 DeviceEvent deviceEvent = (DeviceEvent) event;
187 if (event.type().toString().startsWith("PORT")) {
188 // Port event
189 print("%s %s\t%s/%s [%s]",
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700190 Tools.defaultOffsetDataTime(event.time()),
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800191 event.type(),
192 deviceEvent.subject().id(), deviceEvent.port().number(),
193 deviceEvent.port()
194 );
195 } else {
196 // Device event
197 print("%s %s\t%s [%s]",
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700198 Tools.defaultOffsetDataTime(event.time()),
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800199 event.type(),
200 deviceEvent.subject().id(),
201 deviceEvent.subject()
202 );
203 }
204
205 } else if (event instanceof MastershipEvent) {
206 print("%s %s\t%s [%s]",
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700207 Tools.defaultOffsetDataTime(event.time()),
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800208 event.type(),
209 event.subject(),
210 ((MastershipEvent) event).roleInfo());
211
212 } else if (event instanceof LinkEvent) {
213 LinkEvent linkEvent = (LinkEvent) event;
214 Link link = linkEvent.subject();
215 print("%s %s\t%s/%s-%s/%s [%s]",
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700216 Tools.defaultOffsetDataTime(event.time()),
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800217 event.type(),
218 link.src().deviceId(), link.src().port(), link.dst().deviceId(), link.dst().port(),
219 link);
220
221 } else if (event instanceof HostEvent) {
222 HostEvent hostEvent = (HostEvent) event;
223 print("%s %s\t%s [%s->%s]",
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700224 Tools.defaultOffsetDataTime(event.time()),
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800225 event.type(),
226 hostEvent.subject().id(),
227 hostEvent.prevSubject(), hostEvent.subject());
228
229 } else if (event instanceof TopologyEvent) {
230 TopologyEvent topoEvent = (TopologyEvent) event;
Ray Milkeyc18d0e32016-01-04 16:10:59 -0800231 List<Event> reasons = MoreObjects.firstNonNull(topoEvent.reasons(),
232 ImmutableList.<Event>of());
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800233 Topology topo = topoEvent.subject();
234 String summary = String.format("(d=%d,l=%d,c=%d)",
235 topo.deviceCount(),
236 topo.linkCount(),
237 topo.clusterCount());
238 print("%s %s%s [%s]",
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700239 Tools.defaultOffsetDataTime(event.time()),
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800240 event.type(),
241 summary,
242 reasons.stream().map(e -> e.type()).collect(toList()));
243
244 } else if (event instanceof ClusterEvent) {
245 print("%s %s\t%s [%s]",
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700246 Tools.defaultOffsetDataTime(event.time()),
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800247 event.type(),
248 ((ClusterEvent) event).subject().id(),
249 event.subject());
250
251 } else {
252 // Unknown Event?
253 print("%s %s\t%s [%s]",
Yuta HIGUCHI0c47d532017-08-18 23:16:35 -0700254 Tools.defaultOffsetDataTime(event.time()),
HIGUCHI Yuta9092db82016-01-03 18:45:01 -0800255 event.type(),
256 event.subject(),
257 event);
258 }
259 }
260
261}