Skip to content

hcloud

sc_crawler.vendors.hcloud #

inventory_compliance_frameworks #

inventory_compliance_frameworks(vendor)

Manual list of known compliance frameworks at Hetzner.

Data collected from https://www.hetzner.com/unternehmen/zertifizierung.

Source code in sc_crawler/vendors/hcloud.py
def inventory_compliance_frameworks(vendor):
    """Manual list of known compliance frameworks at Hetzner.

    Data collected from <https://www.hetzner.com/unternehmen/zertifizierung>."""
    return map_compliance_frameworks_to_vendor(vendor.vendor_id, ["iso27001"])

inventory_regions #

inventory_regions(vendor)

List all regions via API call.

Hetzner Cloud uses integers for the region (virtual datacenter) id that we convert into string. Best to use the unique name, which can be also passed instead of the id in most hcloud API endpoints via the id_or_name method.

Not taking the Hetzner unique name as id, as it's not stated to be unique for other resources, and uniqueness for servers might also change in the future.

All regions are powered by green energy as per https://www.hetzner.com/unternehmen/umweltschutz/.

Lon/lat coordinates were collected by searching for Hetzner locations in the Region's city.

Source code in sc_crawler/vendors/hcloud.py
def inventory_regions(vendor):
    """List all regions via API call.

    Hetzner Cloud uses integers for the region (virtual datacenter) id
    that we convert into string. Best to use the unique `name`, which
    can be also passed instead of the `id` in most `hcloud` API
    endpoints via the `id_or_name` method.

    Not taking the Hetzner unique `name` as id, as it's not
    stated to be unique for other resources, and uniqueness
    for servers might also change in the future.

    All regions are powered by green energy as per
    <https://www.hetzner.com/unternehmen/umweltschutz/>.

    Lon/lat coordinates were collected by searching for Hetzner
    locations in the Region's city.

    """
    regions = {
        "2": {  # Nuremberg
            "lat": 49.4498349,
            "lon": 11.0128772,
        },
        "3": {  # Helsinki
            "lat": 60.3433291,
            "lon": 25.02683,
        },
        "4": {  # Falkenstein
            "lat": 50.4793313,
            "lon": 12.3331105,
        },
        "5": {  # Ashburn, VA
            "lat": 39.0176685,
            "lon": -77.468102,
        },
        "6": {  # Hillsboro, OR
            "lat": 45.558319,
            "lon": -122.9306602,
        },
        "7": {  # Singapore
            "lat": 1.290270,
            "lon": 103.851959,
        },
    }

    items = []
    for region in _client().datacenters.get_all():
        items.append(
            {
                "vendor_id": vendor.vendor_id,
                "region_id": str(region.id),
                "name": region.name,
                "api_reference": region.name,
                "display_name": (
                    region.location.city + f" ({region.location.country})"
                ),
                # TODO add region.description
                "aliases": [region.location.name],
                "country_id": region.location.country,
                "state": None,
                "city": region.location.city,
                "address_line": None,
                "zip_code": None,
                "lat": regions[str(region.id)]["lat"],
                "lon": regions[str(region.id)]["lon"],
                "founding_year": None,
                "green_energy": True,
            }
        )
    return items

inventory_zones #

inventory_zones(vendor)

List all regions as availability zones.

There is no concept of having multiple availability zones withing a region (virtual datacenter) at Hetzner Cloud, so creating 1-1 dummy Zones reusing the Region id and name.

Source code in sc_crawler/vendors/hcloud.py
def inventory_zones(vendor):
    """List all regions as availability zones.

    There is no concept of having multiple availability zones withing
    a region (virtual datacenter) at Hetzner Cloud, so creating 1-1
    dummy Zones reusing the Region id and name.

    """
    items = []
    for region in vendor.regions:
        items.append(
            {
                "vendor_id": vendor.vendor_id,
                "region_id": region.region_id,
                "zone_id": region.region_id,
                "name": region.name,
                "api_reference": region.name,
                "display_name": region.name,
            }
        )
    return items

inventory_servers #

inventory_servers(vendor)

List all server types from API and manual data entry from the Hetzner Cloud homepage.

CPU information is recorded from https://www.hetzner.com/cloud/ as not exposed via API.

