#!/usr/bin/env python3

import argparse

import boto3

BLOCKSIZE = 512 * 1024

IPXELOG_OFFSET = 16 * 1024

IPXELOG_MAGIC = b'iPXE LOG'


def create_snapshot(region, instance_id):
    """Create root volume snapshot"""
    client = boto3.client('ec2', region_name=region)
    resource = boto3.resource('ec2', region_name=region)
    instance = resource.Instance(instance_id)
    volumes = list(instance.volumes.all())
    snapshot = volumes[0].create_snapshot()
    snapshot.wait_until_completed()
    return snapshot.id


def get_snapshot_block(region, snapshot_id, index):
    """Get block content from snapshot"""
    client = boto3.client('ebs', region_name=region)
    blocks = client.list_snapshot_blocks(SnapshotId=snapshot_id,
                                         StartingBlockIndex=index)
    token = blocks['Blocks'][0]['BlockToken']
    block = client.get_snapshot_block(SnapshotId=snapshot_id,
                                      BlockIndex=index,
                                      BlockToken=token)
    return block['BlockData'].read()


def get_block0_content(region, instance_id):
    """Get content of root volume block zero from instance"""
    client = boto3.client('ec2', region_name=region)
    resource = boto3.resource('ec2', region_name=region)
    snapshot_id = create_snapshot(region, instance_id)
    block = get_snapshot_block(region, snapshot_id, 0)
    resource.Snapshot(snapshot_id).delete()
    return block


def get_int13con_output(region, instance_id):
    """Get INT13 console output"""
    block = get_block0_content(region, instance_id)
    logpart = block[IPXELOG_OFFSET:]
    magic = logpart[:len(IPXELOG_MAGIC)]
    if magic != IPXELOG_MAGIC:
        raise ValueError("Invalid log magic signature")
    log = logpart[len(IPXELOG_MAGIC):].split(b'\0')[0]
    return log.decode()


# Parse command-line arguments
parser = argparse.ArgumentParser(description="Get AWS INT13 console output")
parser.add_argument('--region', '-r', help="AWS region")
parser.add_argument('id', help="Instance ID")
args = parser.parse_args()

# Get console output from INT13CON partition
output = get_int13con_output(args.region, args.id)

# Print console output
print(output)
