# Boto3 for EC2

## Creating VMs - Creating Volumes - Attaching Volumes to VMs

This is a walk-through section for a script that does the following:

* Creates a connection to your AWS-compatible Zadara region.
* Creates a VM instance.
* Creates a volume.
* Attaches the volume to the VM instance.

1. **Import the boto3 and sys packages**:
   ```console
   import boto3
   import sys
   ```
2. **Define a main() function**:
   ```console
   def main():
    """
    This script shows an example of Boto3 integration with Zadara Cloud
    Services. The scenario is as follows:
         1. Instantiate an instance from an AMI.
         2. Create a 20 GB volume.
         3. Attach the volume to the created AMI.
    """
   ```
3. **Create a connection to your Zadara region**:

   This snippet creates the connection by using the boto `Session` resource
   to create a custom session. This custom session contains the following
   configuration values and credentials:
   - **Service name**: In order to create VMs, set the service name to `ec2`.
   - **Region**: When connecting to Zadara, set the region name to `symphony`.
   - **Endpoint URL**: This is the IP of the installed Zadara region, followed
     by `/api/v2/ec2/.`
   - **AWS access key and secret access key**: These are the keys from the
     Zadara Cloud Services GUI.

   ```console
   # creating a connection to Zadara Cloud Services AWS Compatible region
   client = boto3.Session.client(boto3.session.Session(), service_name="ec2",
         region_name="symphony",
         endpoint_url="https://<cluster ip>/api/v2/ec2/",
         verify=False,
         aws_access_key_id="<key>",
         aws_secret_access_key="<secret>")
   ```
4. **Get the image ID** of the image that will be used for creating a VM instance in a later step.
   This machine image was uploaded using the Zadara Cloud Services UI.
   1. Use the EC2 `describe_images()` method to list the images
      in the Zadara Cloud Service.
   2. Search the list of images to find the image whose `Name`
      attribute matches the name your image was given when it was uploaded through
      the Zadara Cloud Services UI. In this example, assume you named your image
      **centos**.
   3. Once the image to use is found, retrieve the image ID stored in its `ImageId`
      attribute and print out a status message.

   ```console
   # finding our Centos image, grabbing its image ID
   images = client.describe_images()
   image_id = next(image['ImageId'] for image in images if 'centos' in image['Name'])
   print "Found desired image with ID: " + image_id
   ```
5. **Create a new VM**:

   Use the `run_instances()` method, passing the image ID and count values.
   Output a status message.
   ```console
   # running a new instance using our Centos image ID
   ec2_instance = client.run_instances(
      ImageId=image_id,
      MinCount=1,
      MaxCount=1
   )

   # check if EC2 instance was created successfully
   if ec2_instance['ResponseMetadata']['HTTPStatusCode'] == 200:
      print "Successfully created instance! " + ec2_instance['Instances'][0]['InstanceId']
   ```
6. **Create a Volume**:
   1. Use the `create_volume()` method.

      Note that you need to set the `AvailabilityZone` to `symphony`.
   2. Get the volume ID of the newly created volume and assign it to the
      `volume_id` variable.
   3. Output a status message.

   ```console
   # create an EBS volume, 20G size
       ebs_vol = client.create_volume(
           Size=20,
           AvailabilityZone='symphony'
       )

       volume_id = ebs_vol['VolumeId
   # check that the EBS volume has been created successfully
       if ebs_vol['ResponseMetadata']['HTTPStatusCode'] == 200:
           print "Successfully created Volume! " + volume_id
   ```
7. **Attach the volume to the VM**, using the `attach_volume()` method.
   Pass in the `VolumeId` and the VM’s `InstanceId`. Set the `Device` name to `/dev/sdm`.
   ```console
   # attaching EBS volume to our EC2 instance
       attach_resp = client.attach_volume(
           VolumeId=volume_id,
           InstanceId=ec2_instance['Instances'][0]['InstanceId'],
           Device='/dev/sdm'
       )
   ```

   **Exit**.
   ```console
   if __name__ == '__main__':
   sys.exit(main(sys.argv[1:]))
   ```

<br/>

## Full Script for Creating VMs

