{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### End to End demo of starting spot instance in AWS" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%reload_ext autoreload\n", "%autoreload 2\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from aws_setup import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Testing" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[ec2.KeyPairInfo(name='AmazonEC2test'),\n", " ec2.KeyPairInfo(name='aws-key-fast-ai'),\n", " ec2.KeyPairInfo(name='aws-key-test-vpc'),\n", " ec2.KeyPairInfo(name='id_rsa'),\n", " ec2.KeyPairInfo(name='Mac')]" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(ec2.key_pairs.all())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Define parameters" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "collapsed": true }, "outputs": [], "source": [ "vpc_name='fast-ai'\n", "instance_name = f'{vpc_name}-instance'\n", "instance_type = 't2.medium'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Get Existing VPC by tag name" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "ec2.Vpc(id='vpc-6e6b2a17')" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" } ], "source": [ "vpc = get_vpc(vpc_name); vpc" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Request Spot instance" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'0.031900'" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spot_prices = get_spot_prices(); spot_prices[instance_type]" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": true }, "outputs": [], "source": [ "launch_specs = LaunchSpecs(vpc, instance_type=instance_type, volume_size=80).build()" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'BlockDeviceMappings': [{'DeviceName': '/dev/sda1',\n", " 'Ebs': {'DeleteOnTermination': True,\n", " 'VolumeSize': 80,\n", " 'VolumeType': 'gp2'}}],\n", " 'ImageId': 'ami-8c4288f4',\n", " 'InstanceType': 't2.medium',\n", " 'KeyName': 'aws-key-fast-ai',\n", " 'NetworkInterfaces': [{'AssociatePublicIpAddress': True,\n", " 'DeviceIndex': 0,\n", " 'Groups': ['sg-f60fca88'],\n", " 'SubnetId': 'subnet-f056ff89'}]}" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "launch_specs" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Waiting on spot fullfillment...\n", "Fulfillment completed. InstanceId: i-07f29a1137e5bd67f\n", "Rebooting...\n", "Completed. SSH: ssh -i ~/.ssh/aws-key-fast-ai.pem ubuntu@34.217.9.117\n" ] }, { "data": { "text/plain": [ "ec2.Instance(id='i-07f29a1137e5bd67f')" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "instance = create_spot_instance(instance_name, launch_specs, spot_price='0.5'); instance" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Request on demand instance (if spot error)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# instance = create_instance(instance_name, vpc, instance_type='t2.micro'); instance" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "ec2.Instance(id='i-0976e3eb46f705bb0')" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "instance = get_instance(instance_name); instance" ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "collapsed": true }, "outputs": [], "source": [ "v1 = list(instance.volumes.all())[0]" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "ename": "ClientError", "evalue": "An error occurred (IncorrectState) when calling the DetachVolume operation: Volume 'vol-0ec18e0d7a4782ee8'is in the 'available' state.", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mClientError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mv1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdetach_from_instance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m~/miniconda3/envs/imagenet/lib/python3.6/site-packages/boto3/resources/factory.py\u001b[0m in \u001b[0;36mdo_action\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 518\u001b[0m \u001b[0;31m# instance via ``self``.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 519\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdo_action\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 520\u001b[0;31m \u001b[0mresponse\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0maction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 521\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 522\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'load'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/miniconda3/envs/imagenet/lib/python3.6/site-packages/boto3/resources/action.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, parent, *args, **kwargs)\u001b[0m\n\u001b[1;32m 81\u001b[0m operation_name, params)\n\u001b[1;32m 82\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 83\u001b[0;31m \u001b[0mresponse\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmeta\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mclient\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moperation_name\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mparams\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 84\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 85\u001b[0m \u001b[0mlogger\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdebug\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Response: %r'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mresponse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/miniconda3/envs/imagenet/lib/python3.6/site-packages/botocore/client.py\u001b[0m in \u001b[0;36m_api_call\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 312\u001b[0m \"%s() only accepts keyword arguments.\" % py_operation_name)\n\u001b[1;32m 313\u001b[0m \u001b[0;31m# The \"self\" in this scope is referring to the BaseClient.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 314\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_make_api_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0moperation_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 315\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 316\u001b[0m \u001b[0m_api_call\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__name__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpy_operation_name\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/miniconda3/envs/imagenet/lib/python3.6/site-packages/botocore/client.py\u001b[0m in \u001b[0;36m_make_api_call\u001b[0;34m(self, operation_name, api_params)\u001b[0m\n\u001b[1;32m 610\u001b[0m \u001b[0merror_code\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparsed_response\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Error\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Code\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 611\u001b[0m \u001b[0merror_class\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexceptions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrom_code\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0merror_code\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 612\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0merror_class\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparsed_response\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moperation_name\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 613\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 614\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mparsed_response\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mClientError\u001b[0m: An error occurred (IncorrectState) when calling the DetachVolume operation: Volume 'vol-0ec18e0d7a4782ee8'is in the 'available' state." ] } ], "source": [ "v1.detach_from_instance()" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'in-use'" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v1.state" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### SSH" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connecting to SSH...\n", "Connected!\n" ] } ], "source": [ "client = connect_to_instance(instance)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Attach EBS volume (Optional)" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "collapsed": true }, "outputs": [], "source": [ "volume_tag = 'fast-ai-imagenet'" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": true }, "outputs": [], "source": [ "_ = attach_volume(instance, volume_tag, device='/dev/xvdf')" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connecting to SSH...\n", "Connected!\n" ] } ], "source": [ "mount_volume(instance, device='/dev/xvdf', mount_dir='ebs_mount')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Mount EFS" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'fs-0ea233a7.efs.us-west-2.amazonaws.com'" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "efs_addr = get_efs_address('fast-ai-efs'); efs_addr" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "run_command returned: \n", "\n" ] } ], "source": [ "out, _ = run_command(client, 'mkdir ~/efs_mount_point')" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": true }, "outputs": [], "source": [ "efs_mount_cmd = f'sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 {efs_addr}:/ ~/efs_mount_point'" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "run_command returned: \n", "\n" ] } ], "source": [ "out, _ = run_command(client, efs_mount_cmd)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "run_command returned: \n", "efs_saved.txt\r\n", "\n" ] } ], "source": [ "out, _ = run_command(client, 'ls efs_mount_point') # no reformatting" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.3" } }, "nbformat": 4, "nbformat_minor": 2 }