blob: c6f15de6109010b38c767f5b6db440ce2fda450f [file] [log] [blame]
HIGUCHI Yuta9092db82016-01-03 18:45:01 -08001/*
2 * Copyright 2016 Open Networking Laboratory
3 *
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
18import static java.util.stream.Collectors.toList;
19
20import java.io.PrintWriter;
21import java.io.StringWriter;
22import java.util.List;
23import java.util.function.Predicate;
24import java.util.stream.Collector;
25import java.util.stream.Stream;
26
27import org.apache.karaf.shell.commands.Command;
28import org.apache.karaf.shell.commands.Option;
29import org.joda.time.LocalDateTime;
30import org.onosproject.cli.AbstractShellCommand;
31import org.onosproject.cluster.ClusterEvent;
32import org.onosproject.event.Event;
33import org.onosproject.mastership.MastershipEvent;
34import org.onosproject.net.Link;
35import org.onosproject.net.device.DeviceEvent;
36import org.onosproject.net.host.HostEvent;
37import org.onosproject.net.link.LinkEvent;
38import org.onosproject.net.topology.Topology;
39import org.onosproject.net.topology.TopologyEvent;
40
41import com.fasterxml.jackson.core.JsonProcessingException;
42import com.fasterxml.jackson.databind.JsonNode;
43import com.fasterxml.jackson.databind.node.ArrayNode;
44import com.fasterxml.jackson.databind.node.ObjectNode;
45import com.google.common.base.MoreObjects;
46import com.google.common.collect.ImmutableList;
47
48/**
49 * Command to print history of instance local ONOS Events.
50 */
51@Command(scope = "onos", name = "events",
52 description = "Command to print history of instance local ONOS Events")
53public class EventsCommand
54 extends AbstractShellCommand {
55
56 @Option(name = "--all", aliases = "-a",
57 description = "Include all Events (default behavior)",
58 required = false)
59 private boolean all = false;
60
61 @Option(name = "--mastership", aliases = "-m",
62 description = "Include MastershipEvent",
63 required = false)
64 private boolean mastership = false;
65
66 @Option(name = "--device", aliases = "-d",
67 description = "Include DeviceEvent",
68 required = false)
69 private boolean device = false;
70
71 @Option(name = "--link", aliases = "-l",
72 description = "Include LinkEvent",
73 required = false)
74 private boolean link = false;
75
76 @Option(name = "--topology", aliases = "-t",
77 description = "Include TopologyEvent",
78 required = false)
79 private boolean topology = false;
80
81 @Option(name = "--host", aliases = "-t",
82 description = "Include HostEvent",
83 required = false)
84 private boolean host = false;
85
86 @Option(name = "--cluster", aliases = "-c",
87 description = "Include ClusterEvent",
88 required = false)
89 private boolean cluster = false;
90
91 @Option(name = "--max-events", aliases = "-n",
92 description = "Maximum number of events to print",
93 required = false,
94 valueToShowInHelp = "-1 [no limit]")
95 private long maxSize = -1;
96
97 @Override
98 protected void execute() {
99 EventHistoryService eventHistoryService = get(EventHistoryService.class);
100
101 Stream<Event<?, ?>> events = eventHistoryService.history().stream();
102
103 boolean dumpAll = all || !(mastership || device || link || topology || host);
104
105 if (!dumpAll) {
106 Predicate<Event<?, ?>> filter = (defaultIs) -> false;
107
108 if (mastership) {
109 filter = filter.or(evt -> evt instanceof MastershipEvent);
110 }
111 if (device) {
112 filter = filter.or(evt -> evt instanceof DeviceEvent);
113 }
114 if (link) {
115 filter = filter.or(evt -> evt instanceof LinkEvent);
116 }
117 if (topology) {
118 filter = filter.or(evt -> evt instanceof TopologyEvent);
119 }
120 if (host) {
121 filter = filter.or(evt -> evt instanceof HostEvent);
122 }
123 if (cluster) {
124 filter = filter.or(evt -> evt instanceof ClusterEvent);
125 }
126
127 events = events.filter(filter);
128 }
129
130 if (maxSize > 0) {
131 events = events.limit(maxSize);
132 }
133
134 if (outputJson()) {
135 ArrayNode jsonEvents = events.map(this::json).collect(toArrayNode());
136 printJson(jsonEvents);
137 } else {
138 events.forEach(this::printEvent);
139 }
140
141 }
142
143 private Collector<JsonNode, ArrayNode, ArrayNode> toArrayNode() {
144 return Collector.of(() -> mapper().createArrayNode(),
145 ArrayNode::add,
146 ArrayNode::addAll);
147 }
148
149 private ObjectNode json(Event<?, ?> event) {
150 ObjectNode result = mapper().createObjectNode();
151
152 result.put("time", event.time())
153 .put("type", event.type().toString())
154 .put("event", event.toString());
155
156 return result;
157 }
158
159 /**
160 * Print JsonNode using default pretty printer.
161 *
162 * @param json JSON node to print
163 */
164 private void printJson(JsonNode json) {
165 try {
166 print("%s", mapper().writerWithDefaultPrettyPrinter().writeValueAsString(json));
167 } catch (JsonProcessingException e) {
168 StringWriter sw = new StringWriter();
169 e.printStackTrace(new PrintWriter(sw));
170 print("[ERROR] %s\n%s", e.getMessage(), sw.toString());
171 }
172 }
173
174 private void printEvent(Event<?, ?> event) {
175 if (event instanceof DeviceEvent) {
176 DeviceEvent deviceEvent = (DeviceEvent) event;
177 if (event.type().toString().startsWith("PORT")) {
178 // Port event
179 print("%s %s\t%s/%s [%s]",
180 new LocalDateTime(event.time()),
181 event.type(),
182 deviceEvent.subject().id(), deviceEvent.port().number(),
183 deviceEvent.port()
184 );
185 } else {
186 // Device event
187 print("%s %s\t%s [%s]",
188 new LocalDateTime(event.time()),
189 event.type(),
190 deviceEvent.subject().id(),
191 deviceEvent.subject()
192 );
193 }
194
195 } else if (event instanceof MastershipEvent) {
196 print("%s %s\t%s [%s]",
197 new LocalDateTime(event.time()),
198 event.type(),
199 event.subject(),
200 ((MastershipEvent) event).roleInfo());
201
202 } else if (event instanceof LinkEvent) {
203 LinkEvent linkEvent = (LinkEvent) event;
204 Link link = linkEvent.subject();
205 print("%s %s\t%s/%s-%s/%s [%s]",
206 new LocalDateTime(event.time()),
207 event.type(),
208 link.src().deviceId(), link.src().port(), link.dst().deviceId(), link.dst().port(),
209 link);
210
211 } else if (event instanceof HostEvent) {
212 HostEvent hostEvent = (HostEvent) event;
213 print("%s %s\t%s [%s->%s]",
214 new LocalDateTime(event.time()),
215 event.type(),
216 hostEvent.subject().id(),
217 hostEvent.prevSubject(), hostEvent.subject());
218
219 } else if (event instanceof TopologyEvent) {
220 TopologyEvent topoEvent = (TopologyEvent) event;
221 List<Event> reasons = MoreObjects.firstNonNull(topoEvent.reasons(), ImmutableList.of());
222 Topology topo = topoEvent.subject();
223 String summary = String.format("(d=%d,l=%d,c=%d)",
224 topo.deviceCount(),
225 topo.linkCount(),
226 topo.clusterCount());
227 print("%s %s%s [%s]",
228 new LocalDateTime(event.time()),
229 event.type(),
230 summary,
231 reasons.stream().map(e -> e.type()).collect(toList()));
232
233 } else if (event instanceof ClusterEvent) {
234 print("%s %s\t%s [%s]",
235 new LocalDateTime(event.time()),
236 event.type(),
237 ((ClusterEvent) event).subject().id(),
238 event.subject());
239
240 } else {
241 // Unknown Event?
242 print("%s %s\t%s [%s]",
243 new LocalDateTime(event.time()),
244 event.type(),
245 event.subject(),
246 event);
247 }
248 }
249
250}