HeatTemplateFormatVersion: '2012-12-12'
Description: MonboDB Config Server
Mappings:
  AWSInstanceType2Arch:
    m1.large: {Arch: '64'}
    m1.medium: {Arch: '64'}
    m1.small: {Arch: '64'}
    m1.tiny: {Arch: '64'}
    m1.xlarge: {Arch: '64'}
    k1.tiny: {Arch: '64'}
  DistroArch2AMI:
    F17: {'32': F17-i386-cfntools, '64': F17-x86_64-cfntools}
    F18: {'32': F18-i386-cfntools, '64': F18-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}
    SL6: {'32': NOT IMPLEMENTED, '64': sl6-msc-image}
    U10: {'32': U10-i386-cfntools, '64': U10-x86_64-cfntools}
Outputs:
  ConfigSvrName:
    Description: public DNS name of the MongoDB Config Server Instance
    Value:
      Fn::Select:
      - ip_address
      - Fn::Select:
        - '0'
        - Fn::GetAtt: [BackendInterface, fixed_ips]
Parameters:
  ClusterName:
    Description: Cluster Name
    Type: String
  SvrId:
    Description: Server ID
    Type: String
  MongoDBYumRepo: {Description: Mongo DB Yum Repo,
    Default: 'http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/',
    Type: String}
  PrimarySecurityGroup: {Description: Primary Security
      Group, Type: String}
  BackendSecurityGroup: {Description: Backend Security
      Group, Type: String}
  BackendIpAddress: {Description: BackendIpAddress,
    Type: String}
  BackendNetworkId: {Description: BackendNetworkId,
    Type: String}
  BackendSubnetId: {Description: BackendSubnetId,
    Type: String}
  ExtraUserData: {Default: '', Description: Extra
      UserData script, Type: String}
  InstanceType:
    AllowedValues: [m1.tiny, m1.small, m1.large, m1.xlarge, m2.xlarge,
      m2.2xlarge, m2.4xlarge, c1.xlarge, cc1.4xlarge, k1.tiny]
    Default: m1.tiny
    Description: EC2 instance type (e.g. m1.large, m1.xlarge, m2.xlarge)
    Type: String
  InstanceZone: {Description: AvailabilityZone for
      this instance, Type: String}
  KeyName: {Description: Name of an existing EC2 KeyPair
      to enable SSH access, Type: String}
  LinuxDistribution:
    AllowedValues: [SL6, F18, F17, U10, RHEL-6.1, RHEL-6.2, RHEL-6.3]
    Default: SL6
    Description: Distribution of choice
    Type: String
  PrimaryNetworkId: {Description: PrimaryNetworkId,
    Type: String}
  StartupTimeout: {Default: '1700', Description: How
      long to wait on node coming up, Type: Number}
  VolumeSize: {Default: '2', Description: Volume
      size for each EBS volume, Type: Number}
  SchedulerGroup: {Default: '', Description: The
      scheduler hints for the node, Type: String}
