def verify_vcpus_limit()

in source/soca/cluster_manager/add_nodes.py [0:0]


def verify_vcpus_limit(instance_type, desired_capacity, quota_info):
    cpus_count_pattern = re.search(r'[.](\d+)', instance_type)
    instance_family = instance_type[0].upper()
    if cpus_count_pattern:
        vcpus_per_instance = int(cpus_count_pattern.group(1)) * 4
    else:
        if 'xlarge' in instance_type:
            vcpus_per_instance = 4
        else:
            vcpus_per_instance = 2

    total_vcpus_requested = vcpus_per_instance * int(desired_capacity)
    running_vcpus = 0

    max_vcpus_allowed = False
    quota_name = False

    if not quota_info or instance_type not in quota_info.keys():
        # Get quota
        token = True
        next_token = False
        while token is True:
            if next_token is False:
                response = servicequotas.list_service_quotas(
                    ServiceCode="ec2",
                    MaxResults=100)

            else:
                response = servicequotas.list_service_quotas(
                    ServiceCode="ec2",
                    MaxResults=100,
                    NextToken=next_token)
            try:
                next_token = response['NextToken']
            except KeyError:
                token = False

            for quota in response["Quotas"]:
                # Remove 'Running' to prevent error when using R instance family
                if "running on-demand" in quota["QuotaName"].lower() and instance_family in quota["QuotaName"].replace("Running",""):
                    max_vcpus_allowed = quota["Value"]
                    quota_name = quota["QuotaName"]
                    #print("Instance Type {}. Quota {}, Max CPUs {}".format(instance_type, quota_name, max_vcpus_allowed))
    else:
        max_vcpus_allowed = quota_info[instance_type]["max_vcpus_allowed"]
        quota_name = quota_info[instance_type]["quota_name"]

    if max_vcpus_allowed is False:
        return {"message": "Unable to find ServiceQuota for {}".format(instance_type), "quota_info": quota_info}

    # list all ec2 instances
    if "standard" in quota_name.lower():
        instances_family_allowed_in_quota = re.search(r"running on-demand standard \((.*)\) instances", quota_name.lower()).group(1).split(',')
    else:
        instances_family_allowed_in_quota = list(re.search(r"running on-demand (.*) instances", quota_name.lower()).group(1))

    if not quota_info or instance_type not in quota_info.keys():
        all_instances_available = ec2._service_model.shape_for('InstanceType').enum
        all_instances_for_quota = [instance_family for x in instances_family_allowed_in_quota for instance_family in all_instances_available if instance_family.startswith(x.rstrip().lstrip())]
        required_api_calls = ceil(len(all_instances_for_quota) / 190)
        for i in range(0, required_api_calls):
            # DescribeInstances has a limit of 200 attributes per filter
            instances_to_check = all_instances_for_quota[i * 190:(i + 1) * 190]
            if instances_to_check:
                running_vcpus += find_running_cpus_per_instance(instances_to_check)

    else:
        running_vcpus = quota_info[instance_type]["vcpus_provisioned"]

    quota_info[instance_type] = {"max_vcpus_allowed": max_vcpus_allowed,
                                 "vcpus_provisioned": running_vcpus + total_vcpus_requested,
                                 "quota_name": quota_name}

    if max_vcpus_allowed >= (running_vcpus + total_vcpus_requested):
        return {"message": True, "quota_info": quota_info}
    else:
        return {"message": "Job cannot start due to AWS Service limit. Max Vcpus allowed {}. Detected running Vcpus {}. Requested Vcpus for this job {}. Quota Name {}".format(max_vcpus_allowed, running_vcpus, total_vcpus_requested, quota_name), "quota_info": quota_info}