Add AWS::RDS::DBInstance

Fixes #163

This is an initial implementation of the DBInstance resource type and a
sample Wordpress template showing it off.

Change-Id: I5e156dc58eee563ae9de068664bafa1af1fb5ffe
Signed-off-by: Tomas Sedovic <tomas@sedovic.cz>
This commit is contained in:
Tomas Sedovic 2012-07-18 15:39:37 +02:00
parent 312a84ec70
commit 9c75b6d3b0
3 changed files with 372 additions and 0 deletions

203
heat/engine/dbinstance.py Normal file
View File

@ -0,0 +1,203 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import urllib2
import json
from heat.common import exception
from heat.engine import stack
from heat.db import api as db_api
from heat.engine import parser
from novaclient.exceptions import NotFound
from heat.openstack.common import log as logging
logger = logging.getLogger(__file__)
mysql_template = r'''
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Builtin RDS::DBInstance",
"Parameters" : {
"DBInstanceClass" : {
"Type": "String"
},
"DBName" : {
"Type": "String"
},
"MasterUsername" : {
"Type": "String"
},
"MasterUserPassword" : {
"Type": "String"
},
"AllocatedStorage" : {
"Type": "String"
},
"DBSecurityGroups" : {
"Type": "List"
},
"Port" : {
"Type": "String"
},
"KeyName" : {
"Type" : "String"
}
},
"Mappings" : {
"DBInstanceToInstance" : {
"db.m1.small": {"Instance": "m1.small"},
"db.m1.large": {"Instance": "m1.large"},
"db.m1.xlarge": {"Instance": "m1.xlarge"},
"db.m2.xlarge": {"Instance": "m2.xlarge"},
"db.m2.2xlarge": {"Instance": "m2.2xlarge"},
"db.m2.4xlarge": {"Instance": "m2.4xlarge"}
}
},
"Resources": {
"DatabaseInstance": {
"Type": "AWS::EC2::Instance",
"Metadata": {
"AWS::CloudFormation::Init": {
"config": {
"packages": {
"yum": {
"mysql" : [],
"mysql-server" : []
}
},
"services": {
"systemd": {
"mysqld" : { "enabled" : "true", "ensureRunning" : "true" }
}
}
}
}
},
"Properties": {
"ImageId": "F16-x86_64-cfntools",
"InstanceType": { "Fn::FindInMap": [ "DBInstanceToInstance",
{ "Ref": "DBInstanceClass" },
"Instance" ] },
"KeyName": { "Ref": "KeyName" },
"UserData": { "Fn::Base64": { "Fn::Join": ["", [
"#!/bin/bash -v\n",
"/opt/aws/bin/cfn-init\n",
"# Setup MySQL root password and create a user\n",
"mysqladmin -u root password '", {"Ref":"MasterUserPassword"},"'\n",
"cat << EOF | mysql -u root --password='",
{ "Ref" : "MasterUserPassword" }, "'\n",
"CREATE DATABASE ", { "Ref" : "DBName" }, ";\n",
"GRANT ALL PRIVILEGES ON ", { "Ref" : "DBName" },
".* TO \"", { "Ref" : "MasterUsername" }, "\"@\"%\"\n",
"IDENTIFIED BY \"", { "Ref" : "MasterUserPassword" }, "\";\n",
"FLUSH PRIVILEGES;\n",
"EXIT\n",
"EOF\n"
]]}}
}
}
},
"Outputs": {
}
}
'''
class DBInstance(stack.Stack):
properties_schema = {
'DBSnapshotIdentifier': {'Type': 'String',
'Implemented': False},
'AllocatedStorage': {'Type': 'String',
'Required': True},
'AvailabilityZone': {'Type': 'String',
'Implemented': False},
'BackupRetentionPeriod': {'Type': 'String',
'Implemented': False},
'DBInstanceClass': {'Type': 'String',
'Required': True},
'DBName': {'Type': 'String',
'Required': False},
'DBParameterGroupName': {'Type': 'String',
'Implemented': False},
'DBSecurityGroups': {'Type': 'List',
'Required': False, 'Default': []},
'DBSubnetGroupName': {'Type': 'String',
'Implemented': False},
'Engine': {'Type': 'String',
'AllowedValues': ['MySQL'],
'Required': True},
'EngineVersion': {'Type': 'String',
'Implemented': False},
'LicenseModel': {'Type': 'String',
'Implemented': False},
'MasterUsername': {'Type': 'String',
'Required': True},
'MasterUserPassword': {'Type': 'String',
'Required': True},
'Port': {'Type': 'String',
'Default': '3306',
'Required': False},
'PreferredBackupWindow': {'Type': 'String',
'Implemented': False},
'PreferredMaintenanceWindow': {'Type': 'String',
'Implemented': False},
'MultiAZ': {'Type': 'Boolean',
'Implemented': False},
}
def _params(self):
params = {
'KeyName': {'Ref': 'KeyName'},
}
# Add the DBInstance parameters specified in the user's template
# Ignore the not implemented ones
for key, value in self.properties_schema.items():
if value.get('Implemented', True) and key != 'Engine':
params[key] = self.properties[key]
p = self.stack.resolve_static_data(params)
return p
def handle_create(self):
templ = json.loads(mysql_template)
self.create_with_template(templ)
def FnGetAtt(self, key):
'''
We don't really support any of these yet.
'''
if key == 'Endpoint.Address':
if self.nested() and 'DatabaseInstance' in self.nested().resources:
return self.nested().resources['DatabaseInstance']._ipaddress()
else:
return '0.0.0.0'
elif key == 'Endpoint.Port':
return self.properties['Port']
else:
raise exception.InvalidTemplateAttribute(resource=self.name,
key=key)

