{
    "AWSTemplateFormatVersion" : "2010-09-09",

    "Description" : "MongoDB Server deployment with a RAID10 storage configuration with 8 EBS volumes",

    "Parameters" : {
        "KeyName" : {
            "Description" : "Name of an existing EC2 KeyPair to enable SSH access",
            "Type" : "String" 
        },

        "InstanceType" : {
            "Type" : "String", 
            "Default" : "m1.large", 
            "AllowedValues" : [ "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "c1.xlarge", "cc1.4xlarge" ],
            "Description" : "EC2 instance type (e.g. m1.large, m1.xlarge, m2.xlarge)"
        },

        "VolumeSize" : {
            "Description" : "Volume size for each EBS volume",
            "Type" : "Number",
            "Default" : "10"
        },
        
        "ReplicaSetName" : {
            "Description" : "Name for the MongoDB replica set",
            "Type" : "String",
            "Default" : "MyReplicaSet"
        },
        
        "AccessKeyId" : {
            "Description" : "Access Key ID",
            "Type" : "String"
        },

        "SecretAccessKey" : {
            "Description" : "Secret Access Key for the specified Access Key ID",
            "Type" : "String"
        },

        "SecurityGroupName" : {
            "Description" : "MongoDB replica set security group name",
            "Type" : "String"
        }
    },

    "Mappings" : {
        "InstanceTypeArch" : {
        	"t1.micro"    : { "Arch" : "64" },
            "m1.small"    : { "Arch" : "64" },
            "m1.medium"   : { "Arch" : "64" },
            "m1.large"    : { "Arch" : "64" },
            "m1.xlarge"   : { "Arch" : "64" },
            "m2.xlarge"   : { "Arch" : "64" },
            "m2.2xlarge"  : { "Arch" : "64" },
            "m2.4xlarge"  : { "Arch" : "64" },
            "c1.medium"   : { "Arch" : "64" },
            "c1.xlarge"   : { "Arch" : "64" },
            "cc1.4xlarge" : { "Arch" : "64HVM" }
        },

        "RegionImageZone" : {
            "us-east-1"      : { "64" : "ami-e565ba8c", "64HVM" : "ami-e965ba80" },
            "us-west-2"      : { "64" : "ami-3ac64a0a", "64HVM" : "NOT_YET_SUPPORTED" },
            "us-west-1"      : { "64" : "ami-e78cd4a2", "64HVM" : "NOT_YET_SUPPORTED" },
            "eu-west-1"      : { "64" : "ami-f9231b8d", "64HVM" : "NOT_YET_SUPPORTED" },
            "ap-southeast-1" : { "64" : "ami-be3374ec", "64HVM" : "NOT_YET_SUPPORTED" },
            "ap-northeast-1" : { "64" : "ami-e47acbe5", "64HVM" : "NOT_YET_SUPPORTED" },
            "sa-east-1"      : { "64" : "ami-a6855bbb", "64HVM" : "NOT_YET_SUPPORTED" }
        }
    },

    "Resources" : {

        "MongoSecondary" : {
            "Type" : "AWS::EC2::Instance",
            "Metadata" : {
                "AWS::CloudFormation::Init" : {
                    "config" : {
                        "packages" : {
                            "yum" : {
                                "mdadm" : [],
                                "sysstat" : []
                            }
                        },
                        "files" : {
                            "/etc/yum.repos.d/10gen.repo" : {
                                "content" : { "Fn::Join" : ["", [
                                    "[10gen]\n",
                                    "name=10gen Repository\n",
                                    "baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64\n",
                                    "gpgcheck=0\n"
                                ] ] },
                                "mode" : "000644",
                                "owner" : "root",
                                "group" : "root"
                            }
                        }
                    }
                }
            },

            "Properties" : {
                "InstanceType" : { "Ref" : "InstanceType" },
                "ImageId" : { "Fn::FindInMap" : [ "RegionImageZone", { "Ref" : "AWS::Region" }, 
                    { "Fn::FindInMap" : [ "InstanceTypeArch", { "Ref" : "InstanceType" }, "Arch" ] } ] },
                "SecurityGroups" : [ { "Ref" : "SecurityGroupName" } ],
                "KeyName" : { "Ref" : "KeyName" },
                "Tags" : [
          			{"Key" : "Name", "Value" : "MongoSecondary" },
          			{"Key" : "Owner", "Value" : "IntegratingStuff" }
        		],
                "UserData" : { "Fn::Base64" : { "Fn::Join" : ["", [
                    "#!/bin/bash\n",
                    "yum update -y aws-cfn-bootstrap\n",

                    "## Error reporting helper function\n",
                    "function error_exit\n",
                    "{\n",
                    "   /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '", { "Ref" : "WaitHandleMongoSecondary" }, "'\n",
                    "   exit 1\n",
                    "}\n",

                    "## Initialize CloudFormation bits\n",
                    "/opt/aws/bin/cfn-init -v -s ", { "Ref" : "AWS::StackName" }, " -r MongoSecondary",
                    "   --access-key ",  { "Ref" : "AccessKeyId" },
                    "   --secret-key ", {"Ref": "SecretAccessKey" },
                    "   --region ", { "Ref" : "AWS::Region" }, " > /tmp/cfn-init.log 2>&1 || error_exit $(</tmp/cfn-init.log)\n",

                    "## Waiting for EBS mounts to become available\n",
                    "while [ ! -e /dev/sdh1 ]; do echo waiting for /dev/sdh1 to attach; sleep 10; done\n",
                    "while [ ! -e /dev/sdh2 ]; do echo waiting for /dev/sdh2 to attach; sleep 10; done\n",
                    "while [ ! -e /dev/sdh3 ]; do echo waiting for /dev/sdh3 to attach; sleep 10; done\n",
                    "while [ ! -e /dev/sdh4 ]; do echo waiting for /dev/sdh4 to attach; sleep 10; done\n",
                    "while [ ! -e /dev/sdh5 ]; do echo waiting for /dev/sdh5 to attach; sleep 10; done\n",
                    "while [ ! -e /dev/sdh6 ]; do echo waiting for /dev/sdh6 to attach; sleep 10; done\n",
                    "while [ ! -e /dev/sdh7 ]; do echo waiting for /dev/sdh7 to attach; sleep 10; done\n",
                    "while [ ! -e /dev/sdh8 ]; do echo waiting for /dev/sdh8 to attach; sleep 10; done\n",

                    "yum -y install mongo-10gen-server > /tmp/yum-mongo.log 2>&1\n",

                    "## Create RAID10 and persist configuration\n",
                    "mdadm --verbose --create /dev/md0 --level=10 --chunk=256 --raid-devices=8 /dev/sdh1 /dev/sdh2 /dev/sdh3 /dev/sdh4 /dev/sdh5 /dev/sdh6 /dev/sdh7 /dev/sdh8 > /tmp/mdadm.log 2>&1\n",
                    "echo '`mdadm --detail --scan`' | tee -a /etc/mdadm.conf\n",

                    "## Set read-ahead on each device\n",
                    "blockdev --setra 128 /dev/md0\n",
                    "blockdev --setra 128 /dev/sdh1\n",
                    "blockdev --setra 128 /dev/sdh2\n",
                    "blockdev --setra 128 /dev/sdh3\n",
                    "blockdev --setra 128 /dev/sdh4\n",
                    "blockdev --setra 128 /dev/sdh5\n",
                    "blockdev --setra 128 /dev/sdh6\n",
                    "blockdev --setra 128 /dev/sdh7\n",
                    "blockdev --setra 128 /dev/sdh8\n",

                    "## Create physical and logical volumes\n",
                    "dd if=/dev/zero of=/dev/md0 bs=512 count=1\n",
                    "pvcreate /dev/md0\n",
                    "vgcreate vg0 /dev/md0\n",
                    "lvcreate -l 90%vg -n data vg0\n",
                    "lvcreate -l 5%vg -n log vg0\n",
                    "lvcreate -l 5%vg -n journal vg0\n",

                    "## Create filesystems and mount point info\n",
                    "mke2fs -t ext4 -F /dev/vg0/data > /tmp/mke2fs1.log 2>&1\n",
                    "mke2fs -t ext4 -F /dev/vg0/log > /tmp/mke2fs2.log 2>&1\n",
                    "mke2fs -t ext4 -F /dev/vg0/journal > /tmp/mke2fs3.log 2>&1\n",

                    "mkdir /data\n",
                    "mkdir /log\n",
                    "mkdir /journal\n",

                    "echo '/dev/vg0/data /data ext4 defaults,auto,noatime,nodiratime,noexec 0 0' | tee -a /etc/fstab\n",
                    "echo '/dev/vg0/log /log ext4 defaults,auto,noatime,nodiratime,noexec 0 0' | tee -a /etc/fstab\n",
                    "echo '/dev/vg0/journal /journal ext4 defaults,auto,noatime,nodiratime,noexec 0 0' | tee -a /etc/fstab\n",
                    
                    "## Raise file descriptor limits\n",
                    "echo '* hard nofile 100000' | tee -a /etc/security/limits.conf\n",
                    "echo '* soft nofile 100000' | tee -a /etc/security/limits.conf\n",
                    
                    "ulimit -n 100000\n",
                    
                    "mount /data > /tmp/mount1.log 2>&1\n",
                    "mount /log > /tmp/mount2.log 2>&1\n",
                    "mount /journal > /tmp/mount3.log 2>&1\n",

                    "ln -s /journal /data/journal\n",

                    "chown -R mongod:mongod /data > /tmp/chown1.log 2>&1\n",
                    "chown -R mongod:mongod /log > /tmp/chown2.log 2>&1\n",
                    "chown -R mongod:mongod /journal > /tmp/chown3.log 2>&1\n",

                    "## Update mongod configuration\n",
                    "cat <<EOF > /etc/mongod.conf\n",
                    "logpath=/log/mongod.log\n",
                    "logappend=true\n",
                    "fork=true\n",
                    "dbpath=/data\n",
                    "rest=true\n",
                    "replSet=", { "Ref" : "ReplicaSetName" } ,"\n",
                    "EOF\n",

                    "## Start mongod\n",
                    "/etc/init.d/mongod start > /tmp/mongod-start.log 2>&1\n",

                    "## CloudFormation signal that setup is complete\n",
                    "/opt/aws/bin/cfn-signal -e 0 -r \"MongoSecondary setup complete\" '", { "Ref" : "WaitHandleMongoSecondary" }, "'\n"
                ] ] } }
            }
        },

        "MongoSecondaryVolume1" : {
            "Type" : "AWS::EC2::Volume",
            "Properties" : {
                "Size" : { "Ref" : "VolumeSize" },
                "AvailabilityZone" : { "Fn::GetAtt" : [ "MongoSecondary", "AvailabilityZone" ]}
            }
        },

        "MongoSecondaryVolume2" : {
            "Type" : "AWS::EC2::Volume",
            "Properties" : {
                "Size" : { "Ref" : "VolumeSize" },
                "AvailabilityZone" : { "Fn::GetAtt" : [ "MongoSecondary", "AvailabilityZone" ]}
            }
        },

        "MongoSecondaryVolume3" : {
            "Type" : "AWS::EC2::Volume",
            "Properties" : {
                "Size" : { "Ref" : "VolumeSize" },
                "AvailabilityZone" : { "Fn::GetAtt" : [ "MongoSecondary", "AvailabilityZone" ]}
            }
        },

        "MongoSecondaryVolume4" : {
            "Type" : "AWS::EC2::Volume",
            "Properties" : {
                "Size" : { "Ref" : "VolumeSize" },
                "AvailabilityZone" : { "Fn::GetAtt" : [ "MongoSecondary", "AvailabilityZone" ]}
            }
        },
        
        "MongoSecondaryVolume5" : {
            "Type" : "AWS::EC2::Volume",
            "Properties" : {
                "Size" : { "Ref" : "VolumeSize" },
                "AvailabilityZone" : { "Fn::GetAtt" : [ "MongoSecondary", "AvailabilityZone" ]}
            }
        },

        "MongoSecondaryVolume6" : {
            "Type" : "AWS::EC2::Volume",
            "Properties" : {
                "Size" : { "Ref" : "VolumeSize" },
                "AvailabilityZone" : { "Fn::GetAtt" : [ "MongoSecondary", "AvailabilityZone" ]}
            }
        },

        "MongoSecondaryVolume7" : {
            "Type" : "AWS::EC2::Volume",
            "Properties" : {
                "Size" : { "Ref" : "VolumeSize" },
                "AvailabilityZone" : { "Fn::GetAtt" : [ "MongoSecondary", "AvailabilityZone" ]}
            }
        },

        "MongoSecondaryVolume8" : {
            "Type" : "AWS::EC2::Volume",
            "Properties" : {
                "Size" : { "Ref" : "VolumeSize" },
                "AvailabilityZone" : { "Fn::GetAtt" : [ "MongoSecondary", "AvailabilityZone" ]}
            }
        },

        "MongoSecondaryVolumeMount1" : {
            "Type" : "AWS::EC2::VolumeAttachment",
            "Properties" : {
                "InstanceId" : { "Ref" : "MongoSecondary" },
                "VolumeId" : { "Ref" : "MongoSecondaryVolume1" },
                "Device" : "/dev/sdh1"
            }
        },

        "MongoSecondaryVolumeMount2" : {
            "Type" : "AWS::EC2::VolumeAttachment",
            "Properties" : {
                "InstanceId" : { "Ref" : "MongoSecondary" },
                "VolumeId" : { "Ref" : "MongoSecondaryVolume2" },
                "Device" : "/dev/sdh2"
            }
        },

        "MongoSecondaryVolumeMount3" : {
            "Type" : "AWS::EC2::VolumeAttachment",
            "Properties" : {
                "InstanceId" : { "Ref" : "MongoSecondary" },
                "VolumeId" : { "Ref" : "MongoSecondaryVolume3" },
                "Device" : "/dev/sdh3"
            }
        },

        "MongoSecondaryVolumeMount4" : {
            "Type" : "AWS::EC2::VolumeAttachment",
            "Properties" : {
                "InstanceId" : { "Ref" : "MongoSecondary" },
                "VolumeId" : { "Ref" : "MongoSecondaryVolume4" },
                "Device" : "/dev/sdh4"
            }
        },
        
        "MongoSecondaryVolumeMount5" : {
            "Type" : "AWS::EC2::VolumeAttachment",
            "Properties" : {
                "InstanceId" : { "Ref" : "MongoSecondary" },
                "VolumeId" : { "Ref" : "MongoSecondaryVolume5" },
                "Device" : "/dev/sdh5"
            }
        },

        "MongoSecondaryVolumeMount6" : {
            "Type" : "AWS::EC2::VolumeAttachment",
            "Properties" : {
                "InstanceId" : { "Ref" : "MongoSecondary" },
                "VolumeId" : { "Ref" : "MongoSecondaryVolume6" },
                "Device" : "/dev/sdh6"
            }
        },

        "MongoSecondaryVolumeMount7" : {
            "Type" : "AWS::EC2::VolumeAttachment",
            "Properties" : {
                "InstanceId" : { "Ref" : "MongoSecondary" },
                "VolumeId" : { "Ref" : "MongoSecondaryVolume7" },
                "Device" : "/dev/sdh7"
            }
        },

        "MongoSecondaryVolumeMount8" : {
            "Type" : "AWS::EC2::VolumeAttachment",
            "Properties" : {
                "InstanceId" : { "Ref" : "MongoSecondary" },
                "VolumeId" : { "Ref" : "MongoSecondaryVolume8" },
                "Device" : "/dev/sdh8"
            }
        },

        "WaitHandleMongoSecondary" : {
            "Type" : "AWS::CloudFormation::WaitConditionHandle",
            "Properties" : {}
        },

        "WaitConditionMongoSecondary" : {
            "Type" : "AWS::CloudFormation::WaitCondition",
            "DependsOn" : "MongoSecondary",
            "Properties" : {
                "Handle" : { "Ref" : "WaitHandleMongoSecondary" },
                "Timeout" : "300"
            }
        }
    },

    "Outputs" : {
        "InstanceName" : {
            "Value" : { "Fn::GetAtt" : [ "MongoSecondary", "PublicDnsName" ] },
            "Description" : "public DNS name of the new MongoSecondary"
        }
    }
}