# coding=utf-8 # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. """Functions here interact with Amazon EC2 using boto. """ import os import platform import shutil import boto.exception from boto.s3.connection import Key from boto.s3.connection import S3Connection import boto.utils def isEC2VM(): # pylint: disable=invalid-name,missing-return-doc,missing-return-type-doc """Test to see if the specified S3 cache is available, but only on non-WSL Linux systems.""" if not (platform.system() == "Linux" and "Microsoft" not in platform.release()): return False try: return bool(boto.utils.get_instance_metadata(num_retries=1, timeout=1)["instance-id"]) except KeyError: return False class S3Cache: # pylint: disable=missing-docstring def __init__(self, bucket_name): self.bucket = None self.bucket_name = bucket_name def connect(self): # pylint: disable=missing-return-doc,missing-return-type-doc """Connect to the S3 bucket, but only on non-WSL Linux systems.""" if not (platform.system() == "Linux" and "Microsoft" not in platform.release()): return False EC2_PROFILE = None if isEC2VM() else "laniakea" # pylint: disable=invalid-name try: conn = S3Connection(profile_name=EC2_PROFILE) self.bucket = conn.get_bucket(self.bucket_name) return True except boto.provider.ProfileNotFoundError: print(f'Unable to connect via boto using profile name "{EC2_PROFILE}" in ~/.boto') return False except boto.exception.S3ResponseError: print(f'Unable to connect to the following bucket "{self.bucket_name}", please check your credentials.') return False def downloadFile(self, origin, dest): # pylint: disable=invalid-name,missing-param-doc,missing-return-doc # pylint: disable=missing-return-type-doc,missing-type-doc """Download files from S3.""" key = self.bucket.get_key(origin) if key is not None: key.get_contents_to_filename(dest) print("Finished downloading.") return True return False def compressAndUploadDirTarball(self, directory, tarball_path): # pylint: disable=invalid-name,missing-param-doc # pylint: disable=missing-type-doc """Compress a directory into a bz2 tarball and upload it to S3.""" print("Creating archive...") shutil.make_archive(directory, "bztar", directory) self.uploadFileToS3(tarball_path) def uploadFileToS3(self, filename): # pylint: disable=invalid-name,missing-param-doc,missing-type-doc """Upload file to S3.""" # Root folder of the S3 bucket destDir = "" # pylint: disable=invalid-name destpath = os.path.join(destDir, os.path.basename(filename)) print(f"Uploading {filename} to Amazon S3 bucket {self.bucket_name}") k = Key(self.bucket) k.key = destpath k.set_contents_from_filename(filename, reduced_redundancy=True) def uploadStrToS3(self, destDir, filename, contents): # pylint: disable=invalid-name,missing-param-doc # pylint: disable=missing-type-doc """Upload a string to an S3 file.""" print(f"Uploading {filename} to Amazon S3 bucket {self.bucket_name}") k2 = Key(self.bucket) # pylint: disable=invalid-name k2.key = os.path.join(destDir, filename) k2.set_contents_from_string(contents, reduced_redundancy=True) print() # This newline is needed to get the path of the compiled binary printed on a newline.