Resources:
  PrimaryInterface:
    Properties:
      name:
        Fn::Join:
          - ''
          - - {Ref: ClusterName}
            - '-Config'
            - {Ref: SvrId}
            - '-PrimaryPort'
      network_id: {Ref: PrimaryNetworkId}
      security_groups:
      - {Ref: PrimarySecurityGroup}
    Type: OS::Neutron::Port
  BackendInterface:
    Properties:
      name:
        Fn::Join:
          - ''
          - - {Ref: ClusterName}
            - '-Config'
            - {Ref: SvrId}
            - '-BackendPort'
      fixed_ips:
      - ip_address: {Ref: BackendIpAddress}
        subnet_id: {Ref: BackendSubnetId}
      network_id: {Ref: BackendNetworkId}
      security_groups:
      - {Ref: BackendSecurityGroup}
    Type: OS::Neutron::Port
  ConfigServer:
    Metadata:
      AWS::CloudFormation::Init:
        config:
          files:
            /etc/yum.repos.d/10gen.repo:
              content:
                Fn::Join:
                - ''
                - - "[10gen]\n"
                  - "name=10gen Repository\n"
                  - "baseurl="
                  - {Ref: MongoDBYumRepo}
                  - "\n"
                  - "gpgcheck=0\n"
              group: root
              mode: '000644'
              owner: root
          packages:
            yum:
              mdadm: []
              sysstat: []
    Properties:
      name:
        Fn::Join:
          - ''
          - - {Ref: ClusterName}
            - '-Config'
            - {Ref: SvrId}
      availability_zone: {Ref: InstanceZone}
      scheduler_hints: {'group': {Ref: SchedulerGroup} }
      image:
        Fn::FindInMap:
        - DistroArch2AMI
        - {Ref: LinuxDistribution}
        - Fn::FindInMap:
          - AWSInstanceType2Arch
          - {Ref: InstanceType}
          - Arch
      flavor: {Ref: InstanceType}
      key_name: {Ref: KeyName}
      networks:
        - {port: {Ref: PrimaryInterface}}
        - {port: {Ref: BackendInterface}}
      user_data:
        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: WaitHandleConfigSvr}
            - "'\n"
            - "   exit 1\n"
            - "}\n"
            - "function trap_error\n"
            - "{\n"
            - "	error_exit \"Line: ${BASH_LINENO[0]}, ExitCode: $1\"\n"
            - "}\n"
            - "set -eu\n"
            - "trap 'trap_error \"$?\"' ERR\n"
            - "## Initialize CloudFormation bits\n"
            - "/opt/aws/bin/cfn-init -s "
            - {Ref: "AWS::StackName"}
            - " -r Instance --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/vdb ]; do echo waiting for /dev/vdb to attach; sleep 10; done\n"
            - "while [ ! -e /dev/vdc ]; do echo waiting for /dev/vdc to attach; sleep 10; done\n"
            - "yum -y install mongo-10gen-server mongo-10gen xfsprogs > /tmp/yum-mongo.log 2>&1\n"
            - "(echo mklabel msdos; echo mkpart primary xfs 0 -1; echo set 1 raid "
            - "on; echo print; echo quit) | parted -a optimal /dev/vdb\n"
            - "(echo mklabel msdos; echo mkpart primary xfs 0 -1; echo set 1 raid "
            - "on; echo print; echo quit) | parted -a optimal /dev/vdc\n"
            - "## Create RAID10 and persist configuration\n"
            - "yes | mdadm --verbose --create /dev/md0 --level=1 --raid-devices=2 "
            - "/dev/vdb1 /dev/vdc1 > /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/vdb\n"
            - "blockdev --setra 128 /dev/vdc\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 40%vg -n data vg0\n"
            - "lvcreate -l 20%vg -n log vg0\n"
            - "lvcreate -l 40%vg -n journal vg0\n"
            - "## Create filesystems and mount point info\n"
            - "mkfs.xfs -f /dev/vg0/data > /tmp/mke2fs1.log 2>&1 &\n"
            - "mkfs.xfs -f /dev/vg0/log > /tmp/mke2fs2.log 2>&1 &\n"
            - "mkfs.xfs -f /dev/vg0/journal > /tmp/mke2fs3.log 2>&1 &\n"
            - "mkdir /data\n"
            - "mkdir /log\n"
            - "mkdir /journal\n"
            - "echo '/dev/vg0/data /data xfs defaults,auto,noatime,noexec 0 0'"
            - " | tee -a /etc/fstab\n"
            - "echo '/dev/vg0/log /log xfs defaults,auto,noatime,noexec 0 0'"
            - " | tee -a /etc/fstab\n"
            - "echo '/dev/vg0/journal /journal xfs defaults,auto,noatime,noexec "
            - "0 0' | tee -a /etc/fstab\n"
            - "wait\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"
            - "cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth1\n"
            - "sed -i 's/eth0/eth1/' /etc/sysconfig/network-scripts/ifcfg-eth1\n"
            - "echo PEERDNS=no >> /etc/sysconfig/network-scripts/ifcfg-eth1\n"
            - "ifup eth1\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"
            - "configsvr=true\n"
            - "EOF\n"
            - "## Start mongod\n"
            - "/etc/init.d/mongod start > /tmp/mongod-start.log 2>&1\n"
            - "## Extra userdata\n"
            - {Ref: ExtraUserData}
            - "\n"
            - "## CloudFormation signal that setup is complete\n"
            - "/opt/aws/bin/cfn-signal -e 0 -r \"ConfigServer setup complete\" '"
            - {Ref: WaitHandleConfigSvr}
            - "'\n"
    Type: OS::Nova::Server
  MongoVolume1:
    Properties:
      name:
        Fn::Join:
          - ''
          - - {Ref: ClusterName}
            - '-Config'
            - {Ref: SvrId}
            - '-D1'
      availability_zone: {Ref: InstanceZone}
      size: {Ref: VolumeSize}
    Type: OS::Cinder::Volume
  MongoVolume2:
    Properties:
      name:
        Fn::Join:
          - ''
          - - {Ref: ClusterName}
            - '-Config'
            - {Ref: SvrId}
            - '-D2'
      availability_zone: {Ref: InstanceZone}
      size: {Ref: VolumeSize}
    Type: OS::Cinder::Volume
  MongoVolumeMount1:
    Properties:
      Device: /dev/vdb
      InstanceId: {Ref: ConfigServer}
      VolumeId: {Ref: MongoVolume1}
    Type: AWS::EC2::VolumeAttachment
  MongoVolumeMount2:
    Properties:
      Device: /dev/vdc
      InstanceId: {Ref: ConfigServer}
      VolumeId: {Ref: MongoVolume2}
    Type: AWS::EC2::VolumeAttachment
  WaitConditionConfigSvr:
    DependsOn: ConfigServer
    Properties:
      Handle: {Ref: WaitHandleConfigSvr}
      Timeout: {Ref: StartupTimeout}
    Type: AWS::CloudFormation::WaitCondition
  WaitHandleConfigSvr:
    Properties: {}
    Type: AWS::CloudFormation::WaitConditionHandle