def storage()

in installer/resources/src/cdk_construct.py [0:0]


    def storage(self):
        """
        Create two EFS or FSx for Lustre file systems that will be mounted as /apps and /data
        aws_efs.FileSystem is experimental and we cannot add multiple SG (as of April 2021).
        Because of that we have to use CfnFilesystem
        """

        if install_props.Config.storage.apps.provider == "efs" and not user_specified_variables.fs_apps:
            self.soca_resources["fs_apps"] = efs.CfnFileSystem(self, "EFSApps", encrypted=install_props.Config.storage.apps.efs.encrypted, kms_key_id=None if install_props.Config.storage.apps.kms_key_id is False else install_props.Config.storage.apps.kms_key_id,
                                                               throughput_mode=install_props.Config.storage.apps.efs.throughput_mode,
                                                               file_system_tags=[
                                                                  efs.CfnFileSystem.ElasticFileSystemTagProperty(key="soca:BackupPlan", value=user_specified_variables.cluster_id),
                                                                  efs.CfnFileSystem.ElasticFileSystemTagProperty(key="Name", value=f"{user_specified_variables.cluster_id}-Apps")],
                                                               performance_mode=install_props.Config.storage.apps.efs.performance_mode)

            if install_props.Config.storage.apps.efs.deletion_policy.upper() == "RETAIN":
                self.soca_resources["fs_apps"].cfn_options.deletion_policy = cdk.CfnDeletionPolicy.RETAIN

        if install_props.Config.storage.data.provider == "efs" and not user_specified_variables.fs_data:
            self.soca_resources["fs_data"] = efs.CfnFileSystem(self, "EFSData", encrypted=install_props.Config.storage.data.efs.encrypted, kms_key_id=None if install_props.Config.storage.data.kms_key_id is False else install_props.Config.storage.data.kms_key_id,
                                                               throughput_mode=install_props.Config.storage.data.efs.throughput_mode,
                                                               file_system_tags=[
                                                                  efs.CfnFileSystem.ElasticFileSystemTagProperty(key="soca:BackupPlan", value=user_specified_variables.cluster_id),
                                                                  efs.CfnFileSystem.ElasticFileSystemTagProperty(key="Name", value=f"{user_specified_variables.cluster_id}-Data")],
                                                               lifecycle_policies=[efs.CfnFileSystem.LifecyclePolicyProperty(transition_to_ia=install_props.Config.storage.data.efs.transition_to_ia)],
                                                               performance_mode=install_props.Config.storage.data.efs.performance_mode)
            if install_props.Config.storage.data.efs.deletion_policy.upper() == "RETAIN":
                self.soca_resources["fs_data"].cfn_options.deletion_policy = cdk.CfnDeletionPolicy.RETAIN

        # Create the mount targets for /data
        if install_props.Config.storage.data.provider == "efs" and not user_specified_variables.fs_data:
            for i in range(len(self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnet_ids)):
                efs.CfnMountTarget(self, f"EFSDataMountTarget{i+1}", file_system_id=self.soca_resources["fs_data"].ref,
                                   security_groups=[self.soca_resources["compute_node_sg"].security_group_id, self.soca_resources["scheduler_sg"].security_group_id],
                                   subnet_id=self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnets[i].subnet_id)

        # Create the mount targets for /apps
        if install_props.Config.storage.apps.provider == "efs" and not user_specified_variables.fs_apps:
            for i in range(len(self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnet_ids)):
                efs.CfnMountTarget(self, f"EFSAppsMountTarget{i+1}", file_system_id=self.soca_resources["fs_apps"].ref,
                                   security_groups=[self.soca_resources["compute_node_sg"].security_group_id, self.soca_resources["scheduler_sg"].security_group_id],
                                   subnet_id=self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnets[i].subnet_id)

            # Create CloudWatch/SNS alarm for SNS EFS. This will check BurstCreditBalance and increase allocated throughput to support temporary burst activity if needed
            sns_efs_topic = sns.Topic(self, "SNSEFSTopic", display_name=f"{user_specified_variables.cluster_id}-EFSAlarm-SNS", topic_name=f"{user_specified_variables.cluster_id}-EFSAlarm-SNS")
            sns_efs_topic.add_to_resource_policy(iam.PolicyStatement(effect=iam.Effect.ALLOW, actions=["sns:Publish"],
                                                                     resources=[sns_efs_topic.topic_arn], principals=[iam.ServicePrincipal(principals_suffix["cloudwatch"])],
                                                                     conditions={"ArnLike": {"aws:SourceArn": f"arn:{core.Aws.PARTITION}:*:*:{core.Aws.ACCOUNT_ID}:*"}}))

            efs_apps_cw_alarm_low = cloudwatch.Alarm(self, "EFSAppsCWAlarmLowThreshold",
                                                     metric=cloudwatch.Metric(metric_name="BurstCreditBalance",
                                                     namespace="AWS/EFS", dimensions=dict(FileSystemId=self.soca_resources["fs_apps"].ref)),
                                                     comparison_operator=cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD,
                                                     evaluation_periods=10, period=core.Duration.minutes(1), statistic="Average", threshold=10000000)

            efs_apps_cw_alarm_high = cloudwatch.Alarm(self, "EFSAppsCWAlarmHighThreshold",
                                                      metric=cloudwatch.Metric(metric_name="BurstCreditBalance",
                                                      namespace="AWS/EFS", dimensions=dict(FileSystemId=self.soca_resources["fs_apps"].ref)),
                                                      comparison_operator=cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
                                                      evaluation_periods=10, period=core.Duration.minutes(1), statistic="Average", threshold=2000000000000)
            efs_apps_cw_alarm_low.add_alarm_action(cw_actions.SnsAction(sns_efs_topic))
            efs_apps_cw_alarm_high.add_alarm_action(cw_actions.SnsAction(sns_efs_topic))

            efs_apps_throughput_lambda = aws_lambda.Function(self, f"{user_specified_variables.cluster_id}-EFSAppsLambda",
                                                             function_name=f"{user_specified_variables.cluster_id}-EFSThroughput",
                                                             description="Check EFS BurstCreditBalance and update ThroughputMode when needed",
                                                             memory_size=128, role=self.soca_resources["fs_apps_lambda_role"],
                                                             timeout=core.Duration.minutes(3),
                                                             runtime=aws_lambda.Runtime.PYTHON_3_7,
                                                             log_retention=logs.RetentionDays.INFINITE,
                                                             handler="EFSThroughputLambda.lambda_handler",
                                                             code=aws_lambda.Code.asset("../functions/EFSThroughputLambda"))
            efs_apps_throughput_lambda.add_environment("EFSBurstCreditLowThreshold", "10000000")
            efs_apps_throughput_lambda.add_environment("EFSBurstCreditHighThreshold", "2000000000000")
            efs_apps_throughput_lambda.add_permission("InvokePermission", principal=iam.ServicePrincipal(principals_suffix["sns"]), action="lambda:InvokeFunction")

            sns.Subscription(self, f"{user_specified_variables.cluster_id}-SNSEFSSubscription", protocol=sns.SubscriptionProtocol.LAMBDA, endpoint=efs_apps_throughput_lambda.function_arn, topic=sns_efs_topic)

        if install_props.Config.storage.data.provider == "fsx_lustre" and not user_specified_variables.fs_data:
            if install_props.Config.storage.data.fsx_lustre.storage_type == "SSD":
                if install_props.Config.storage.data.fsx_lustre.deployment_type == "PERSISTENT_1":
                    lustre_configuration = fsx.CfnFileSystem.LustreConfigurationProperty(
                        per_unit_storage_throughput=install_props.Config.storage.data.fsx_lustre.per_unit_storage_throughput,
                        deployment_type=install_props.Config.storage.data.fsx_lustre.deployment_type)
                else:
                    lustre_configuration = fsx.CfnFileSystem.LustreConfigurationProperty(
                        deployment_type=install_props.Config.storage.data.fsx_lustre.deployment_type)
            else:
                lustre_configuration = fsx.CfnFileSystem.LustreConfigurationProperty(
                    deployment_type=install_props.Config.storage.data.fsx_lustre.deployment_type,
                    per_unit_storage_throughput=install_props.Config.storage.data.fsx_lustre.per_unit_storage_throughput,
                    drive_cache_type=install_props.Config.storage.data.fsx_lustre.drive_cache_type),

            self.soca_resources["fs_data"] = fsx.CfnFileSystem(self, "FSxLustreData", file_system_type="LUSTRE",
                    subnet_ids=[self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnets[0].subnet_id],
                    lustre_configuration=lustre_configuration,
                    security_group_ids=[self.soca_resources["compute_node_sg"].security_group_id],
                    storage_capacity=install_props.Config.storage.data.fsx_lustre.storage_capacity,
                    storage_type=install_props.Config.storage.data.fsx_lustre.storage_type,
                    kms_key_id=None if install_props.Config.storage.data.kms_key_id is False else install_props.Config.storage.data.kms_key_id)

            core.Tags.of(self.soca_resources["fs_data"]).add("Name", f"{user_specified_variables.cluster_id}-Data")

        if install_props.Config.storage.apps.provider == "fsx_lustre" and not user_specified_variables.fs_apps:
            if install_props.Config.storage.apps.fsx_lustre.storage_type == "SSD":
                if install_props.Config.storage.apps.fsx_lustre.deployment_type == "PERSISTENT_1":
                    lustre_configuration=fsx.CfnFileSystem.LustreConfigurationProperty(
                        per_unit_storage_throughput=install_props.Config.storage.apps.fsx_lustre.per_unit_storage_throughput,
                        deployment_type=install_props.Config.storage.apps.fsx_lustre.deployment_type)
                else:
                    lustre_configuration=fsx.CfnFileSystem.LustreConfigurationProperty(
                        deployment_type=install_props.Config.storage.apps.fsx_lustre.deployment_type)
            else:
                lustre_configuration=fsx.CfnFileSystem.LustreConfigurationProperty(
                    deployment_type=install_props.Config.storage.apps.fsx_lustre.deployment_type,
                    per_unit_storage_throughput=install_props.Config.storage.apps.fsx_lustre.per_unit_storage_throughput,
                    drive_cache_type=install_props.Config.storage.apps.fsx_lustre.drive_cache_type),

            self.soca_resources["fs_apps"] = fsx.CfnFileSystem(self, "FSxLustreApps", file_system_type="LUSTRE",
                    subnet_ids=[self.soca_resources["vpc"].select_subnets(subnet_type=ec2.SubnetType.PRIVATE).subnets[0].subnet_id],
                    lustre_configuration=lustre_configuration,
                    security_group_ids=[self.soca_resources["compute_node_sg"].security_group_id],
                    storage_capacity=install_props.Config.storage.apps.fsx_lustre.storage_capacity,
                    storage_type=install_props.Config.storage.apps.fsx_lustre.storage_type,
                    kms_key_id=None if install_props.Config.storage.apps.kms_key_id is False else install_props.Config.storage.apps.kms_key_id)

            core.Tags.of(self.soca_resources["fs_apps"]).add("Name", f"{user_specified_variables.cluster_id}-Apps")