Permalink
Browse files

Merge pull request #1 from dwighthubbard/rpc_handlers

Rpc handlers
  • Loading branch information...
dwighthubbard committed Jul 26, 2013
2 parents d4b5619 + fb5487b commit 6bc438811f17c182b5de90ee1b50585527ca4742
Showing with 777 additions and 437 deletions.
  1. +41 −0 .gitignore
  2. +0 −12 LICENSE.txt
  3. +1 −1 setup.py
  4. +18 −3 sshmap/__init__.py
  5. +228 −0 sshmap/callback.py
  6. +67 −0 sshmap/defaults.py
  7. +48 −0 sshmap/runner.py
  8. +44 −38 sshmap/sshmap
  9. +202 −383 sshmap/sshmap.py
  10. +54 −0 sshmap/utility.py
  11. +74 −0 tests/test.py
View
@@ -0,0 +1,41 @@
+*.py[cod]
+
+# C extensions
+*.so
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+lib
+lib64
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+nosetests.xml
+
+# Translations
+*.mo
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
+
+# Pycharm
+.idea
+
+# Backup files
+*~
View
@@ -1,12 +0,0 @@
- Copyright (c) 2010 Yahoo! Inc. All rights reserved.
- 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. See accompanying LICENSE file.
View
@@ -19,7 +19,7 @@
setup(
name="sshmap",
- version="0.5.8",
+ version="0.5.50",
author="Dwight Hubbard",
author_email="dhubbard@yahoo-inc.com",
url="https://github.com/dwighthubbard/sshmap",
View
21 sshmap/__init__.py 100644 → 100755
@@ -1,13 +1,28 @@
-#Copyright (c) 2012 Yahoo! Inc. All rights reserved.
+#Copyright (c) 2012-2013 Yahoo! Inc. All rights reserved.
#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. See accompanying LICENSE file.
-from sshmap import *
+
+#from sshmap import run, run_command, ssh_result, ssh_results, fastSSHClient
+import sshmap
+import callback
+import utility
+import runner
+
+# For backwards compatibility
+from callback import summarize_failures as callback_summarize_failures
+from callback import aggregate_output as callback_aggregate_output
+from callback import exec_command as callback_exec_command
+from callback import filter_match as callback_filter_match
+from callback import status_count as callback_status_count
+
+# The actual used sshmap functions
+from sshmap import run, run_command
View
@@ -0,0 +1,228 @@
+#Copyright (c) 2012 Yahoo! Inc. All rights reserved.
+#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. See accompanying LICENSE file.
+__author__ = 'dhubbard'
+"""
+sshmap built in callback handlers
+"""
+import os
+import sys
+import hashlib
+import json
+import stat
+import base64
+import subprocess
+
+import utility
+
+
+# Filter callback handlers
+def flowthrough(result):
+ """
+ Builtin Callback, return the raw data passed
+
+ >>> result=flowthrough(ssh_result(["output"], ["error"],"foo", 0))
+ >>> result.dump()
+ foo output error 0 0 None
+ """
+ return result
+
+
+def summarize_failures(result):
+ """
+ Builtin Callback, put a summary of failures into parm
+ """
+ failures = result.setting('failures')
+ if not failures:
+ result.parm['failures'] = []
+ failures = []
+ if result.ssh_retcode:
+ failures.append(result.host)
+ result.parm['failures'] = failures
+ return result
+
+
+def exec_command(result):
+ """
+ Builtin Callback, pass the results to a command/script
+ :param result:
+ """
+ script = result.setting("callback_script")
+ if not script:
+ return result
+ utility.status_clear()
+ result_out, result_err = subprocess.Popen(
+ script + " " + result.host,
+ shell=True,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE
+ ).communicate(
+ result.out_string() + result.err_string()
+ )
+ result.out = [result_out]
+ result.err = [result_err]
+ print(result.out_string())
+ return result
+
+
+def aggregate_output(result):
+ """ Builtin Callback, Aggregate identical results """
+ aggregate_hosts = result.setting('aggregate_hosts')
+ if not aggregate_hosts:
+ aggregate_hosts = {}
+ collapsed_output = result.setting('collapsed_output')
+ if not collapsed_output:
+ collapsed_output = {}
+ h = hashlib.md5()
+ h.update(result.out_string())
+ h.update(result.err_string())
+ if result.ssh_retcode:
+ h.update(result.ssh_error_message())
+ digest = h.hexdigest()
+ if digest in aggregate_hosts.keys():
+ aggregate_hosts[digest].append(result.host)
+ else:
+ aggregate_hosts[digest] = [result.host]
+ if result.ssh_retcode:
+ error = []
+ if result.err:
+ error = result.err
+ error.append(result.ssh_error_message())
+ collapsed_output[digest] = (result.out, error)
+ else:
+ collapsed_output[digest] = (result.out, result.err)
+ result.parm['aggregate_hosts'] = aggregate_hosts
+ if collapsed_output:
+ result.parm['collapsed_output'] = collapsed_output
+ return result
+
+
+def filter_match(result):
+ """
+ Builtin Callback, remove all output if the string is not found in the
+ output
+ similar to grep
+ :param result:
+ """
+ if result.out_string().find(result.setting('match')) == -1 and \
+ result.err_string().find(result.setting('match')) == -1:
+ result.out = ''
+ result.err = ''
+ return result
+
+
+def filter_json(result):
+ """
+ Builtin Callback, change stdout to json
+
+ >>> result=filter_json(ssh_result(["output"], ["error"],"foo", 0))
+ >>> result.dump()
+ foo [["output"], ["error"], 0] error 0 0 None
+ """
+ result.out = [json.dumps((result.out, result.err, result.retcode))]
+ return result
+
+
+def filter_base64(result):
+ """
+ Builtin Callback, base64 encode the info in out and err streams
+ """
+ result.out = [base64.b64encode(result.out_string)]
+ result.err = [base64.b64encode(result.err_string)]
+ return result
+
+
+#Status callback handlers
+def status_count(result):
+ """
+ Builtin Callback, show the count complete/remaining
+ :param result:
+ """
+ # The master process inserts the status into the
+ # total_host_count and completed_host_count variables
+ sys.stderr.write('\x1b[0G\x1b[0K%s/%s' % (
+ result.setting('completed_host_count'),
+ result.setting('total_host_count')))
+ sys.stderr.flush()
+ return result
+
+
+#Output callback handlers
+def output_prefix_host(result):
+ """
+ Builtin Callback, print the output with the hostname: prefixed to each line
+ :param result:
+ hostname: out
+
+ >>> result=sshmap.callback.output_prefix_host(ssh_result(['out'],['err'], 'hostname', 0))
+ >>> result.dump()
+ """
+ output = []
+ error = []
+ utility.status_clear()
+ # If summarize_failures option is set don't print ssh errors inline
+ if result.setting('summarize_failed') and result.ssh_retcode:
+ return result
+ if result.setting('print_rc'):
+ rc = ' SSH_Returncode: %d\tCommand_Returncode: %d' % (
+ result.ssh_retcode, result.retcode)
+ else:
+ rc = ''
+ if result.ssh_retcode:
+ print >> sys.stderr, '%s: %s' % (result.host, result.ssh_error_message())
+ error = ['%s: %s' % (result.host, result.ssh_error_message())]
+ if len(result.out_string()):
+ for line in result.out:
+ if line:
+ print '%s:%s %s' % (result.host, rc, line.strip())
+ output.append('%s:%s %s\n' % (result.host, rc, line.strip()))
+ if len(result.err_string()):
+ for line in result.err:
+ if line:
+ print >> sys.stderr, '%s:%s %s' % (result.host, rc, line.strip())
+ error.append('%s:%s Error: %s\n' % (result.host, rc, line.strip()))
+ if result.setting('output'):
+ if not len(result.out_string()) and not len(result.err_string()) and not result.setting(
+ 'only_output') and result.setting('print_rc'):
+ print '%s:%s' % (result.host, rc)
+ sys.stdout.flush()
+ sys.stderr.flush()
+ result.out = output
+ result.err = error
+ return result
+
+
+def read_conf(key=None, prompt=True):
+ """ Read settings from the config file
+ :param key:
+ :param prompt:
+ """
+ try:
+ conf = json.load(open(os.path.expanduser('~/.sshmap.conf'), 'r'))
+ except IOError:
+ conf = sshmap.conf_defaults
+ if key:
+ try:
+ return conf[key].encode('ascii')
+ except KeyError:
+ pass
+ else:
+ return conf
+ if key and prompt:
+ conf[key] = raw_input(sshmap.conf_desc[key] + ': ')
+ fh = open(os.path.expanduser('~/.sshmap2.conf'), 'w')
+ os.fchmod(fh.fileno(), stat.S_IRUSR | stat.S_IWUSR)
+ json.dump(conf, fh)
+ fh.close()
+ return conf[key]
+ else:
+ return None
View
@@ -0,0 +1,67 @@
+#Copyright (c) 2012 Yahoo! Inc. All rights reserved.
+#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. See accompanying LICENSE file.
+"""
+Default Values for sshmap
+"""
+__author__ = 'dhubbard'
+import os
+
+# Defaults
+JOB_MAX = 100
+# noinspection PyBroadException
+try:
+ for line in open('/proc/%d/limits' % os.getpid(), 'r').readlines():
+ if line.startswith('Max processes'):
+ JOB_MAX = int(line.strip().split()[2]) / 4
+except:
+ pass
+
+# Return code values
+RUN_OK = 0
+RUN_FAIL_AUTH = 1
+RUN_FAIL_TIMEOUT = 2
+RUN_FAIL_CONNECT = 3
+RUN_FAIL_SSH = 4
+RUN_SUDO_PROMPT = 5
+RUN_FAIL_UNKNOWN = 6
+RUN_FAIL_NOPASSWORD = 7
+RUN_FAIL_BADPASSWORD = 8
+
+# Text return codes
+RUN_CODES = ['Ok', 'Authentication Error', 'Timeout', 'SSH Connection Failed',
+ 'SSH Failure',
+ 'Sudo did not send a password prompt', 'Connection refused',
+ 'Sudo password required',
+ 'Invalid sudo password']
+
+# Configuration file field descriptions
+conf_desc = {
+ "username": "IRC Server username",
+ "password": "IRC Server password",
+ "channel": "sshmap",
+}
+
+# Configuration file defaults
+conf_defaults = {
+ "address": "chat.freenode.net",
+ "port": "6667",
+ "use_ssl": False,
+}
+
+sudo_message = [
+ 'We trust you have received the usual lecture from the local System',
+ 'Administrator. It usually boils down to these three things:',
+ '#1) Respect the privacy of others.',
+ '#2) Think before you type.',
+ '#3) With great power comes great responsibility.'
+]
Oops, something went wrong.

0 comments on commit 6bc4388

Please sign in to comment.