Skip to content

Commit

Permalink
fix SpareCores/sc-www#163 check if instance is available in the zone
Browse files Browse the repository at this point in the history
  • Loading branch information
daroczig committed Jan 17, 2025
1 parent a4cdda1 commit 38e818c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 4 deletions.
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ The related user or role requires the below minimum IAM policy:
"ec2:DescribeRegions",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeInstanceTypes",
"ec2:DescribeSpotPriceHistory"
"ec2:DescribeSpotPriceHistory",
"ec2:DescribeInstanceTypeOfferings"
],
"Resource": "*"
}
Expand Down
55 changes: 52 additions & 3 deletions src/sc_crawler/vendors/aws.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import re
from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timedelta
from itertools import chain, repeat
Expand All @@ -21,6 +22,7 @@
Gpu,
PriceTier,
PriceUnit,
Status,
StorageType,
TrafficDirection,
)
Expand Down Expand Up @@ -64,6 +66,33 @@ def _boto_describe_availability_zones(region):
return zones


@cachier()
def _describe_instance_type_offerings_per_zone(region: str):
"""Lookup all instance types available in a region per zone.
Args:
region: AWS region id
Returns:
Dict of instance types as keys and list of zone ids as values.
"""
client = boto3.client("ec2", region_name=region)
paginator = client.get_paginator("describe_instance_type_offerings")
instances = defaultdict(list)
for page in paginator.paginate(LocationType="availability-zone-id"):
for instance in page["InstanceTypeOfferings"]:
instances[instance["InstanceType"]].append(instance["Location"])
return instances


def _describe_instance_type_offerings_per_zone_with_progress(
region: str, vendor: Vendor
) -> dict:
zones = _describe_instance_type_offerings_per_zone(region)
vendor.progress_tracker.advance_task()
return zones


@cachier()
def _boto_price_list(region):
"""Download published AWS price lists. Currently unused."""
Expand Down Expand Up @@ -860,6 +889,23 @@ def inventory_server_prices(vendor):
regions = scmodels_to_dict(vendor.regions, keys=["name", "aliases"])
servers = scmodels_to_dict(vendor.servers, keys=["server_id"])

# check all regions for instance types per zone
active_region_ids = [
r.api_reference for r in regions.values() if r.status == Status.ACTIVE
]
vendor.progress_tracker.start_task(
name="Look up supported server types in all ACTIVE regions/zones",
total=len(active_region_ids),
)
with ThreadPoolExecutor(max_workers=8) as executor:
regions_servers = executor.map(
_describe_instance_type_offerings_per_zone_with_progress,
active_region_ids,
repeat(vendor),
)
regions_servers = dict(zip(active_region_ids, regions_servers))
vendor.progress_tracker.hide_task()

server_prices = []
vendor.progress_tracker.start_task(
name="Preprocess ondemand server_price(s)", total=len(products)
Expand All @@ -870,15 +916,18 @@ def inventory_server_prices(vendor):
# early drop Gov regions
if "GovCloud" in attributes["location"]:
continue
region = regions[attributes["location"]]
server = servers[attributes["instanceType"]]
region = regions[attributes["location"]]
zones = regions_servers.get(region.api_reference, {}).get(
server.server_id, []
)
price = _extract_ondemand_price(product["terms"])
for zone in region.zones:
for zone in zones:
server_prices.append(
{
"vendor_id": vendor.vendor_id,
"region_id": region.region_id,
"zone_id": zone.zone_id,
"zone_id": zone,
"server_id": server.server_id,
# TODO ingest other OSs
"operating_system": "Linux",
Expand Down

0 comments on commit 38e818c

Please sign in to comment.