View File

@ -22,6 +22,7 @@ from heat.engine import resources
from heat.engine import autoscaling
from heat.engine import cloud_watch
from heat.engine import dbinstance
from heat.engine import eip
from heat.engine import instance
from heat.engine import loadbalancer
@ -51,6 +52,7 @@ _resource_classes = {
'AWS::AutoScaling::LaunchConfiguration': autoscaling.LaunchConfiguration,
'AWS::AutoScaling::AutoScalingGroup': autoscaling.AutoScalingGroup,
'AWS::AutoScaling::ScalingPolicy': autoscaling.ScalingPolicy,
'AWS::RDS::DBInstance': dbinstance.DBInstance,
}

View File

@ -0,0 +1,167 @@
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation Sample Template WordPress_With_RDS: WordPress is web software you can use to create a beautiful website or blog. This template installs two instances: one running a WordPress deployment and the other using RDS as a data storage.",
"Parameters" : {
"KeyName" : {
"Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instances",
"Type" : "String"
},
"InstanceType" : {
"Description" : "WebServer EC2 instance type",
"Type" : "String",
"Default" : "m1.large",
"AllowedValues" : [ "t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "c1.medium", "c1.xlarge", "cc1.4xlarge" ],
"ConstraintDescription" : "must be a valid EC2 instance type."
},
"DBClass" : {
"Default" : "db.m1.small",
"Description" : "Database instance class",
"Type" : "String",
"AllowedValues" : [ "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge" ],
"ConstraintDescription" : "must select a valid database instance type."
},
"DBName": {
"Default": "wordpress",
"Description" : "The WordPress database name",
"Type": "String",
"MinLength": "1",
"MaxLength": "64",
"AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
"ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
},
"DBUsername": {
"Default": "admin",
"NoEcho": "true",
"Description" : "The WordPress database admin account username",
"Type": "String",
"MinLength": "1",
"MaxLength": "16",
"AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
"ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
},
"DBPassword": {
"Default": "admin",
"NoEcho": "true",
"Description" : "The WordPress database admin account password",
"Type": "String",
"MinLength": "1",
"MaxLength": "41",
"AllowedPattern" : "[a-zA-Z0-9]*",
"ConstraintDescription" : "must contain only alphanumeric characters."
},
"DBRootPassword": {
"Default": "admin",
"NoEcho": "true",
"Description" : "Root password for MySQL",
"Type": "String",
"MinLength": "1",
"MaxLength": "41",
"AllowedPattern" : "[a-zA-Z0-9]*",
"ConstraintDescription" : "must contain only alphanumeric characters."
},
"DBAllocatedStorage" : {
"Default": "5",
"Description" : "The size of the database (Gb)",
"Type": "Number",
"MinValue": "5",
"MaxValue": "1024",
"ConstraintDescription" : "must be between 5 and 1024Gb."
},
"LinuxDistribution": {
"Default": "F16",
"Description" : "Distribution of choice",
"Type": "String",
"AllowedValues" : [ "F16", "F17", "U10", "RHEL-6.1", "RHEL-6.2", "RHEL-6.3" ]
}
},
"Mappings" : {
"AWSInstanceType2Arch" : {
"t1.micro" : { "Arch" : "32" },
"m1.small" : { "Arch" : "32" },
"m1.large" : { "Arch" : "64" },
"m1.xlarge" : { "Arch" : "64" },
"m2.xlarge" : { "Arch" : "64" },
"m2.2xlarge" : { "Arch" : "64" },
"m2.4xlarge" : { "Arch" : "64" },
"c1.medium" : { "Arch" : "32" },
"c1.xlarge" : { "Arch" : "64" },
"cc1.4xlarge" : { "Arch" : "64" }
},
"DistroArch2AMI": {
"F16" : { "32" : "F16-i386-cfntools", "64" : "F16-x86_64-cfntools" },
"F17" : { "32" : "F17-i386-cfntools", "64" : "F17-x86_64-cfntools" },
"U10" : { "32" : "U10-i386-cfntools", "64" : "U10-x86_64-cfntools" },
"RHEL-6.1" : { "32" : "rhel61-i386-cfntools", "64" : "rhel61-x86_64-cfntools" },
"RHEL-6.2" : { "32" : "rhel62-i386-cfntools", "64" : "rhel62-x86_64-cfntools" },
"RHEL-6.3" : { "32" : "rhel63-i386-cfntools", "64" : "rhel63-x86_64-cfntools" }
}
},
"Resources" : {
"DatabaseServer": {
"Type": "AWS::RDS::DBInstance",
"Properties": {
"DBName" : { "Ref" : "DBName" },
"Engine" : "MySQL",
"MasterUsername" : { "Ref" : "DBUsername" },
"DBInstanceClass" : { "Ref" : "DBClass" },
"DBSecurityGroups" : [],
"AllocatedStorage" : { "Ref" : "DBAllocatedStorage" },
"MasterUserPassword": { "Ref" : "DBPassword" }
}
},
"WebServer": {
"Type": "AWS::EC2::Instance",
"DependsOn": "DatabaseServer",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"config" : {
"packages" : {
"yum" : {
"httpd" : [],
"wordpress" : []
}
},
"services" : {
"systemd" : {
"httpd" : { "enabled" : "true", "ensureRunning" : "true" }
}
}
}
}
},
"Properties": {
"ImageId" : { "Fn::FindInMap" : [ "DistroArch2AMI", { "Ref" : "LinuxDistribution" },
{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
"InstanceType" : { "Ref" : "InstanceType" },
"KeyName" : { "Ref" : "KeyName" },
"UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -v\n",
"/opt/aws/bin/cfn-init\n",
"sed --in-place --e s/database_name_here/", { "Ref" : "DBName" }, "/ --e s/username_here/", { "Ref" : "DBUsername" }, "/ --e s/password_here/", { "Ref" : "DBPassword" }, "/ --e s/localhost/", { "Fn::GetAtt" : [ "DatabaseServer", "Endpoint.Address" ]}, "/ /usr/share/wordpress/wp-config.php\n"
]]}}
}
}
},
"Outputs" : {
"WebsiteURL" : {
"Value" : { "Fn::Join" : ["", ["http://", { "Fn::GetAtt" : [ "WebServer", "PublicIp" ]}, "/wordpress"]] },
"Description" : "URL for Wordpress wiki"
}
}
}