def upload_binary_to_custom_s3_bucket(botname, filepath, zipfile, bucket): ''' Uploads a binary and source directory to a custom S3 bucket. ''' s3_client = boto3.client('s3', **CUSTOM_AWS_CREDS) binary_obj = botname if zipfile is not None: zip_obj = '{}-src.zip'.format(botname) try: s3_client.upload_file(filepath, bucket, binary_obj, ExtraArgs={'ACL': 'public-read'}) if zipfile is not None: s3_client.upload_file(zipfile, bucket, zip_obj, ExtraArgs={'ACL': 'public-read'}) except ClientError as e: error('Uploading binary and source to custom S3 failed.') print(e) exit(1) if zipfile is not None: info('Uploaded source `{}` and binary `{}` successfully!'.format( zip_obj, binary_obj)) else: info('Uploaded binary `{}` successfully!'.format(binary_obj))
def get_user(): try: athena_user = str(getpass.getuser()) except Exception as e: error('Could not get student username.') print(e) exit(1) info('Found username `{}`.'.format(athena_user)) return athena_user
def add_player_to_db(name, official_name, desc): data = {'name': name, 'official_name': official_name, 'desc': desc} resp = requests.post(PLAYER_REPO_SERVER + '/add', data=data) resp_json = json.loads(resp.text) if 'error' in resp_json: err = resp_json['error'] error('Failed to add player `{}` to our custom database: {}'.format( name, err)) exit(1) else: info(resp.text)
def test_6172_s3_bucket_valid(): # Test for bucket existence. s3 = boto3.resource('s3') bucket = s3.Bucket(STUDENT_BUCKET) try: s3.meta.client.head_bucket(Bucket=STUDENT_BUCKET) except botocore.exceptions.ClientError as e: error_code = int(e.response['Error']['Code']) if error_code == 404: error( 'Amazon S3 Bucket `{}` does not exist.'.format(STUDENT_BUCKET)) else: error('Could not get Amazon S3 bucket.') print(e) exit(1) info('Using bucket `{}`.'.format(STUDENT_BUCKET))
def main(binary, srcpath, botname, botdesc): ALLOWED_CHARS = set( '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_') if not all(c in ALLOWED_CHARS for c in botname): error( 'Bot name must only contain alphanumeric characters or the underscore.' ) exit(1) if not os.path.isfile(binary): error('`{}` is not a file.'.format(binary)) exit(1) if srcpath is not None and not os.path.isdir(srcpath): error('`{}` is not a directory.'.format(srcpath)) exit(1) check_player_in_db(botname) if srcpath is None: info('No source directory has been provided. ' 'Are you sure you want to upload a binary ' 'without the corresponding source?') if input('(y / n)').lower() != 'y': info('User canceled upload operation.') exit(1) zip_path = None if srcpath is not None: zip_path = zip_source_code(srcpath) info('Zipped source code at `{}` to `{}`.'.format(srcpath, zip_path)) athena_user, iam_user = get_user() official_name = '{}.{}'.format(athena_user, botname) info('Bot official_name is `{}`.'.format(official_name)) # Upload binary to custom bucket upload_binary_to_custom_s3_bucket(botname, binary, zip_path, CUSTOM_S3_BUCKET) # Upload binary to 6.172 S3 bucket test_6172_s3_bucket_valid() upload_binary_to_6172_s3_bucket(botname, binary, iam_user, athena_user) # Register bot with custom database add_player_to_db(botname, official_name, botdesc)
def upload_binary_to_6172_s3_bucket(botname, binary, iam_user, athena_user): ''' Uploads a binary to the student bucket. ''' s3_client = boto3.client('s3') upload_key = '/'.join( [OBJECT_KEY_PREFIX, iam_user, OBJECT_KEY_BINARIES, botname]) info('Uploading bot `{}` located at path ' '`{}` to ~/s3home/{}/{} on instance.'.format( botname, binary, OBJECT_KEY_BINARIES, botname, )) try: s3_client.upload_file(binary, STUDENT_BUCKET, upload_key, ExtraArgs={'ACL': 'bucket-owner-full-control'}) except Exception as e: error('Was not able to upload bot to the Amazon S3 bucket.') print(e) exit(1) # Register the binary with the server. info('Registering bot `{}` with server...'.format(botname)) endpoint = 'http://{}/upload/{}/{}'.format(REG_SERVER, botname, athena_user) try: resp = requests.get(endpoint) except Exception as e: error('Cannot contact registration server `{}`.'.format(REG_SERVER)) print(e) exit(1) if len(resp.text) > 0: error('Server error: {}'.format(resp.text)) exit(1) else: info('Registration success!')
def round_robin(players, time_control, round_robin_rounds, username): # Get the list of uploaded binaries pipe = subprocess.Popen(['autotest-list', '10000'], stdout=subprocess.PIPE, universal_newlines=True) staff_binaries = set(['reference', 'reference_plusplus']) binaries = set() output = pipe.communicate()[0] for line in output.split('\n'): player = line.split(' ')[0] if player.startswith(username): binaries.add(player) all_binaries = staff_binaries.union(binaries) info( 'All available competitors (add #<number> to multiply total time, e.g. reference*4 has 4x time): ' ) for binary in binaries: info('* {}'.format(binary)) for i in range(0, len(players)): if players[i] not in staff_binaries and not players[i].startswith( username): players[i] = '{}.{}'.format(username, players[i]) for p in players: base_p, _ = parse_player_name(p) if base_p not in all_binaries: error('Bot `{}` has not been uploaded to the 6.172 server.'.format( p)) exit(1) # No need to modify anything below this line. autotest_filename = '/tmp/tmp.6172_autotest-{}'.format(uuid.uuid4()) with open(autotest_filename, 'w') as f: f.write('***Manual Game List***\n') f.write('{}.\n'.format(username)) tc_inc = TIME_CONTROL_MAP[time_control]['tc_inc'] tc_pool = TIME_CONTROL_MAP[time_control]['tc_pool'] # Schedule round robin rounds for i in range(round_robin_rounds): for p1 in players: for p2 in players: # Set up time multipliers. p1_base, p1_mul = parse_player_name(p1) p2_base, p2_mul = parse_player_name(p2) if p1_base == p2_base: continue game_str = '{} {} {} {} true {} {}'.format( p1_base, p2_base, int(tc_pool * p1_mul), tc_inc * p1_mul, int(tc_pool * p2_mul), tc_inc * p2_mul) info('Queuing game: {}'.format(game_str)) f.write('{}\n'.format(game_str)) subprocess.call(['autotest-lowlevelrun', autotest_filename])