Adding a tool for remote collection of node and cluster diagnostics.
- Includes 'onos-diagnostics', 'onos-node-diagnostics'
- Includes REST API /onos/v1/diagnostics
Change-Id: Ife0a15627b14238d0fce52b01b72d56e6a1fe40f
diff --git a/tools/package/bin/onos-form-cluster b/tools/package/bin/onos-form-cluster
index 9286d0c..e677873 100755
--- a/tools/package/bin/onos-form-cluster
+++ b/tools/package/bin/onos-form-cluster
@@ -2,8 +2,9 @@
# -----------------------------------------------------------------------------
# Forms ONOS cluster using REST API of each separate instance.
# -----------------------------------------------------------------------------
-
-[ $# -lt 2 ] && echo "usage: $(basename $0) ip1 ip2..." && exit 1
+function usage() {
+ echo "usage: $(basename $0)[-x] [-u user] [-p password] [-s partitionSize] ip1 ip2..." && exit 1
+}
# Scan arguments for user/password or other options...
while getopts u:p:s: o; do
@@ -11,6 +12,7 @@
u) user=$OPTARG;;
p) password=$OPTARG;;
s) partitionsize=$OPTARG;;
+ *) usage;;
esac
done
ONOS_WEB_USER=${ONOS_WEB_USER:-onos} # ONOS WEB User defaults to 'onos'
@@ -20,6 +22,8 @@
let OPC=$OPTIND-1
shift $OPC
+[ $# -lt 2 ] && usage
+
ip=$1
shift
nodes=$*
diff --git a/tools/package/runtime/bin/onos-diagnostics b/tools/package/runtime/bin/onos-diagnostics
new file mode 100755
index 0000000..51b3f8c
--- /dev/null
+++ b/tools/package/runtime/bin/onos-diagnostics
@@ -0,0 +1,137 @@
+#!/bin/bash
+
+#
+# Copyright 2015-present Open Networking Foundation
+#
+# 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.
+#
+
+# -----------------------------------------------------------------------------
+# Tool to collect cluster-wide diagnostics into a single tar stream.
+# -----------------------------------------------------------------------------
+function usage() {
+ echo "usage: $(basename $0) [-x] [-n name] [-u user] [-p password] [ip1 ip2...]"
+ echo ""
+ echo "Environment Variables:"
+ echo " ONOS_INSTANCES IPs or hostnames of ONOS cluster machines"
+ echo " ONOS_WEB_USER username for REST API"
+ echo " ONOS_WEB_PASS password for REST API"
+ echo ""
+ echo "Example Usages:"
+ echo " # Collect compressed diagnostics for the cluster."
+ echo " # REST API user and password are drawn from environment variables."
+ echo " # Collection archive will be named /tmp/onos-diags.tar.gz"
+ echo " # The cluster node IPs will be drawn from ONOS_INSTANCES variable."
+ echo " > $(basename $0) "
+ echo ""
+ echo " # Collect diagnostics for the cluster and leave them extracted. "
+ echo " # Collection directory will be named /tmp/prague-diags/"
+ echo " # Collection archive will be named /tmp/prague-diags.tar.gz."
+ echo " # REST API user name is 'onos' and password is 'rules'."
+ echo " # The cluster node IPs will be drawn from ONOS_INSTANCES variable."
+ echo " > $(basename $0) -x -n prague -u onos -p rules"
+ echo ""
+ echo " # Collect compressed diagnostics for a cluster."
+ echo " # REST API user name is 'onos' and password is 'rules'."
+ echo " # Collection archive will be named /tmp/onos-diags.tar.gz"
+ echo " # The cluster node IPs are listed explicitly."
+ echo " > $(basename $0) -u onos -p rules 172.17.0.11 172.17.0.12 172.17.0.13"
+
+ exit 1
+}
+
+CLI_COMMANDS=(
+ "feature:list"
+ "bundle:list"
+ "scr:list"
+
+ "summary"
+ "nodes"
+ "apps -s"
+ "netcfg"
+ "cfg get"
+
+ "devices"
+ "links"
+ "hosts"
+
+ "ports -e"
+ "portstats -nz"
+
+ "intents"
+ "flows -s"
+ "groups"
+
+ "roles"
+ "masters"
+
+ "routes"
+ "obj-next-ids"
+ "obj-pending-nexts"
+
+ "log:display -l WARN"
+)
+
+# Scan arguments for user/password or other options...
+while getopts n:u:p:x?h o; do
+ case "$o" in
+ n) name=$OPTARG;;
+ u) user=$OPTARG;;
+ p) password=$OPTARG;;
+ x) extract=true;;
+ *) usage;;
+ esac
+done
+ONOS_WEB_USER=${ONOS_WEB_USER:-onos} # ONOS WEB User defaults to 'onos'
+ONOS_WEB_PASS=${ONOS_WEB_PASS:-rocks} # ONOS WEB Password defaults to 'rocks'
+user=${user:-$ONOS_WEB_USER}
+password=${password:-$ONOS_WEB_PASS}
+let OPC=$OPTIND-1
+shift $OPC
+
+[ $# -lt 1 -a -z "$ONOS_INSTANCES" ] && usage;
+
+diags=/tmp/${name:-onos}-diags
+rm -fr $diags $diags.tar.gz; mkdir -p $diags
+
+[ -z $1 ] && nodes=$ONOS_INSTANCES || nodes=$*
+
+# Collect diagnostics from each cluster node
+for node in $nodes; do
+ printf "Collecting diagnostics on $node..."
+
+ # Prepare a clean place for collecting the node diagnostic data
+ cd $diags; rm -fr $node; mkdir -p $node; cd $node;
+
+ # Acquire locally obtained diagnostics via REST API and extract them
+ printf "logs "
+ curl -sS --fail --user $user:$password \
+ http://$node:8181/onos/v1/diagnostics > ../$node.tar.gz
+ tar zxf ../$node.tar.gz
+
+ # Acquire remotely obtained diagnostics via ssh CLI
+ for cmd in "${CLI_COMMANDS[@]}"; do
+ cmdLog="$(echo $cmd | cut -d\ -f1 | sed 's/:/-/g').txt"
+ printf "$cmdLog "
+ onos $node $cmd 2>/dev/null >$cmdLog
+ done
+
+ # Tar-up local and remote diagnostics together
+ printf " Done.\n"
+ tar zcf ../$node.tar.gz *
+done
+
+# Tar-up diagnostics from all the nodes
+cd $diags
+tar zcf $diags.tar.gz *
+[ -z $extract ] && rm -fr $diags
diff --git a/tools/package/runtime/bin/onos-node-diagnostics b/tools/package/runtime/bin/onos-node-diagnostics
new file mode 100755
index 0000000..1cb18b5
--- /dev/null
+++ b/tools/package/runtime/bin/onos-node-diagnostics
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+#
+# Copyright 2015-present Open Networking Foundation
+#
+# 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.
+#
+
+# -----------------------------------------------------------------------------
+# Tool to collect node-specific diagnostics into a single tar stream.
+# -----------------------------------------------------------------------------
+
+# If ONOS_HOME is set, respect its value.
+# If ONOS_HOME is not set (e.g. in the init or service environment),
+# set it based on this script's path.
+ONOS_HOME=${ONOS_HOME:-$(cd $(dirname $0)/.. >/dev/null 2>&1 && pwd)}
+
+diag=/tmp/diag$$
+mkdir -p $diag; cd $diag
+
+# Collect application state
+ls -l $ONOS_HOME/apps/* > apps-dir.txt
+
+# Collect the karaf logs
+cp $ONOS_HOME/apache-karaf-*/data/log/* .
+
+# Tar-up the collected information
+tar zcf ../onos-node-diags.tar.gz *
+rm -fr $diag
+
+
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java b/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java
index 6cd7884..4677844 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/CoreWebApplication.java
@@ -52,7 +52,8 @@
VirtualNetworkWebResource.class,
MastershipWebResource.class,
InvalidConfigExceptionMapper.class,
- DpisWebResource.class
+ DpisWebResource.class,
+ DiagnosticsWebResource.class
);
}
}
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/DiagnosticsWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/DiagnosticsWebResource.java
new file mode 100644
index 0000000..6b951e0
--- /dev/null
+++ b/web/api/src/main/java/org/onosproject/rest/resources/DiagnosticsWebResource.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015-present Open Networking Foundation
+ *
+ * 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.rest.resources;
+
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import static com.google.common.io.ByteStreams.toByteArray;
+
+/**
+ * Provides stream of diagnostic information.
+ */
+@Path("diagnostics")
+public class DiagnosticsWebResource extends AbstractWebResource {
+
+ private static final String COMMAND = "../bin/onos-node-diagnostics";
+ private static final String DIAGS = "/tmp/onos-node-diags.tar.gz";
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * Get tar.gz stream of node diagnostic information.
+ *
+ * @return 200 OK with a tar.gz stream of diagnostic data
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_OCTET_STREAM)
+ public Response getDiagnostics() {
+ try {
+ execute(COMMAND);
+ return ok(new FileInputStream(DIAGS)).build();
+ } catch (IOException e) {
+ return Response.serverError().build();
+ }
+ }
+
+ // Executes the given command arguments as a system command.
+ private void execute(String command) throws IOException {
+ try {
+ Process process = Runtime.getRuntime().exec(command);
+ byte[] output = toByteArray(process.getInputStream());
+ byte[] error = toByteArray(process.getErrorStream());
+ int code = process.waitFor();
+ if (code != 0) {
+ log.info("Command failed: status={}, output={}, error={}",
+ code, new String(output), new String(error));
+ }
+ } catch (InterruptedException e) {
+ log.error("Interrupted executing command {}", command, e);
+ }
+ }
+}