Skip to content

Commit

Permalink
using AWS Deep Learning Base AMI by default
Browse files Browse the repository at this point in the history
  • Loading branch information
apls777 committed May 8, 2019
1 parent 68ba3b9 commit e28b734
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 49 deletions.
21 changes: 6 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,7 @@ Use [pip](http://www.pip-installer.org/en/latest/) to install or upgrade Spotty:
- Read [this](https://medium.com/@apls/how-to-train-deep-learning-models-on-aws-spot-instances-using-spotty-8d9e0543d365)
article for a real-world example.

2. Create an AMI. Run the following command from the root directory of your project:

```bash
$ spotty aws create-ami
```

In several minutes you will have an AMI with NVIDIA Docker that Spotty will use
for all your projects within the AWS region.

3. Start an instance:
2. Start an instance:

```bash
$ spotty start
Expand All @@ -55,11 +46,7 @@ Use [pip](http://www.pip-installer.org/en/latest/) to install or upgrade Spotty:
It will run a Spot Instance, restore snapshots if any, synchronize the project with the running instance
and start the Docker container with the environment.

4. Train a model or run notebooks.

You can run custom scripts inside the Docker container using the `spotty run <SCRIPT_NAME>` command. Read more
about custom scripts in the documentation:
[Configuration: "scripts" section](https://apls777.github.io/spotty/docs/configuration/#scripts-section-optional).
3. Train a model or run notebooks.

To connect to the running container via SSH, use the following command:

Expand All @@ -71,6 +58,10 @@ Use [pip](http://www.pip-installer.org/en/latest/) to install or upgrade Spotty:
__`Ctrl + b`__, then __`d`__ combination of keys. To be attached to that session later, just use the
`spotty ssh` command again.

Also, you can run your custom scripts inside the Docker container using the `spotty run <SCRIPT_NAME>` command. Read more
about custom scripts in the documentation:
[Configuration: "scripts" section](https://apls777.github.io/spotty/docs/configuration/#scripts-section-optional).

## Contributions

Any feedback or contributions are welcome! Please check out the [guidelines](CONTRIBUTING.md).
Expand Down
4 changes: 4 additions & 0 deletions spotty/providers/aws/config/instance_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def on_demand(self) -> bool:
def ami_name(self) -> str:
return self._params['amiName'] if self._params['amiName'] else DEFAULT_AMI_NAME

@property
def has_ami_name(self) -> bool:
return bool(self._params['amiName'])

@property
def ami_id(self) -> str:
return self._params['amiId']
Expand Down
9 changes: 0 additions & 9 deletions spotty/providers/aws/deployment/abstract_aws_deployment.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from abc import ABC, abstractmethod
import boto3
from spotty.providers.aws.aws_resources.image import Image
from spotty.providers.aws.aws_resources.subnet import Subnet
from spotty.providers.aws.aws_resources.vpc import Vpc
from spotty.providers.aws.config.instance_config import InstanceConfig
Expand Down Expand Up @@ -40,11 +39,3 @@ def get_vpc_id(self) -> str:
vpc_id = default_vpc.vpc_id

return vpc_id

def get_ami(self) -> Image:
if self.instance_config.ami_id:
image = Image.get_by_id(self._ec2, self.instance_config.ami_id)
else:
image = Image.get_by_name(self._ec2, self.instance_config.ami_name)

return image
7 changes: 4 additions & 3 deletions spotty/providers/aws/deployment/ami_deployment.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from spotty.commands.writers.abstract_output_writrer import AbstractOutputWriter
from spotty.providers.aws.aws_resources.image import Image
from spotty.providers.aws.deployment.abstract_aws_deployment import AbstractAwsDeployment
from spotty.providers.aws.aws_resources.instance import Instance
from spotty.providers.aws.deployment.cf_templates.ami_template import prepare_ami_template
Expand Down Expand Up @@ -31,9 +32,9 @@ def deploy(self, debug_mode: bool, output: AbstractOutputWriter):
raise ValueError('"%s" is not a GPU instance' % instance_type)

# check that an image with this name doesn't exist yet
ami = self.get_ami()
ami = Image.get_by_name(self._ec2, self.instance_config.ami_name)
if ami:
raise ValueError('AMI with the name "%s" already exists.' % ami.name)
raise ValueError('AMI with the name "%s" already exists.' % self.instance_config.ami_name)

# check availability zone and subnet
check_az_and_subnet(self._ec2, self.instance_config.region, self.instance_config.availability_zone,
Expand Down Expand Up @@ -77,7 +78,7 @@ def delete(self, output: AbstractOutputWriter):
stack_id = None
if not self.stack.get_stack():
# try to get the stack ID from the AMI tags (for older versions of Spotty)
ami = self.get_ami()
ami = Image.get_by_name(self._ec2, self.instance_config.ami_name)
if not ami:
raise ValueError('AMI with the name "%s" not found.' % self.instance_config.ami_name)

Expand Down
34 changes: 30 additions & 4 deletions spotty/providers/aws/deployment/instance_deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from spotty.config.project_config import ProjectConfig
from spotty.config.validation import is_subdir
from spotty.deployment.abstract_instance_volume import AbstractInstanceVolume
from spotty.providers.aws.aws_resources.image import Image
from spotty.providers.aws.aws_resources.snapshot import Snapshot
from spotty.providers.aws.aws_resources.volume import Volume
from spotty.providers.aws.config.instance_config import VOLUME_TYPE_EBS
Expand All @@ -13,7 +14,6 @@
from spotty.providers.aws.deployment.project_resources.ebs_volume import EbsVolume
from spotty.providers.aws.deployment.cf_templates.instance_template import prepare_instance_template
from spotty.providers.aws.deployment.project_resources.instance_profile_stack import InstanceProfileStackResource
from spotty.providers.aws.errors.ami_not_found import AmiNotFoundError
from spotty.providers.aws.helpers.download import get_tmp_instance_s3_path
from spotty.providers.aws.helpers.sync import sync_project_with_s3, get_project_s3_path, get_instance_sync_arguments
from spotty.providers.aws.deployment.project_resources.bucket import BucketResource
Expand Down Expand Up @@ -144,9 +144,8 @@ def _get_template_parameters(self, instance_profile_arn: str, instance_name: str
vpc_id = self.get_vpc_id()

# get image info
ami = self.get_ami()
if not ami:
raise AmiNotFoundError(self.instance_config.ami_name)
ami = self._get_ami()
output.write('- AMI: "%s" (%s)' % (ami.name, ami.image_id))

# check root volume size
root_volume_size = self.instance_config.root_volume_size
Expand Down Expand Up @@ -195,6 +194,33 @@ def _get_template_parameters(self, instance_profile_arn: str, instance_name: str

return parameters

def _get_ami(self) -> Image:
if self.instance_config.ami_id:
image = Image.get_by_id(self._ec2, self.instance_config.ami_id)
if not image:
ValueError('AMI with ID=%s not found.' % self.instance_config.ami_id)
else:
image = Image.get_by_name(self._ec2, self.instance_config.ami_name)
if not image:
if self.instance_config.has_ami_name:
# AMI with the name specified in the configuration file was not found
ValueError('AMI with the name "%s" was not found.' % self.instance_config.ami_name)
else:
# get the latest "Deep Learning Base AMI"
res = self._ec2.describe_images(
Owners=['amazon'],
Filters=[{'Name': 'name', 'Values': ['Deep Learning Base AMI (Ubuntu)*']}],
)

if not len(res['Images']):
raise ValueError('AWS Deep Learning Base AMI not found.\n'
'Use the "spotty aws create-ami" command to create an AMI with NVIDIA Docker.')

image_info = sorted(res['Images'], key=lambda x: x['CreationDate'], reverse=True)[0]
image = Image(self._ec2, image_info)

return image

def apply_deletion_policies(self, output: AbstractOutputWriter):
"""Applies deletion policies to the EBS volumes."""

Expand Down
5 changes: 0 additions & 5 deletions spotty/providers/aws/errors/ami_not_found.py

This file was deleted.

13 changes: 0 additions & 13 deletions spotty/providers/aws/instance_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from spotty.providers.aws.config.instance_config import InstanceConfig
from spotty.providers.aws.deployment.ami_deployment import AmiDeployment
from spotty.providers.aws.deployment.instance_deployment import InstanceDeployment
from spotty.providers.aws.errors.ami_not_found import AmiNotFoundError
from spotty.providers.aws.helpers.download import download_from_s3_to_local, upload_from_instance_to_s3
from spotty.providers.aws.helpers.sync import sync_project_with_s3, sync_instance_with_s3
from spotty.providers.abstract_instance_manager import AbstractInstanceManager
Expand Down Expand Up @@ -52,18 +51,6 @@ def start(self, output: AbstractOutputWriter, dry_run=False):
instance.terminate()
instance.wait_instance_terminated()

# check that the AMI exists
if not deployment.get_ami():
print('The AMI "%s" doesn\'t exist. Do you want to create it?'
% self.instance_config.ami_name)
res = input('Type "y" to confirm: ')
if res == 'y':
# create an AMI
self.ami_deployment.deploy(False, output)
output.write()
else:
raise AmiNotFoundError(self.instance_config.ami_name)

# deploy the instance
deployment.deploy(self.project_config, output, dry_run=dry_run)

Expand Down

0 comments on commit e28b734

Please sign in to comment.