# (c) Copyright 2010-2014 Cloudera, Inc. """This module can be used in one of two ways. It can be run independently from the command line, given a user, host, port, dropdir, and file, it will transfer the file to the host's dropdir. This is meant to phone cluster statistics to conductor for collection. This script can also automatically be used by cluster statistics, where its transfer_file function is invoked to transfer the file to home.""" import os import sys import subprocess import tempfile import optparse import logging import socket # Attempt to use new version of md5 to avoid nasty warnings try: from hashlib import md5 except ImportError: import md5 logger = logging.getLogger() COPS_PUBLIC_KEY="cops.mtv.cloudera.com,172.20.45.27 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2A4SRMUf08kv82jGQmIaDO8obPbkUOcaxql51kzMFRWWEGOVibQJt6rnuHlzqnujxvyPmI9F/VZKWNg+Bljm9XKxQ6PrjYgG7Mcm3pO+ae+c28nn3Qg4somCzVLnMBS4HkkmTOiX5Bct4R7zKHElsKSY8PMPGQOyfnCjnZwi/w4E1sYYqrLR1TjYrwFnIJUR9X6HEjqEEVK0dT9uARAhQYdUL3ykRPlyM+aHt8KSssfgltNNDdLcM3yTrW58B8yysCzO5MGT7LR8yuaCDOVwPhQxa5QbCdUgYJq2mbQXpdwkyyHtrMDGorykB+oG6GLr093oCqJrAinlUNgL4eP6yQ==\ncops.cloudera.com,173.227.38.190 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA2A4SRMUf08kv82jGQmIaDO8obPbkUOcaxql51kzMFRWWEGOVibQJt6rnuHlzqnujxvyPmI9F/VZKWNg+Bljm9XKxQ6PrjYgG7Mcm3pO+ae+c28nn3Qg4somCzVLnMBS4HkkmTOiX5Bct4R7zKHElsKSY8PMPGQOyfnCjnZwi/w4E1sYYqrLR1TjYrwFnIJUR9X6HEjqEEVK0dT9uARAhQYdUL3ykRPlyM+aHt8KSssfgltNNDdLcM3yTrW58B8yysCzO5MGT7LR8yuaCDOVwPhQxa5QbCdUgYJq2mbQXpdwkyyHtrMDGorykB+oG6GLr093oCqJrAinlUNgL4eP6yQ==" def generate_hash(file_name): """Given a file_name, this will open the file, read the contents, and generate an md5 hash of the file.""" # If we're using hashlib module, the new() method doesn't exist so we will # catch an attribute error and create the object properly try: m = md5.new() except AttributeError: m = md5() f = open(file_name, "rb") try: while True: data = f.read(128) if not data: break m.update(data) finally: f.close() return m.hexdigest() def store_cops_public_key(): """Stores the cops.cloudera.com public key to a temp file to be passed to the UserKnownHostsFile option of SFTP command :return: temp file where the public key is stored """ fd, cops_public_key_path = tempfile.mkstemp() logger.info("Storing cops.cloudera.com public key to %s", cops_public_key_path) os.write(fd, bytes(COPS_PUBLIC_KEY, encoding='utf-8')) os.close(fd) return cops_public_key_path def get_transfer_command(port, user, host, file_name, drop_dir, key_path, sftp=False): """Gets an appropriate sftp or curl command to upload the given file to the given location. Parameters: - port - the port of the upload server. - user - the user to upload as. - file_name - resolvable path to file to upload. - drop_dir - the location on the upload server for the file. For HTTPS uploads, only the filename is retained. - sftp - indicates whether to upload with https (curl) [enabled by default] or sftp """ if not sftp: # use https transfer_file_command = "curl -u \"%s:cm_diag@\" --header \"X-FILENAME: %s\" --data-binary '@%s' https://%s:%s/upload" return transfer_file_command % (user, os.path.basename(drop_dir), file_name, host, port) else: transfer_file_command = "sftp -b /dev/stdin -o Port=%s -o UserKnownHostsFile=%s -o StrictHostKeyChecking=yes %s@%s <\n") sys.exit(1) # - Handle non-readable / non-existent files if not can_upload_file(options.file): sys.stderr.write("Unable to read file, please make sure it exists and is readable\n") sys.exit(1) # Parse slashes out of the filename options.file = options.file.replace("\\", "") return options def main(): """Invoked as a main from the command line, so parse the command line arguments, and attempt to transfer the file.""" options = handle_args() if options.sftp: if not has_program("sftp"): sys.stderr.write("sftp is not installed, please install it before continuing\n") sys.exit(1) else: if not has_program("curl"): sys.stderr.write("curl is not installed, please install it before continuing\n") sys.exit(1) success = transfer_file(options.user, options.host, options.port, options.dropdir, options.file, options.sftp) if not success: sys.exit(1) def init_logger(): """Initialize some default logging settings""" handler = logging.StreamHandler() formatter = logging.Formatter("%(asctime)s %(module)-25s %(levelname)-8s: %(message)s") handler.setFormatter(formatter) logger.setLevel(logging.DEBUG) logger.addHandler(handler) def can_upload_file(fpath): """Does this file exist and is it readable?""" return os.path.isfile(fpath) and os.access(fpath, os.R_OK) def has_program(name): """Does this system have the given program on it?""" for path in os.environ["PATH"].split(os.pathsep): path = path.strip('"') fpath = os.path.join(path, name) if os.path.isfile(fpath) and os.access(fpath, os.X_OK): return True return False if __name__ == "__main__": print("Cloudera Support Upload Tool") init_logger() main()