AWSTemplateFormatVersion: "2010-09-09" # MIT License # # Copyright (c) 2021 Qumulo, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. Description: This template buiilds the Qumulo Cluster. It calls subordinate CloudFormation templates to instantiate the infrastructure. (qs-1t69a3rgc) Metadata: cfn-lint: config: ignore_checks: - W9002 - W9003 - W9004 - W9006 Parameters: BucketName: Type: String BucketRegion: Type: String KeyPrefix: Type: String KeyPair: Type: String VPCId: Type: String PrivateSubnetIDs: Type: CommaDelimitedList NumberAZs: Type: String QNodeCount: Type: String QDiskConfig: Type: String QFlashType: Type: String QAmiID: Type: String QFloatingIP: Type: String QClusterName: Type: String QInstanceType: Type: String VolumesEncryptionKey: Type: String QInstanceRecoveryTopic: Type: String QInstanceIAMProfile: Type: String QSgCidr1: Type: String RequireIMDSv2: Type: String Conditions: Provision5: !Or [!Equals [!Ref QNodeCount, "5"], Condition: Provision6] Provision6: !Or [!Equals [!Ref QNodeCount, "6"], Condition: Provision7] Provision7: !Or [!Equals [!Ref QNodeCount, "7"], Condition: Provision8] Provision8: !Or [!Equals [!Ref QNodeCount, "8"], Condition: Provision9] Provision9: !Or [!Equals [!Ref QNodeCount, "9"], Condition: Provision10] Provision10: !Or [!Equals [!Ref QNodeCount, "10"], Condition: Provision11] Provision11: !Or [!Equals [!Ref QNodeCount, "11"], Condition: Provision12] Provision12: !Or [!Equals [!Ref QNodeCount, "12"], Condition: Provision13] Provision13: !Or [!Equals [!Ref QNodeCount, "13"], Condition: Provision14] Provision14: !Or [!Equals [!Ref QNodeCount, "14"], Condition: Provision15] Provision15: !Or [!Equals [!Ref QNodeCount, "15"], Condition: Provision16] Provision16: !Or [!Equals [!Ref QNodeCount, "16"], Condition: Provision17] Provision17: !Or [!Equals [!Ref QNodeCount, "17"], Condition: Provision18] Provision18: !Or [!Equals [!Ref QNodeCount, "18"], Condition: Provision19] Provision19: !Or [!Equals [!Ref QNodeCount, "19"], Condition: Provision20] Provision20: !Or [!Equals [!Ref QNodeCount, "20"], Condition: Provision21] Provision21: !Or [!Equals [!Ref QNodeCount, "21"], Condition: Provision22] Provision22: !Or [!Equals [!Ref QNodeCount, "22"], Condition: Provision23] Provision23: !Or [!Equals [!Ref QNodeCount, "23"], Condition: Provision24] Provision24: !Equals [!Ref QNodeCount, "24"] ProvMultiAZ: !Not - !Equals - !Ref NumberAZs - "1" ProvFloatIP: !Not - !Equals - !Ref QFloatingIP - "0" StrictIMDSv2: !Equals - !Ref RequireIMDSv2 - "YES" Mappings: AZforNode: "1": "1": "0" "2": "0" "3": "0" "4": "0" "5": "0" "6": "0" "7": "0" "8": "0" "9": "0" "10": "0" "11": "0" "12": "0" "13": "0" "14": "0" "15": "0" "16": "0" "17": "0" "18": "0" "19": "0" "20": "0" "21": "0" "22": "0" "23": "0" "24": "0" # "3": # "1": "0" # "2": "1" # "3": "2" # "4": "0" # "5": "1" # "6": "2" # "7": "0" # "8": "1" # "9": "2" # "10": "0" # "11": "1" # "12": "2" # "13": "0" # "14": "1" # "15": "2" # "16": "0" # "17": "1" # "18": "2" # "19": "0" # "20": "1" # "21": "2" # "22": "0" # "23": "1" # "24": "2" "4": "1": "0" "2": "1" "3": "2" "4": "3" "5": "0" "6": "1" "7": "2" "8": "3" "9": "0" "10": "1" "11": "2" "12": "3" "13": "0" "14": "1" "15": "2" "16": "3" "17": "0" "18": "1" "19": "2" "20": "3" "21": "0" "22": "1" "23": "2" "24": "3" "5": "1": "0" "2": "1" "3": "2" "4": "3" "5": "4" "6": "0" "7": "1" "8": "2" "9": "3" "10": "4" "11": "0" "12": "1" "13": "2" "14": "3" "15": "4" "16": "0" "17": "1" "18": "2" "19": "3" "20": "4" "21": "0" "22": "1" "23": "2" "24": "3" # "6": # "1": "0" # "2": "1" # "3": "2" # "4": "3" # "5": "4" # "6": "5" # "7": "0" # "8": "1" # "9": "2" # "10": "3" # "11": "4" # "12": "5" # "13": "0" # "14": "1" # "15": "2" # "16": "3" # "17": "4" # "18": "5" # "19": "0" # "20": "1" # "21": "2" # "22": "3" # "23": "4" # "24": "5" Resources: QumuloSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable ports for NFS/SMB/FTP/SSH, Management, Replication, and Clustering. VpcId: !Ref VPCId SecurityGroupEgress: - CidrIp: 0.0.0.0/0 Description: Outbound traffic FromPort: 0 IpProtocol: "-1" ToPort: 0 SecurityGroupIngress: - CidrIp: !Ref QSgCidr1 Description: TCP ports for FTP FromPort: 21 IpProtocol: tcp ToPort: 21 - CidrIp: !Ref QSgCidr1 Description: TCP ports for SSH FromPort: 22 IpProtocol: tcp ToPort: 22 - CidrIp: !Ref QSgCidr1 Description: TCP ports for HTTP FromPort: 80 IpProtocol: tcp ToPort: 80 - CidrIp: !Ref QSgCidr1 Description: TCP ports for SUNRPC FromPort: 111 IpProtocol: tcp ToPort: 111 - CidrIp: !Ref QSgCidr1 Description: TCP ports for HTTPS FromPort: 443 IpProtocol: tcp ToPort: 443 - CidrIp: !Ref QSgCidr1 Description: TCP ports for SMB FromPort: 445 IpProtocol: tcp ToPort: 445 - CidrIp: !Ref QSgCidr1 Description: TCP ports for NFS FromPort: 2049 IpProtocol: tcp ToPort: 2049 - CidrIp: !Ref QSgCidr1 Description: TCP ports for Replication FromPort: 3712 IpProtocol: tcp ToPort: 3712 - CidrIp: !Ref QSgCidr1 Description: TCP ports for REST FromPort: 8000 IpProtocol: tcp ToPort: 8000 - CidrIp: !Ref QSgCidr1 Description: UDP port for SUNRPC FromPort: 111 IpProtocol: udp ToPort: 111 - CidrIp: !Ref QSgCidr1 Description: UDP port for NFS FromPort: 2049 IpProtocol: udp ToPort: 2049 - CidrIp: !Ref QSgCidr1 Description: TCP port for S3 FromPort: 9000 IpProtocol: TCP ToPort: 9000 QumuloSecurityGroupNodeRule: Type: AWS::EC2::SecurityGroupIngress Properties: Description: Qumulo Internode Communication FromPort: 0 GroupId: !Ref QumuloSecurityGroup IpProtocol: "-1" SourceSecurityGroupId: !Ref QumuloSecurityGroup ToPort: 0 QClusterGroup: Type: AWS::EC2::PlacementGroup Properties: Strategy: !If [ProvMultiAZ, spread, cluster] QClusterLaunchTemplate: Type: AWS::EC2::LaunchTemplate Properties: LaunchTemplateName: !Ref AWS::StackName LaunchTemplateData: MetadataOptions: HttpEndpoint: enabled HttpPutResponseHopLimit: 3 HttpTokens: !If [StrictIMDSv2, required, optional] NODESTACK1: Type: 'AWS::CloudFormation::Stack' Properties: Parameters: QNodeNumber: 1 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "1"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK2: Type: 'AWS::CloudFormation::Stack' Properties: Parameters: QNodeNumber: 2 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "2"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK3: Type: 'AWS::CloudFormation::Stack' Properties: Parameters: QNodeNumber: 3 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "3"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK4: Type: 'AWS::CloudFormation::Stack' Properties: Parameters: QNodeNumber: 4 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "4"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK5: Type: 'AWS::CloudFormation::Stack' Condition: Provision5 Properties: Parameters: QNodeNumber: 5 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "5"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK6: Type: 'AWS::CloudFormation::Stack' Condition: Provision6 Properties: Parameters: QNodeNumber: 6 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "6"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK7: Type: 'AWS::CloudFormation::Stack' Condition: Provision7 Properties: Parameters: QNodeNumber: 7 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "7"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK8: Type: 'AWS::CloudFormation::Stack' Condition: Provision8 Properties: Parameters: QNodeNumber: 8 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "8"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK9: Type: 'AWS::CloudFormation::Stack' Condition: Provision9 Properties: Parameters: QNodeNumber: 9 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "9"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK10: Type: 'AWS::CloudFormation::Stack' Condition: Provision10 Properties: Parameters: QNodeNumber: 10 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "10"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK11: Type: 'AWS::CloudFormation::Stack' Condition: Provision11 Properties: Parameters: QNodeNumber: 11 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "11"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK12: Type: 'AWS::CloudFormation::Stack' Condition: Provision12 Properties: Parameters: QNodeNumber: 12 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "12"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK13: Type: 'AWS::CloudFormation::Stack' Condition: Provision13 Properties: Parameters: QNodeNumber: 13 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "13"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK14: Type: 'AWS::CloudFormation::Stack' Condition: Provision14 Properties: Parameters: QNodeNumber: 14 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "14"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK15: Type: 'AWS::CloudFormation::Stack' Condition: Provision15 Properties: Parameters: QNodeNumber: 15 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "15"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK16: Type: 'AWS::CloudFormation::Stack' Condition: Provision16 Properties: Parameters: QNodeNumber: 16 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "16"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK17: Type: 'AWS::CloudFormation::Stack' Condition: Provision17 Properties: Parameters: QNodeNumber: 17 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "17"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK18: Type: 'AWS::CloudFormation::Stack' Condition: Provision18 Properties: Parameters: QNodeNumber: 18 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "18"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK19: Type: 'AWS::CloudFormation::Stack' Condition: Provision19 Properties: Parameters: QNodeNumber: 19 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "19"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK20: Type: 'AWS::CloudFormation::Stack' Condition: Provision20 Properties: Parameters: QNodeNumber: 20 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "20"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK21: Type: 'AWS::CloudFormation::Stack' Condition: Provision21 Properties: Parameters: QNodeNumber: 21 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "21"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK22: Type: 'AWS::CloudFormation::Stack' Condition: Provision22 Properties: Parameters: QNodeNumber: 22 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "22"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK23: Type: 'AWS::CloudFormation::Stack' Condition: Provision23 Properties: Parameters: QNodeNumber: 23 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "23"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 NODESTACK24: Type: 'AWS::CloudFormation::Stack' Condition: Provision24 Properties: Parameters: QNodeNumber: 24 QAmiID: !Ref QAmiID QClusterName: !Ref QClusterName QFloatingIP: !Ref QFloatingIP QInstanceIAMProfile: !Ref QInstanceIAMProfile QInstanceRecoveryTopic: !Ref QInstanceRecoveryTopic QInstanceType: !Ref QInstanceType KeyPair: !Ref KeyPair QSgId: !Ref QumuloSecurityGroup QClusterGroup: !Ref QClusterGroup QDiskConfig: !Ref QDiskConfig QFlashType: !Ref QFlashType SubnetId: !Select [!FindInMap [AZforNode, !Ref NumberAZs, "24"], !Ref PrivateSubnetIDs] VolumesEncryptionKey: !Ref VolumesEncryptionKey QStackName: !Ref AWS::StackName TemplateURL: !Sub "https://${BucketName}.s3.${BucketRegion}.${AWS::URLSuffix}/${KeyPrefix}templates/cfn/qnode.cft.yaml" TimeoutInMinutes: 150 Outputs: AWSStackID: Description: AWS ARN for this stack Value: !Ref AWS::StackId ClusterNodeNames: Description: List of name tags for the nodes in the cluster Value: !Join - ", " - - !GetAtt NODESTACK1.Outputs.NodeName - !GetAtt NODESTACK2.Outputs.NodeName - !GetAtt NODESTACK3.Outputs.NodeName - !GetAtt NODESTACK4.Outputs.NodeName - !If [Provision5, !GetAtt NODESTACK5.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision6, !GetAtt NODESTACK6.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision7, !GetAtt NODESTACK7.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision8, !GetAtt NODESTACK8.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision9, !GetAtt NODESTACK9.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision10, !GetAtt NODESTACK10.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision11, !GetAtt NODESTACK11.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision12, !GetAtt NODESTACK12.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision13, !GetAtt NODESTACK13.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision14, !GetAtt NODESTACK14.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision15, !GetAtt NODESTACK15.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision16, !GetAtt NODESTACK16.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision17, !GetAtt NODESTACK17.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision18, !GetAtt NODESTACK18.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision19, !GetAtt NODESTACK19.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision20, !GetAtt NODESTACK20.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision21, !GetAtt NODESTACK21.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision22, !GetAtt NODESTACK22.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision23, !GetAtt NODESTACK23.Outputs.NodeName, !Ref AWS::NoValue] - !If [Provision24, !GetAtt NODESTACK24.Outputs.NodeName, !Ref AWS::NoValue] AWSStackName: Description: AWS Name for this stack Value: !Ref AWS::StackName ClusterInstanceIDs: Description: List of the instance IDs of the nodes in your Qumulo Cluster Value: !Join - ", " - - !GetAtt NODESTACK1.Outputs.NodeInstanceID - !GetAtt NODESTACK2.Outputs.NodeInstanceID - !GetAtt NODESTACK3.Outputs.NodeInstanceID - !GetAtt NODESTACK4.Outputs.NodeInstanceID - !If [Provision5, !GetAtt NODESTACK5.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision6, !GetAtt NODESTACK6.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision7, !GetAtt NODESTACK7.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision8, !GetAtt NODESTACK8.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision9, !GetAtt NODESTACK9.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision10, !GetAtt NODESTACK10.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision11, !GetAtt NODESTACK11.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision12, !GetAtt NODESTACK12.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision13, !GetAtt NODESTACK13.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision14, !GetAtt NODESTACK14.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision15, !GetAtt NODESTACK15.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision16, !GetAtt NODESTACK16.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision17, !GetAtt NODESTACK17.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision18, !GetAtt NODESTACK18.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision19, !GetAtt NODESTACK19.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision20, !GetAtt NODESTACK20.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision21, !GetAtt NODESTACK21.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision22, !GetAtt NODESTACK22.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision23, !GetAtt NODESTACK23.Outputs.NodeInstanceID, !Ref AWS::NoValue] - !If [Provision24, !GetAtt NODESTACK24.Outputs.NodeInstanceID, !Ref AWS::NoValue] ClusterPlacementGroup: Description: The placement group created for the cluster Value: !Ref QClusterGroup ClusterPrivateIPs: Description: List of the primary private IPs of the nodes in your Qumulo Cluster Value: !Join - ", " - - !GetAtt NODESTACK1.Outputs.NodePrivateIP - !GetAtt NODESTACK2.Outputs.NodePrivateIP - !GetAtt NODESTACK3.Outputs.NodePrivateIP - !GetAtt NODESTACK4.Outputs.NodePrivateIP - !If [Provision5, !GetAtt NODESTACK5.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision6, !GetAtt NODESTACK6.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision7, !GetAtt NODESTACK7.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision8, !GetAtt NODESTACK8.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision9, !GetAtt NODESTACK9.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision10, !GetAtt NODESTACK10.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision11, !GetAtt NODESTACK11.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision12, !GetAtt NODESTACK12.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision13, !GetAtt NODESTACK13.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision14, !GetAtt NODESTACK14.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision15, !GetAtt NODESTACK15.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision16, !GetAtt NODESTACK16.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision17, !GetAtt NODESTACK17.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision18, !GetAtt NODESTACK18.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision19, !GetAtt NODESTACK19.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision20, !GetAtt NODESTACK20.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision21, !GetAtt NODESTACK21.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision22, !GetAtt NODESTACK22.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision23, !GetAtt NODESTACK23.Outputs.NodePrivateIP, !Ref AWS::NoValue] - !If [Provision24, !GetAtt NODESTACK24.Outputs.NodePrivateIP, !Ref AWS::NoValue] ClusterSGID: Description: The security group being used by the cluster network interfaces Value: !Ref QumuloSecurityGroup ClusterSecondaryPrivateIPs: Condition: ProvFloatIP Description: List of the secondary private IPs of the nodes in your Qumulo Cluster Value: !Join - ", " - - !Join - ", " - - !GetAtt NODESTACK1.Outputs.NodeSecondaryPrivateIPs - !Join - ", " - - !GetAtt NODESTACK2.Outputs.NodeSecondaryPrivateIPs - !Join - ", " - - !GetAtt NODESTACK3.Outputs.NodeSecondaryPrivateIPs - !Join - ", " - - !GetAtt NODESTACK4.Outputs.NodeSecondaryPrivateIPs - !If - Provision5 - !Join - ", " - - !GetAtt NODESTACK5.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision6 - !Join - ", " - - !GetAtt NODESTACK6.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision7 - !Join - ", " - - !GetAtt NODESTACK7.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision8 - !Join - ", " - - !GetAtt NODESTACK8.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision9 - !Join - ", " - - !GetAtt NODESTACK9.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision10 - !Join - ", " - - !GetAtt NODESTACK10.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision11 - !Join - ", " - - !GetAtt NODESTACK11.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision12 - !Join - ", " - - !GetAtt NODESTACK12.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision13 - !Join - ", " - - !GetAtt NODESTACK13.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision14 - !Join - ", " - - !GetAtt NODESTACK14.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision15 - !Join - ", " - - !GetAtt NODESTACK15.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision16 - !Join - ", " - - !GetAtt NODESTACK16.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision17 - !Join - ", " - - !GetAtt NODESTACK17.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision18 - !Join - ", " - - !GetAtt NODESTACK18.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision19 - !Join - ", " - - !GetAtt NODESTACK19.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision20 - !Join - ", " - - !GetAtt NODESTACK20.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision21 - !Join - ", " - - !GetAtt NODESTACK21.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision22 - !Join - ", " - - !GetAtt NODESTACK22.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision23 - !Join - ", " - - !GetAtt NODESTACK23.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue - !If - Provision24 - !Join - ", " - - !GetAtt NODESTACK24.Outputs.NodeSecondaryPrivateIPs - !Ref AWS::NoValue FlashIOPS: Description: gp3 Flash IOPS Value: !GetAtt NODESTACK1.Outputs.FlashIOPS LinkToManagement: Description: Use to launch the Qumulo Admin Console for Node 1 Value: !Join - '' - - https:// - !GetAtt NODESTACK1.Outputs.NodePrivateIP QumuloKnowledgeBase: Description: Knowledge Base for Qumulo in public clouds Value: https://care.qumulo.com/hc/en-us/categories/115000637447-KNOWLEDGE-BASE TemporaryPassword: Description: Temporary admin password for your Qumulo cluster (exclude quotes, matches node1 instance ID). Value: !Join - '' - - "\"" - !GetAtt NODESTACK1.Outputs.NodeInstanceID - "\""