| Server IP : 20.75.53.88 / Your IP : 216.73.217.72 [ 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 : /home/ralp/ |
Upload File : |
#!/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()