| /* |
| * Copyright 2016 Open Networking Laboratory |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.onosproject.events; |
| |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.util.List; |
| import java.util.function.Predicate; |
| import java.util.stream.Collector; |
| import java.util.stream.Stream; |
| |
| import org.apache.karaf.shell.commands.Command; |
| import org.apache.karaf.shell.commands.Option; |
| import org.joda.time.LocalDateTime; |
| import org.onosproject.cli.AbstractShellCommand; |
| import org.onosproject.cluster.ClusterEvent; |
| import org.onosproject.event.Event; |
| import org.onosproject.mastership.MastershipEvent; |
| import org.onosproject.net.Link; |
| import org.onosproject.net.device.DeviceEvent; |
| import org.onosproject.net.host.HostEvent; |
| import org.onosproject.net.link.LinkEvent; |
| import org.onosproject.net.topology.Topology; |
| import org.onosproject.net.topology.TopologyEvent; |
| |
| import com.fasterxml.jackson.core.JsonProcessingException; |
| import com.fasterxml.jackson.databind.JsonNode; |
| import com.fasterxml.jackson.databind.node.ArrayNode; |
| import com.fasterxml.jackson.databind.node.ObjectNode; |
| import com.google.common.base.MoreObjects; |
| import com.google.common.collect.ImmutableList; |
| |
| import static java.util.stream.Collectors.toList; |
| |
| /** |
| * Command to print history of instance local ONOS Events. |
| */ |
| @Command(scope = "onos", name = "events", |
| description = "Command to print history of instance local ONOS Events") |
| public class EventsCommand |
| extends AbstractShellCommand { |
| |
| @Option(name = "--all", aliases = "-a", |
| description = "Include all Events (default behavior)", |
| required = false) |
| private boolean all = false; |
| |
| @Option(name = "--mastership", aliases = "-m", |
| description = "Include MastershipEvent", |
| required = false) |
| private boolean mastership = false; |
| |
| @Option(name = "--device", aliases = "-d", |
| description = "Include DeviceEvent", |
| required = false) |
| private boolean device = false; |
| |
| @Option(name = "--link", aliases = "-l", |
| description = "Include LinkEvent", |
| required = false) |
| private boolean link = false; |
| |
| @Option(name = "--topology", aliases = "-t", |
| description = "Include TopologyEvent", |
| required = false) |
| private boolean topology = false; |
| |
| @Option(name = "--host", aliases = "-t", |
| description = "Include HostEvent", |
| required = false) |
| private boolean host = false; |
| |
| @Option(name = "--cluster", aliases = "-c", |
| description = "Include ClusterEvent", |
| required = false) |
| private boolean cluster = false; |
| |
| @Option(name = "--max-events", aliases = "-n", |
| description = "Maximum number of events to print", |
| required = false, |
| valueToShowInHelp = "-1 [no limit]") |
| private long maxSize = -1; |
| |
| @Override |
| protected void execute() { |
| EventHistoryService eventHistoryService = get(EventHistoryService.class); |
| |
| Stream<Event<?, ?>> events = eventHistoryService.history().stream(); |
| |
| boolean dumpAll = all || !(mastership || device || link || topology || host); |
| |
| if (!dumpAll) { |
| Predicate<Event<?, ?>> filter = (defaultIs) -> false; |
| |
| if (mastership) { |
| filter = filter.or(evt -> evt instanceof MastershipEvent); |
| } |
| if (device) { |
| filter = filter.or(evt -> evt instanceof DeviceEvent); |
| } |
| if (link) { |
| filter = filter.or(evt -> evt instanceof LinkEvent); |
| } |
| if (topology) { |
| filter = filter.or(evt -> evt instanceof TopologyEvent); |
| } |
| if (host) { |
| filter = filter.or(evt -> evt instanceof HostEvent); |
| } |
| if (cluster) { |
| filter = filter.or(evt -> evt instanceof ClusterEvent); |
| } |
| |
| events = events.filter(filter); |
| } |
| |
| if (maxSize > 0) { |
| events = events.limit(maxSize); |
| } |
| |
| if (outputJson()) { |
| ArrayNode jsonEvents = events.map(this::json).collect(toArrayNode()); |
| printJson(jsonEvents); |
| } else { |
| events.forEach(this::printEvent); |
| } |
| |
| } |
| |
| private Collector<JsonNode, ArrayNode, ArrayNode> toArrayNode() { |
| return Collector.of(() -> mapper().createArrayNode(), |
| ArrayNode::add, |
| ArrayNode::addAll); |
| } |
| |
| private ObjectNode json(Event<?, ?> event) { |
| ObjectNode result = mapper().createObjectNode(); |
| |
| result.put("time", event.time()) |
| .put("type", event.type().toString()) |
| .put("event", event.toString()); |
| |
| return result; |
| } |
| |
| /** |
| * Print JsonNode using default pretty printer. |
| * |
| * @param json JSON node to print |
| */ |
| @java.lang.SuppressWarnings("squid:S1148") |
| private void printJson(JsonNode json) { |
| try { |
| print("%s", mapper().writerWithDefaultPrettyPrinter().writeValueAsString(json)); |
| } catch (JsonProcessingException e) { |
| StringWriter sw = new StringWriter(); |
| e.printStackTrace(new PrintWriter(sw)); |
| print("[ERROR] %s\n%s", e.getMessage(), sw.toString()); |
| } |
| } |
| |
| private void printEvent(Event<?, ?> event) { |
| if (event instanceof DeviceEvent) { |
| DeviceEvent deviceEvent = (DeviceEvent) event; |
| if (event.type().toString().startsWith("PORT")) { |
| // Port event |
| print("%s %s\t%s/%s [%s]", |
| new LocalDateTime(event.time()), |
| event.type(), |
| deviceEvent.subject().id(), deviceEvent.port().number(), |
| deviceEvent.port() |
| ); |
| } else { |
| // Device event |
| print("%s %s\t%s [%s]", |
| new LocalDateTime(event.time()), |
| event.type(), |
| deviceEvent.subject().id(), |
| deviceEvent.subject() |
| ); |
| } |
| |
| } else if (event instanceof MastershipEvent) { |
| print("%s %s\t%s [%s]", |
| new LocalDateTime(event.time()), |
| event.type(), |
| event.subject(), |
| ((MastershipEvent) event).roleInfo()); |
| |
| } else if (event instanceof LinkEvent) { |
| LinkEvent linkEvent = (LinkEvent) event; |
| Link link = linkEvent.subject(); |
| print("%s %s\t%s/%s-%s/%s [%s]", |
| new LocalDateTime(event.time()), |
| event.type(), |
| link.src().deviceId(), link.src().port(), link.dst().deviceId(), link.dst().port(), |
| link); |
| |
| } else if (event instanceof HostEvent) { |
| HostEvent hostEvent = (HostEvent) event; |
| print("%s %s\t%s [%s->%s]", |
| new LocalDateTime(event.time()), |
| event.type(), |
| hostEvent.subject().id(), |
| hostEvent.prevSubject(), hostEvent.subject()); |
| |
| } else if (event instanceof TopologyEvent) { |
| TopologyEvent topoEvent = (TopologyEvent) event; |
| List<Event> reasons = MoreObjects.firstNonNull(topoEvent.reasons(), |
| ImmutableList.<Event>of()); |
| Topology topo = topoEvent.subject(); |
| String summary = String.format("(d=%d,l=%d,c=%d)", |
| topo.deviceCount(), |
| topo.linkCount(), |
| topo.clusterCount()); |
| print("%s %s%s [%s]", |
| new LocalDateTime(event.time()), |
| event.type(), |
| summary, |
| reasons.stream().map(e -> e.type()).collect(toList())); |
| |
| } else if (event instanceof ClusterEvent) { |
| print("%s %s\t%s [%s]", |
| new LocalDateTime(event.time()), |
| event.type(), |
| ((ClusterEvent) event).subject().id(), |
| event.subject()); |
| |
| } else { |
| // Unknown Event? |
| print("%s %s\t%s [%s]", |
| new LocalDateTime(event.time()), |
| event.type(), |
| event.subject(), |
| event); |
| } |
| } |
| |
| } |