```console
import boto3
import s
def main():
    """
    This script shows and example of Boto3 integration with Zadara Cloud Services.
    The scenario is as such:
         1. Instantiate an instance from an AMI,
         2. Create a 20 GB volume,
         3. Attach the volume to the created AMI.
    "
    # creating a connection to Zadara Cloud Services AWS Compatible region
    client = boto3.Session.client(boto3.session.Session(), service_name="ec2", region_name="symphony",
                                  endpoint_url="https://<cluster ip>/api/v2/ec2/",
                                  verify=False,
                                  aws_access_key_id="<key>",
                                  aws_secret_access_key="<secret>"
                                  )
    # finding our Centos image, grabbing its image ID
    images = client.describe_images()
    image_id = next(image['ImageId'] for image in images if 'centos' in image['Name'])
    print "Found desired image with ID: " + image_id
    # running a new instance using our Centos image ID
    ec2_instance = client.run_instances(
        ImageId=image_id,
        MinCount=1,
        MaxCount=1
    )

    # check if EC2 instance was created successfully
    if ec2_instance['ResponseMetadata']['HTTPStatusCode'] == 200:
        print "Successfully created instance! " + ec2_instance['Instances'][0]['InstanceId']

    # create an EBS volume, 20G size
    ebs_vol = client.create_volume(
        Size=20,
        AvailabilityZone='symphony'
        )

    volume_id = ebs_vol['VolumeId']

    # check that the EBS volume had been created successfully
    if ebs_vol['ResponseMetadata']['HTTPStatusCode'] == 200:
       print "Successfully created Volume! " + volume_id

    # attaching EBS volume to our EC2 instance
    attach_resp = client.attach_volume(
        VolumeId=volume_id,
        InstanceId=ec2_instance['Instances'][0]['InstanceId'],
        Device='/dev/sdm'
    )

    if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
```

## Creating VPCs and Security Groups

This snippet displays how to do the following:

- Create a Virtual Private Cloud (VPC) and subnet.
- Create a security group with ingress rules.
- Create a VM that resides in the subnet and uses the security group.

```console
# create VPC
vpc = boto.create_vpc(CidrBlock='10.0.0.0/24')
vpc_id = vpc['Vpc']['VpcId']

# create subnet
subnet = boto.create_subnet(VpcId=vpc_id, CidrBlock='10.0.0.0/24')

# create security group
response = boto.create_security_group(GroupName='my_group_name', Description='my_description', VpcId=vpc_id)
security_group_id = response['GroupId']

# add two ingress rules to the newly created security group,
# CIDR notation "0.0.0.0/0" allows access from anywhere
boto.authorize_security_group_ingress(GroupId=security_group_id, IpPermissions=},
    {'FromPort': 4000, 'ToPort': 4000, 'IpProtocol': 'tcp', 'IpRanges': [{'CidrIp': '0.0.0.0/0'}]}])

# create instance assuming that the image id is image_id
i1 = self.boto.run_instances(ImageId=image_id, MinCount=1, MaxCount=1,
                             NetworkInterfaces=[{'SubnetId': subnet_id, 'Groups': , 'DeviceIndex': 0}])
```

## Creating Key Pairs and Floating IPs

This snippet displays how to create a key pair and floating IP address.

```console
# create a new key pair for your account
key = boto.create_key_pair(KeyName="my_key_name")

# get the unencrypted PEM encoded RSA private key
# these will later be added to the machine
# from which to access the instance
pem = key['KeyMaterial']

i1 = boto.run_instances(KeyName='my_key_name', ImageId=image_id, MinCount=1, MaxCount=1,
                        NetworkInterfaces=[{'SubnetId': subnet_id, 'Groups': , 'DeviceIndex': 0}])

# create a floating IP in our VPC
allocation = sboto.allocate_address(Domain='vpc')
allocation_id = allocation['AllocationId']

# associate address with instance after getting its ID
boto.associate_address(InstanceId=i1_instance_id, allocation_id)
```

## Boto 3 Quick Ref for EC2

```console
import boto
client = boto3.client('ec2')
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| Commonly used methods                                                                                                                         |
+===============================================================================================================================================+
| `run_instances <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.run_instances>`__ (create one or more instances) |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| `describe_instances <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.describe_instances>`__                      |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| `start_instances <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.start_instances>`__                            |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| `stop_instances <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.stop_instances>`__                              |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| `reboot_instances <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.reboot_instances>`__                          |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| `terminate_instances <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.terminate_instances>`__                    |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| `create_volume <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.create_volume>`__                                |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| `attach_volume <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.attach_volume>`__                                |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| `create_image <http://boto3.readthedocs.io/en/latest/reference/services/ec2.html#EC2.Client.create_image>`__                                  |
+-----------------------------------------------------------------------------------------------------------------------------------------------
```
