#!/usr/bin/env python
# coding: utf-8
# Copyright (C) 1994-2018 Altair Engineering, Inc.
# For more information, contact Altair at www.altair.com.
#
# This file is part of the PBS Professional ("PBS Pro") software.
#
# Open Source License Information:
#
# PBS Pro is free software. You can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# PBS Pro is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#
# Commercial License Information:
#
# For a copy of the commercial license terms and conditions,
# go to: (http://www.pbspro.com/UserArea/agreement.html)
# or contact the Altair Legal Department.
#
# Altair’s dual-license business model allows companies, individuals, and
# organizations to create proprietary derivative works of PBS Pro and
# distribute them - whether embedded or bundled with other software -
# under a commercial license agreement.
#
# Use of Altair’s trademarks, including but not limited to "PBS™",
# "PBS Professional®", and "PBS Pro™" and Altair’s logos is subject to Altair's
# trademark licensing policies.
import os
import sys
import getopt
import errno
import logging
import ptl
import time
import tarfile
from getopt import GetoptError
from threading import Thread
from ptl.lib.pbs_testlib import PtlConfig
from ptl.utils.pbs_snaputils import PBSSnapUtils
from ptl.utils.pbs_cliutils import CliUtils
from ptl.utils.pbs_dshutils import DshUtils
def trap_exceptions(etype, value, tb):
"""
Trap SIGINT and SIGPIPE
"""
# This is done so that any exceptions created by this method itself
# are caught by the default excepthook to prevent endless recursion
sys.excepthook = sys.__excepthook__
if issubclass(etype, KeyboardInterrupt):
pass
elif issubclass(etype, IOError) and value.errno == errno.EPIPE:
pass
else:
sys.__excepthook__(etype, value, tb)
# Set sys.excepthook back to trap_exceptions to catch future exceptions
sys.excepthook = trap_exceptions
sys.excepthook = trap_exceptions
def usage():
msg = """
Usage: pbs_snapshot -o [OPTION]
Take snapshot of a PBS system and optionally capture logs for diagnostics
-H primary hostname to operate on
Defaults to local host
-l set log level to one of INFO, INFOCLI,
INFOCLI2, DEBUG, DEBUG2, WARNING, ERROR
or FATAL
-h, --help display this usage message
--daemon-logs= number of daemon logs to collect
--accounting-logs= number of accounting logs to collect
--additional-hosts= collect data from additional hosts
'hostname' is a comma separated list
--map= file to store the map of obfuscated data
--obfuscate obfuscates sensitive data
--with-sudo Uses sudo to capture privileged data
--version print version number and exit
"""
print msg
def childsnap_thread(logger, host):
"""
Thread routine for each child snapshot being run on a remote host
:param logger - Logging object
:type logger - logging.Logger
:param host - the hostname for remote host
:type host - str
"""
logger.info("Capturing snapshot from host %s" % (host))
du = DshUtils()
# Get path to pbs_snapshot on remote host
host_pbsconf = du.parse_pbs_config(hostname=host)
try:
pbs_exec_path = host_pbsconf["PBS_EXEC"]
except KeyError:
logger.error("Couldn't find PBS_EXEC on host %s"
", won't capture snapshot on this host" % (
host))
return
host_pbssnappath = os.path.join(pbs_exec_path, "sbin",
"pbs_snapshot")
# Create a directory on the remote host with a unique name
# We will create the snapshot here
timestamp = str(int(time.time()))
snap_home = "host_" + timestamp
du.mkdir(hostname=host, path=snap_home)
# Run pbs_snapshot on the remote host
cmd = [host_pbssnappath, "-o", snap_home,
"--daemon-logs=" + str(daemon_logs),
"--accounting-logs=" + str(acct_logs)]
if anonymize:
cmd.extend(["--obfuscate", "--map=" + map_file])
if with_sudo:
cmd.append("--with-sudo")
ret = du.run_cmd(hosts=host, cmd=cmd, logerr=False)
if ret['rc'] != 0:
logger.error("Error capturing snapshot from host %s" % (host))
print ret['err']
return
# Get the snapshot tar filename from stdout
child_stdout = ret['out'][-1]
snaptarname = child_stdout.split("Snapshot available at: ")[1]
# Copy over the snapshot tar file as _snapshot.tgz
dest_path = os.path.join(out_dir, host + "_snapshot.tgz")
src_path = host + ":" + snaptarname
ret = du.run_copy(src=src_path, dest=dest_path)
if ret['rc'] != 0:
logger.error("Error copying child snapshot from host %s" % (host))
# Copy over map file if any as 'host_