HeatTemplateFormatVersion: '2012-12-12' Description: "Setup a multi-node OpenStack installation using DevStack. By default, it will start one controller node and one compute node. To start the services, login to each node and run: cd /opt/devstack && ./stack.sh Tested on Ubuntu and may work as-is on Debian too. Note also that the security group resources require to use Neutron and Havana Heat." Parameters: KeyName: Description: Name of an existing KeyPair to enable SSH access to the instances Type: String ComputeNodes: Default: '1' Description: Number of compute nodes Type: String AllowedPattern: '[0-9]*' ControllerFlavor: Description: Instance flavor of the Controller node Type: String Default: m1.medium AllowedValues: [m1.tiny, m1.small, m1.medium, m1.large, m1.xlarge] ConstraintDescription: must be a valid instance type. ComputeFlavor: Description: Instance flavor of the Compute node(s) Type: String Default: m1.small AllowedValues: [m1.tiny, m1.small, m1.medium, m1.large, m1.xlarge] ConstraintDescription: must be a valid instance type. LinuxDistribution: Default: precise Description: Distribution of choice Type: String AllowedValues: [precise, quantal, raring, saucy] AdminPassword: Default: password Description: Password for the OpenStack admin user Type: String Virtualization: Default: kvm Description: Virtualization technology Type: String AllowedValues: [kvm, lxc] Mappings: AWSInstanceType2Arch: m1.tiny: {Arch: '32'} m1.small: {Arch: '32'} m1.medium: {Arch: '64'} m1.large: {Arch: '64'} m1.xlarge: {Arch: '64'} DistroArch2AMI: precise: {'32': precise-server-cloudimg-i386, '64': precise-server-cloudimg-amd64} quantal: {'32': quantal-server-cloudimg-i386, '64': quantal-server-cloudimg-amd64} raring: {'32': raring-server-cloudimg-i386, '64': raring-server-cloudimg-amd64} saucy: {'32': saucy-server-cloudimg-i386, '64': saucy-server-cloudimg-amd64} Resources: IPAddress: {Type: 'AWS::EC2::EIP'} IPAssoc: Type: AWS::EC2::EIPAssociation Properties: InstanceId: {Ref: OsController} EIP: {Ref: IPAddress} CfnUser: Type: AWS::IAM::User CfnUserKey: Type: AWS::IAM::AccessKey Properties: UserName: {Ref: CfnUser} OsControllerWaitHandle: Type: AWS::CloudFormation::WaitConditionHandle OsControllerWaitCondition: Type: AWS::CloudFormation::WaitCondition DependsOn: OsController Properties: Handle: {Ref: OsControllerWaitHandle} Count: '1' Timeout: '600' OsComputeSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable SSH access VpcId: abcd SecurityGroupIngress: - {CidrIp: 0.0.0.0/0, FromPort: '-1', IpProtocol: icmp, ToPort: '-1'} - {CidrIp: 0.0.0.0/0, FromPort: '22', IpProtocol: tcp, ToPort: '22'} OsControllerSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable HTTP access via port 80 plus SSH access VpcId: abcd SecurityGroupIngress: - {CidrIp: 0.0.0.0/0, FromPort: '-1', IpProtocol: icmp, ToPort: '-1'} - {CidrIp: 0.0.0.0/0, FromPort: '80', IpProtocol: tcp, ToPort: '80'} - {CidrIp: 0.0.0.0/0, FromPort: '22', IpProtocol: tcp, ToPort: '22'} OsDefaultSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable all traffic between controller & compute nodes VpcId: neutron SecurityGroupIngress: - {SourceSecurityGroupId: {Ref: OsControllerSecurityGroup}} - {SourceSecurityGroupId: {Ref: OsComputeSecurityGroup}} OsComputeGroup: Type: OS::Heat::InstanceGroup Properties: LaunchConfigurationName: {Ref: OsComputeConfig} Size: {Ref: ComputeNodes} AvailabilityZones: {'Fn::GetAZs': ''} OsComputeConfig: Type: AWS::AutoScaling::LaunchConfiguration Metadata: AWS::CloudFormation::Init: config: packages: {} services: {} files: # Create a YAML reference that will be used by other resources (eg OsController) /etc/cfn/cfn-credentials: &cfn-credentials-file content: Fn::Join: - '' - - AWSAccessKeyId= - {Ref: CfnUserKey} - ' ' - AWSSecretKey= - 'Fn::GetAtt': [CfnUserKey, SecretAccessKey] - ' ' mode: "00400" owner: root group: root Properties: ImageId: Fn::FindInMap: - DistroArch2AMI - {Ref: LinuxDistribution} - Fn::FindInMap: - AWSInstanceType2Arch - {Ref: ComputeFlavor} - Arch InstanceType: {Ref: ComputeFlavor} KeyName: {Ref: KeyName} SecurityGroups: - {Ref: OsComputeSecurityGroup} - {Ref: OsDefaultSecurityGroup} UserData: Fn::Base64: Fn::Join: - '' - - '#!/bin/bash -ve ' - 'cd /opt ' - 'apt-get update; apt-get install -y git python-setuptools; ' - '# Install heat cfn tools ' - 'apt-get -y install python-argparse cloud-init python-psutil python-pip python-dev ' - 'apt-get -y remove python-boto ' - 'pip install ''boto==2.5.2'' heat-cfntools ' - 'cfn-create-aws-symlinks -s /usr/local/bin/ ' - '/opt/aws/bin/cfn-init ' - '# Download DevStack from Github ' - 'git clone https://github.com/openstack-dev/devstack.git ' - 'cd devstack ' - '# Boostrap localrc' - ' ' - 'MY_IPV4=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4/) ' - cat << EOF >> localrc - ' ' - ADMIN_PASSWORD= - {Ref: AdminPassword} - ' ' - 'MYSQL_PASSWORD=password RABBIT_PASSWORD=password SERVICE_PASSWORD=password SERVICE_TOKEN=tokentoken ' - 'LOGFILE=/opt/stack/data/stack.log ' - 'ENABLED_SERVICES=n-cpu,rabbit,neutron,q-agt,q-dhcp ' - LIBVIRT_TYPE= - {Ref: Virtualization} - ' ' - 'HOST_IP=$MY_IPV4 ' - SERVICE_HOST= - Fn::GetAtt: [OsController, PrivateIp] - ' ' - 'ENABLE_TENANT_TUNNELS=True Q_AGENT_EXTRA_AGENT_OPTS=(tunnel_type=gre) Q_DHCP_EXTRA_DHCP_OPTS=(dhcp_agents_per_network=' - {Ref: ComputeNodes} - ') Q_AGENT_EXTRA_OVS_OPTS=(tenant_network_type=gre) ' - 'Q_USE_NAMESPACE=True Q_USE_SECGROUP=True ' - 'MYSQL_HOST=\$SERVICE_HOST ' - 'RABBIT_HOST=\$SERVICE_HOST ' - 'Q_HOST=\$SERVICE_HOST ' - 'GLANCE_HOSTPORT=\$SERVICE_HOST:9292 ' - 'EOF ' - 'chown -R ec2-user:ec2-user /opt/devstack ' OsController: Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Init: config: packages: {} services: {} files: /etc/cfn/cfn-credentials: *cfn-credentials-file Properties: ImageId: Fn::FindInMap: - DistroArch2AMI - {Ref: LinuxDistribution} - Fn::FindInMap: - AWSInstanceType2Arch - {Ref: ControllerFlavor} - Arch InstanceType: {Ref: ControllerFlavor} KeyName: {Ref: KeyName} SecurityGroups: - {Ref: OsControllerSecurityGroup} - {Ref: OsDefaultSecurityGroup} UserData: Fn::Base64: Fn::Join: - '' - - '#!/bin/bash -ve ' - 'cd /opt ' - 'apt-get update; apt-get install -y git; ' - '# Install heat cfn tools ' - 'apt-get -y install python-argparse cloud-init python-psutil python-pip ' - 'apt-get -y remove python-boto ' - 'pip install ''boto==2.5.2'' heat-cfntools ' - 'cfn-create-aws-symlinks -s /usr/local/bin/ ' - '/opt/aws/bin/cfn-init --region ' - {Ref: 'AWS::Region'} - ' -s ' - {Ref: 'AWS::StackName'} - ' -r OsController --access-key ' - {Ref: CfnUserKey} - ' --secret-key ' - 'Fn::GetAtt': [CfnUserKey, SecretAccessKey] - ' ' - '# Download DevStack from Github' - ' ' - 'git clone https://github.com/openstack-dev/devstack.git ' - 'cd devstack ' - '# Boostrap localrc' - 'MY_IPV4=$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4/) ' - ' ' - cat << EOF >> localrc - ' ' - ADMIN_PASSWORD= - {Ref: AdminPassword} - ' ' - 'MYSQL_PASSWORD=password RABBIT_PASSWORD=password SERVICE_PASSWORD=password SERVICE_TOKEN=tokentoken ' - 'LOGFILE=/opt/stack/data/stack.log ' - 'HOST_IP=$MY_IPV4 ' - 'ENABLE_TENANT_TUNNELS=True Q_AGENT_EXTRA_AGENT_OPTS=(tunnel_type=gre) Q_AGENT_EXTRA_OVS_OPTS=(tenant_network_type=gre) Q_SRV_EXTRA_OPTS=(tenant_network_type=gre) ' - 'Q_USE_NAMESPACE=True Q_USE_SECGROUP=True ' - LIBVIRT_TYPE= - {Ref: Virtualization} - ' ' - 'disable_service n-net ' - 'disable_service n-cpu ' - 'enable_service q-svc ' - 'enable_service q-agt ' - 'enable_service q-l3 ' - 'enable_service q-meta ' - 'enable_service neutron ' - 'ENABLED_SERVICES+=,heat,h-api,h-api-cfn,h-api-cw,h-eng ' - 'EOF ' - 'chown -R ec2-user:ec2-user /opt/devstack ' - "/opt/aws/bin/cfn-signal -e 0 '" - {Ref: OsControllerWaitHandle} - "'" Outputs: Horizon URL: Value: Fn::Join: - '' - - http:// - {Ref: IPAddress} - / Description: URL for Horizon dashboard Horizon user: Value: admin Description: Username for Horizon dashboard Horizon password: Value: {Ref: AdminPassword} Description: Password for Horizon dashboard