Source code in sc_crawler/vendors/hcloud.py
def inventory_servers(vendor):
    """List all server types from API and manual data entry from the Hetzner Cloud homepage.

    CPU information is recorded from <https://www.hetzner.com/cloud/> as not exposed via API."""
    items = []
    for server in _client().server_types.get_all():
        # CPU info not available via the API,
        # collected from https://www.hetzner.com/cloud/
        cpu = _server_cpu(server.name)
        items.append(
            {
                "vendor_id": vendor.vendor_id,
                "server_id": str(server.id),
                "name": server.name,
                "api_reference": server.name,
                "display_name": server.name,
                "description": server.description,
                "family": server.name.rstrip("0123456789"),
                "vcpus": server.cores,
                "hypervisor": "QEMU",
                "cpu_allocation": (
                    CpuAllocation.SHARED
                    if server.cpu_type == "shared"
                    else CpuAllocation.DEDICATED
                ),
                "cpu_cores": None,
                "cpu_speed": None,
                "cpu_architecture": (
                    CpuArchitecture.ARM64
                    if server.architecture == "arm"
                    else CpuArchitecture.X86_64
                ),
                "cpu_manufacturer": cpu[0],
                "cpu_family": cpu[1],
                "cpu_model": cpu[2],
                "cpus": [],
                "memory_amount": server.memory * 1024,
                "gpu_count": 0,
                "gpu_memory_min": None,
                "gpu_memory_total": None,
                "gpu_manufacturer": None,
                "gpu_model": None,
                "gpus": [],
                "storage_size": server.disk,
                "storage_type": (
                    StorageType.SSD
                    if server.storage_type == "local"
                    else StorageType.NETWORK
                ),
                "storages": [],
                "network_speed": None,
                # https://docs.hetzner.com/cloud/billing/faq/#how-do-you-bill-for-traffic
                "inbound_traffic": 0,  # free
                "outbound_traffic": (
                    max([region.get("included_traffic") for region in server.prices])
                    / (1024**3)
                ),
                "ipv4": 0,
                "status": Status.ACTIVE if not server.deprecation else Status.INACTIVE,
            }
        )
    return items

inventory_server_prices_spot #

inventory_server_prices_spot(vendor)

There are no spot instaces at Hetzner.

Source code in sc_crawler/vendors/hcloud.py
def inventory_server_prices_spot(vendor):
    """There are no spot instaces at Hetzner."""
    return []

inventory_storages #

inventory_storages(vendor)

Block storage volume information collected manually.

There is not information shared vie the API, so information was collected manually from:

Source code in sc_crawler/vendors/hcloud.py
def inventory_storages(vendor):
    """Block storage volume information collected manually.

    There is not information shared vie the API, so information
    was collected manually from:

    - <https://www.hetzner.com/cloud/>
    - <https://docs.hetzner.cloud/#volumes-create-a-volume>
    """
    items = [
        {
            "storage_id": "block",
            "vendor_id": vendor.vendor_id,
            "name": "Block storage volume",
            "description": None,
            "storage_type": StorageType.NETWORK,
            "max_iops": None,
            "max_throughput": None,
            "min_size": 10,
            "max_size": 10240,
        }
    ]
    return items

inventory_storage_prices #

inventory_storage_prices(vendor)

Block storage volume pricing information collected manually.

Source: https://www.hetzner.com/cloud/

Source code in sc_crawler/vendors/hcloud.py
def inventory_storage_prices(vendor):
    """Block storage volume pricing information collected manually.

    Source: <https://www.hetzner.com/cloud/>
    """
    items = []
    for region in vendor.regions:
        items.append(
            {
                "vendor_id": vendor.vendor_id,
                "region_id": region.region_id,
                "storage_id": "block",
                "unit": PriceUnit.GB_MONTH,
                "price": 0.0440,
                "currency": "EUR",
            }
        )
    return items

inventory_traffic_prices #

inventory_traffic_prices(vendor)

Traffic price collected manually.

Source: https://docs.hetzner.com/robot/general/traffic/

Source code in sc_crawler/vendors/hcloud.py
def inventory_traffic_prices(vendor):
    """Traffic price collected manually.

    Source: <https://docs.hetzner.com/robot/general/traffic/>
    """
    items = []
    for region in vendor.regions:
        items.append(
            {
                "vendor_id": vendor.vendor_id,
                "region_id": region.region_id,
                "price": 0,
                "price_tiered": [],
                "currency": "EUR",
                "unit": PriceUnit.GB_MONTH,
                "direction": TrafficDirection.IN,
            }
        )
        items.append(
            {
                "vendor_id": vendor.vendor_id,
                "region_id": region.region_id,
                "price": round(1 / 1024, 8),
                "price_tiered": [],
                "currency": "EUR",
                "unit": PriceUnit.GB_MONTH,
                "direction": TrafficDirection.OUT,
            }
        )
    return items

inventory_ipv4_prices #

inventory_ipv4_prices(vendor)

IPv4 price collected manually.

Source: https://docs.hetzner.com/general/others/ipv4-pricing/#cloud

Source code in sc_crawler/vendors/hcloud.py
def inventory_ipv4_prices(vendor):
    """IPv4 price collected manually.

    Source: <https://docs.hetzner.com/general/others/ipv4-pricing/#cloud>
    """
    items = []
    for region in vendor.regions:
        items.append(
            {
                "vendor_id": vendor.vendor_id,
                "region_id": region.region_id,
                "price": 0.50,
                "currency": "EUR",
                "unit": PriceUnit.MONTH,
            }
        )
    return items