#########################################################################
#
# Copyright (C) 2016 OSGeo
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################
import configparser
# pip install boto3
# You will also need:
# - A .pem keyfile generated using the Amazon web interface to launch
# new instances
# - The secret and access keys created from the
# The only pre-reqs are having created a keypair (.pem file)
# via the amazon web interface and knowing the AWS key and secret
#
# Usage:
# export AWS_ACCESS_KEY_ID='blahblah'
# export AWS_SECRET_ACCESS_KEY='blebleble'
# ec2.py launch
import os
import sys
import time
import logging
import botocore
import boto3
[docs]
CONFIG_FILE = ".gnec2.cfg"
[docs]
logger = logging.getLogger(__name__)
# Ubuntu
# https://help.ubuntu.com/community/EC2StartersGuide
# All us-east-1 EBS Backed
[docs]
LUCID_32 = "ami-3e9b4957"
[docs]
LUCID_64 = "ami-349b495d"
[docs]
MAVERIK_32 = "ami-c012cea9"
[docs]
MAVERIK_64 = "ami-c412cead"
[docs]
NATTY_32 = "ami-1616ca7f"
[docs]
NATTY_64 = "ami-e016ca89"
[docs]
ONEIRIC_32 = "ami-e1aa7388"
[docs]
ONEIRIC_64 = "ami-8baa73e2"
[docs]
PRECISE_32 = "ami-b89842d1"
[docs]
PRECISE_64 = "ami-3c994355"
[docs]
TRUSTY_32 = "ami-134b0923"
[docs]
TRUSTY_64 = "ami-d0ba0cb8"
# CentOS
# All us-east-1
[docs]
CENTOS_54_32 = "ami-f8b35e91"
[docs]
CENTOS_54_64 = "ami-ccb35ea5"
[docs]
CENTOS_62_32 = "ami-5c4e9235"
[docs]
DEFAULT_BASE = TRUSTY_64
[docs]
DEFAULT_INSTANCE_TYPE = 't2.small'
[docs]
GEONODE_MAVERIK_32 = ""
[docs]
GEONODE_MAVERIK_64 = ""
[docs]
GEONODE_ONEIRIC_32 = ""
[docs]
GEONODE_ONEIRIC_64 = ""
[docs]
GEONODE_PRECISE_32 = ""
[docs]
GEONODE_PRECISE_64 = ""
[docs]
DEFAULT_BASE_GEONODE = GEONODE_PRECISE_32
[docs]
ALPHA_ELASTIC_IP = "54.235.204.189"
[docs]
def wait_for_state(ec2, instance_id, state):
assert state in ('pending', 'running', 'shutting-down',
'terminated', 'stopped')
# Poll for 10 minutes for instance to transition to the specified state
for i in range(120):
for reservation in ec2.describe_instances(
InstanceIds=[instance_id])['Reservations']:
for instance in reservation['Instances']:
if instance['InstanceId'] == instance_id and \
instance['State']['Name'] == state:
return instance
time.sleep(5)
[docs]
def writeconfig(config):
# Writing our configuration file to CONFIG_FILE
with open(CONFIG_FILE, 'wb') as configfile:
config.write(configfile)
[docs]
def readconfig(default_ami=None):
config = configparser.RawConfigParser()
# If there is no config file, let's write one.
if not os.path.exists(CONFIG_FILE):
config.add_section('ec2')
if default_ami is None:
config.set('ec2', 'AMI', DEFAULT_BASE)
else:
config.set('ec2', 'AMI', default_ami)
config.set('ec2', 'INSTANCE', '')
config.set('ec2', 'INSTANCE_TYPE', DEFAULT_INSTANCE_TYPE)
config.set('ec2', 'SECURITY_GROUP', 'geonode')
config.set('ec2', 'KEY_PATH', '~/.ssh/geonode-dev.pem')
config.set('ec2', 'USER', 'ec2-user')
writeconfig(config)
else:
config.read(CONFIG_FILE)
return config
[docs]
def launch_geonode():
readconfig(default_ami=DEFAULT_BASE_GEONODE)
launch()
[docs]
def launch_base():
readconfig(default_ami=DEFAULT_BASE)
launch()
[docs]
def set_alpha_ip():
config = readconfig()
instance_id = config.get('ec2', 'INSTANCE')
ec2 = boto3.client('ec2')
try:
allocation = ec2.allocate_address(Domain='vpc')
response = ec2.associate_address(
AllocationId=allocation['AllocationId'],
InstanceId=instance_id,
PublicIp=ALPHA_ELASTIC_IP)
return response
except botocore.exceptions.ClientError as e:
print(e)
return None
[docs]
def launch():
config = readconfig()
ami = config.get('ec2', 'AMI')
group_name = config.get('ec2', 'SECURITY_GROUP')
key_name = 'geonode'
key_path = config.get('ec2', 'KEY_PATH')
instance_type = config.get('ec2', 'INSTANCE_TYPE')
if config.has_option('ec2', 'HOST'):
host = config.get('ec2', 'HOST')
if host != "" and host is not None:
print("There is already an instance launched")
return
ec2 = boto3.client('ec2')
vpc_id = ec2.describe_vpcs().get('Vpcs', [{}])[0].get('VpcId', '')
try:
geonode_group = ec2.describe_security_groups(
GroupNames=[group_name])['SecurityGroups'][0]
except botocore.exceptions.ClientError:
# Create the security group
geonode_group = ec2.create_security_group(
GroupName=group_name, Description='GeoNode rules.', VpcId=vpc_id)
port_ranges = [
(21, 21), # Batch upload FTP
(22, 22), # SSH
(80, 80), # Apache
(2300, 2400), # Passive FTP
(8000, 8001), # Dev Django and Jetty
(8021, 8021), # Batch upload FTP
(8080, 8080), # Tomcat
]
for from_port, to_port in port_ranges:
ec2.authorize_security_group_ingress(
GroupId=geonode_group['GroupId'],
IpProtocol='tcp',
FromPort=from_port,
ToPort=to_port,
CidrIp='0.0.0.0/0')
try:
key_pairs = ec2.describe_key_pairs(KeyNames=[key_name])['KeyPairs']
except botocore.exceptions.ClientError:
# Key is not likely not defined
logger.warning("GeoNode file not found in server.")
key_pairs = ec2.describe_key_pairs()['KeyPairs']
key = key_pairs[0] if len(
key_pairs) > 0 else ec2.create_key_pair(KeyName=key_name)
reservation = ec2.run_instances(
ImageId=ami,
InstanceType=instance_type,
KeyName=key['KeyName'],
MaxCount=1,
MinCount=1,
SecurityGroupIds=[
geonode_group['GroupId']])
instance_id = [instance['InstanceId']
for instance in reservation['Instances']
if instance['ImageId'] == ami][0]
print("Firing up instance...")
instance = wait_for_state(ec2, instance_id, 'running')
dns = instance['PublicDnsName']
print(f"Instance running at {dns}")
config.set('ec2', 'HOST', dns)
config.set('ec2', 'INSTANCE', instance_id)
writeconfig(config)
print(f"ssh -i {key_path} ubuntu@{dns}")
print("Terminate the instance via the web interface.")
time.sleep(20)
[docs]
def terminate():
config = readconfig()
instance_id = config.get('ec2', 'INSTANCE')
ec2 = boto3.client('ec2')
ec2.terminate_instances(InstanceIds=[instance_id])
print("Terminating instance...")
wait_for_state(ec2, instance_id, 'terminated')
print("Instance terminated.")
config.set('ec2', 'HOST', '')
config.set('ec2', 'INSTANCE', '')
with open(CONFIG_FILE, 'wb') as configfile:
config.write(configfile)
if __name__ == '__main__':
if sys.argv[1] == "launch_geonode":
launch_geonode()
elif sys.argv[1] == "launch_base":
launch_base()
elif sys.argv[1] == "set_alpha_ip":
set_alpha_ip()
elif sys.argv[1] == "terminate":
terminate()
elif sys.argv[1] == "host":
print(config.get('ec2', 'HOST'))
elif sys.argv[1] == "key":
config = readconfig()
print(config.get('ec2', 'KEY_PATH'))
else:
print(f"Usage:\n python {sys.argv[0]} launch_base\n python {sys.argv[0]} launch_geonode\n python {sys.argv[0]} terminate")