Server IP : 184.107.3.203 / Your IP : 216.73.216.51 Web Server : Apache System : Linux dedicated2.avenfashion.com.ph 4.18.0-553.40.1.el8_10.x86_64 #1 SMP Mon Feb 10 12:11:18 EST 2025 x86_64 User : adminteladeoro ( 1015) PHP Version : 8.2.28 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON Directory (0755) : /lib/python3.6/site-packages/sos/upload/ |
[ Home ] | [ C0mmand ] | [ Upload File ] |
---|
# Copyright 2024 Red Hat, Inc. Jose Castillo <jcastillo@redhat.com> # This file is part of the sos project: https://github.com/sosreport/sos # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of # version 2 of the GNU General Public License. # # See the LICENSE file in the source distribution for further information. import os import sys import logging import inspect from sos.component import SoSComponent from sos import _sos as _ from sos import __version__ class SoSUpload(SoSComponent): """ This class is designed to upload files to a distribution defined location. These files can be either sos reports, sos collections, or other kind of files like: vmcores, application cores, logs, etc. """ desc = """Upload a file to a user or policy defined remote location""" arg_defaults = { 'upload_file': '', 'case_id': '', 'low_priority': False, 'upload_url': None, 'upload_directory': None, 'upload_user': None, 'upload_pass': None, 'upload_method': 'auto', 'upload_no_ssl_verify': False, 'upload_protocol': 'auto', 'upload_s3_endpoint': 'https://s3.amazonaws.com', 'upload_s3_region': None, 'upload_s3_bucket': None, 'upload_s3_access_key': None, 'upload_s3_secret_key': None, 'upload_s3_object_prefix': None, 'upload_target': None } def __init__(self, parser=None, args=None, cmdline=None, in_place=False, hook_commons=None, archive=None): if not in_place: # we are running `sos upload` directly super().__init__(parser, args, cmdline) self.from_cmdline = True else: # we are being hooked by either SoSReport or SoSCollector, don't # re-init everything as that will cause issues, but instead load # the needed bits from the calling component self.opts = hook_commons['options'] self.policy = hook_commons['policy'] self.manifest = hook_commons['manifest'] self.parser = parser self.cmdline = cmdline self.args = args self._upload_file = archive self.ui_log = logging.getLogger('sos_ui') self.from_cmdline = False self.archive = archive self.upload_targets = self.load_upload_targets() self.upload_target = None @classmethod def add_parser_options(cls, parser): parser.usage = 'sos upload FILE [options]' upload_grp = parser.add_argument_group( 'Upload Options', 'These options control how upload manages files' ) upload_grp.add_argument("upload_file", metavar="FILE", help="The file or archive to upload") upload_grp.add_argument("--case-id", action="store", dest="case_id", help="specify case identifier") upload_grp.add_argument("--upload-url", default=None, help="Upload the archive to specified server") upload_grp.add_argument("--upload-user", default=None, help="Username to authenticate with") upload_grp.add_argument("--upload-pass", default=None, help="Password to authenticate with") upload_grp.add_argument("--upload-directory", action="store", dest="upload_directory", help="Specify upload directory for archive") upload_grp.add_argument("--upload-s3-endpoint", default=None, help="Endpoint to upload to for S3 bucket") upload_grp.add_argument("--upload-s3-region", default=None, help="Region to upload to for S3 bucket") upload_grp.add_argument("--upload-s3-bucket", default=None, help="Name of the S3 bucket to upload to") upload_grp.add_argument("--upload-s3-access-key", default=None, help="Access key for the S3 bucket") upload_grp.add_argument("--upload-s3-secret-key", default=None, help="Secret key for the S3 bucket") upload_grp.add_argument("--upload-s3-object-prefix", default=None, help="Prefix for the S3 object/key") upload_grp.add_argument("--upload-method", default='auto', choices=['auto', 'put', 'post'], help="HTTP method to use for uploading") upload_grp.add_argument("--upload-protocol", default='auto', choices=['auto', 'https', 'ftp', 'sftp', 's3'], help="Manually specify the upload protocol") upload_grp.add_argument("--upload-no-ssl-verify", default=False, action='store_true', help="Disable SSL verification for upload url") upload_grp.add_argument("--upload-target", default='local', choices=[ 'redhat', 'canonical', 'generic', 'local'], help=("Manually specify vendor-specific " "target for uploads. Supported " "options are:\n" "redhat, canonical, " "generic, local")) @classmethod def display_help(cls, section): section.set_title('SoS Upload Detailed Help') section.add_text( 'The upload command is designed to upload already existing ' 'sos reports, as well as other files like logs and vmcores ' 'to a distribution specific location.' ) def intro(self): """Print the intro message and prompts for a case ID if one is not provided on the command line """ disclaimer = """\ This utility is used to upload files to a target location \ based either on a command line option or detecting the local \ distribution. The archive to be uploaded may contain data considered sensitive \ and its content should be reviewed by the originating \ organization before being passed to any third party. No configuration changes will be made to the system running \ this utility. """ self.ui_log.info(f"\nsos upload (version {__version__})") intro_msg = self._fmt_msg(disclaimer) self.ui_log.info(intro_msg) prompt = "\nPress ENTER to continue, or CTRL-C to quit\n" if not self.opts.batch: try: input(prompt) self.ui_log.info("") except KeyboardInterrupt: self._exit("Exiting on user cancel", 130) except Exception as e: self._exit(e, 1) def get_commons(self): return { 'cmdlineopts': self.opts, 'policy': self.policy, 'case_id': self.opts.case_id, 'upload_directory': self.opts.upload_directory } def set_commons(self, commons): """Set common host data for the Upload targets to reference """ self.commons = commons def determine_upload_target(self): """This sets the upload target and loads that target's options. If no upload target is matched and no target is provided by the user, then we abort. If an upload target is provided in the command line, this will not run. """ checks = list(self.upload_targets.values()) for upload_target in self.upload_targets.values(): checks.remove(upload_target) if upload_target.check_distribution(): cname = upload_target.__class__.__name__ self.ui_log.debug(f"Installation matches {cname}, checking for" " upload targets") self.upload_target = upload_target self.upload_name = upload_target.name() if not self.upload_target: self.upload_target = self.upload_targets["generic"] self.upload_name = self.upload_target.name() self.ui_log.info( f"Upload target set to {self.upload_name}") def load_upload_targets(self): """Loads all upload targets supported by the local installation """ import sos.upload.targets supported_upload_tgts = {} for upload_target in self._load_modules(sos.upload.targets, 'targets'): target_class = upload_target[1]( parser=self.parser, args=self.args, cmdline=self.cmdline ) target_class.set_commons(self.get_commons()) supported_upload_tgts[target_class.get_target_id()] = target_class return supported_upload_tgts @classmethod def _load_modules(cls, package, submod): """Helper to import upload targets""" modules = [] for path in package.__path__: if os.path.isdir(path): modules.extend(cls._find_modules_in_path(path, submod)) return modules @classmethod def _find_modules_in_path(cls, path, modulename): """Given a path and a module name, find everything that can be imported and then import it path - the filesystem path of the package modulename - the name of the module in the package E.G. a path of 'targets', and a modulename of 'redhat' equates to importing sos.upload.targets.redhat """ modules = [] if os.path.exists(path): for pyfile in sorted(os.listdir(path)): if not pyfile.endswith('.py'): continue if '__' in pyfile: continue fname, _ = os.path.splitext(pyfile) modname = f'sos.upload.{modulename}.{fname}' modules.extend(cls._import_modules(modname)) return modules @classmethod def _import_modules(cls, modname): """Import and return all found classes in a module""" mod_short_name = modname.split('.')[2] try: module = __import__(modname, globals(), locals(), [mod_short_name]) except ImportError as e: raise e modules = inspect.getmembers(module, inspect.isclass) for mod in modules.copy(): if mod[0] in ( 'DeviceAuthorizationClass', 'Upload', 'RHELPolicy', 'UbuntuPolicy'): modules.remove(mod) return modules def pre_work(self): # This method will be called before upload begins self.commons = self.get_commons() cmdline_opts = self.commons['cmdlineopts'] if cmdline_opts.low_priority: self.policy._configure_low_priority() def execute(self): self.pre_work() if self.from_cmdline: self.intro() self.archive = self.opts.upload_file self.caseid = self.policy.prompt_for_case_id( cmdline_opts=self.opts ) cmdline_target = self.opts.upload_target if cmdline_target and cmdline_target != 'local': self.upload_target = self.upload_targets[cmdline_target] else: self.determine_upload_target() if not self.upload_target: # There was no upload target set, so we'll throw # an error here and exit self.ui_log.error( "No upload target set via command line options or" " autodetected.\n" "Please specify one using the option --upload-target.\n" "Exiting." ) sys.exit(1) self.upload_target.pre_work(self.get_commons()) try: if os.stat(self.archive).st_size > 0: if os.path.isfile(self.archive): try: self.upload_target.upload_archive(self.archive) self.ui_log.info( _(f"File {self.archive} uploaded successfully") ) except Exception as err: self.ui_log.error(_(f"Upload attempt failed: {err}")) sys.exit(1) else: self.ui_log.error(_(f"{self.archive} is not a file.")) else: self.ui_log.error(_(f"File {self.archive} is empty.")) except Exception as e: self.ui_log.error(_(f"Cannot upload {self.archive}: {e} ")) # vim: set et ts=4 sw=4 :