From f8a138561bd3d36d30b714d9ff122440f9c9dfa1 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 20 Oct 2025 21:18:00 -0400 Subject: [PATCH 01/11] terraform/oci: Introduce helper functions I'm about to add scripts to generate some of the Kconfig menus that configure the OCI terraform provider. Some commonly used helper functions are introduced first as a loadable module. Generated-by: Claude AI Signed-off-by: Chuck Lever --- .gitignore | 2 + terraform/oci/scripts/oci_common.py | 285 ++++++++++++++++++++++++++++ 2 files changed, 287 insertions(+) create mode 100644 terraform/oci/scripts/oci_common.py diff --git a/.gitignore b/.gitignore index a96217845..251a5ce53 100644 --- a/.gitignore +++ b/.gitignore @@ -122,6 +122,8 @@ terraform/aws/kconfigs/Kconfig.instance.generated terraform/aws/kconfigs/Kconfig.location.generated terraform/aws/scripts/__pycache__/ +terraform/oci/scripts/__pycache__/ + .cloud.initialized scripts/__pycache__/ diff --git a/terraform/oci/scripts/oci_common.py b/terraform/oci/scripts/oci_common.py new file mode 100644 index 000000000..1485b5275 --- /dev/null +++ b/terraform/oci/scripts/oci_common.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python3 +# ex: set filetype=python: + +""" +Common utilities for OCI Kconfig generation scripts. + +This module provides shared functionality used by gen_kconfig_location, +gen_kconfig_shape, and gen_kconfig_image scripts to avoid code duplication. +""" + +from __future__ import annotations + +import os +import sys +from configparser import ConfigParser +from pathlib import Path +from typing import Any, Optional + +import yaml +from jinja2 import Environment, FileSystemLoader + + +def get_default_region() -> str: + """ + Get the default OCI region from the ~/.oci/config file. + + Returns: + str: Default region, or 'us-ashburn-1' if no default is found. + """ + config_path = os.path.expanduser("~/.oci/config") + if os.path.exists(config_path): + try: + config = ConfigParser() + config.read(config_path) + if "DEFAULT" in config: + return config["DEFAULT"].get("region", "us-ashburn-1") + except Exception as e: + print(f"Warning: Error reading OCI config file: {e}", file=sys.stderr) + return "us-ashburn-1" + + +def get_default_compartment() -> Optional[str]: + """ + Get the default compartment OCID from OCI config. + + Returns: + str: Tenancy OCID (root compartment), or None on error + """ + try: + config = get_oci_config() + return config["tenancy"] + except Exception as e: + print(f"Error getting compartment: {e}", file=sys.stderr) + return None + + +def get_subscribed_regions(quiet: bool = False) -> list[str]: + """ + Get all subscribed regions for the tenancy. + + Args: + quiet (bool): Suppress debug messages + + Returns: + list: List of subscribed region names + """ + try: + config = get_oci_config() + identity = create_identity_client() + + region_subs = identity.list_region_subscriptions(config["tenancy"]).data + subscribed = [r.region_name for r in region_subs if r.status == "READY"] + + if not quiet: + print( + f"Found {len(subscribed)} subscribed regions: {', '.join(subscribed)}", + file=sys.stderr, + ) + + return subscribed + + except Exception as e: + print(f"Error getting subscribed regions: {e}", file=sys.stderr) + # Fallback to default region + return [get_default_region()] + + +def get_jinja2_environment(template_path: Optional[str] = None) -> Environment: + """ + Create a standardized Jinja2 environment for template rendering. + + Args: + template_path (str): Path to template directory. If None, uses caller's directory. + + Returns: + Environment: Configured Jinja2 Environment object + """ + if template_path is None: + template_path = Path(__file__).parent + + return Environment( + loader=FileSystemLoader(template_path), + trim_blocks=True, + lstrip_blocks=True, + ) + + +def load_yaml_config( + filename: str, quiet: bool = False, default: Optional[Any] = None +) -> Any: + """ + Load a YAML configuration file with consistent error handling. + + This function provides standardized YAML loading used across all + gen_kconfig_* scripts for loading configuration files like + region_friendly_names.yml, catalog_shapes.yml, and + publisher_definitions.yml. + + Args: + filename (str): Name of YAML file (not full path - will be looked up + in script directory) + quiet (bool): Suppress warning messages to stderr + default: Default value to return on error (default: empty dict) + + Returns: + Data loaded from YAML file, or default value on error + """ + if default is None: + default = {} + + yaml_path = Path(__file__).parent / filename + + try: + with open(yaml_path, "r") as f: + data = yaml.safe_load(f) + return data if data else default + except FileNotFoundError: + if not quiet: + print(f"Warning: {yaml_path} not found. Using defaults.", file=sys.stderr) + return default + except yaml.YAMLError as e: + if not quiet: + print( + f"Warning: Error parsing {yaml_path}: {e}. Using defaults.", + file=sys.stderr, + ) + return default + + +def get_oci_config(region: Optional[str] = None) -> dict[str, Any]: + """ + Get OCI configuration with optional region override. + + This provides a centralized way to load OCI config and optionally + override the region, with consistent error handling. + + Args: + region (str): Optional region to override config default + + Returns: + dict: OCI configuration dictionary + + Raises: + ConfigFileNotFound: If OCI config file doesn't exist + Exception: For other configuration errors + """ + # Lazy import - only load OCI SDK when actually needed + import oci + + config = oci.config.from_file() + if region: + config["region"] = region + return config + + +def create_identity_client(region: Optional[str] = None) -> oci.identity.IdentityClient: + """ + Create an OCI Identity client with optional region override. + + Args: + region (str): Optional region to use instead of config default + + Returns: + oci.identity.IdentityClient: Configured identity client + + Raises: + ConfigFileNotFound: If OCI config file doesn't exist + Exception: For other initialization errors + """ + # Lazy import - only load OCI SDK when actually needed + import oci + + config = get_oci_config(region) + return oci.identity.IdentityClient(config) + + +def create_compute_client(region: Optional[str] = None) -> oci.core.ComputeClient: + """ + Create an OCI Compute client with optional region override. + + Args: + region (str): Optional region to use instead of config default + + Returns: + oci.core.ComputeClient: Configured compute client + + Raises: + ConfigFileNotFound: If OCI config file doesn't exist + Exception: For other initialization errors + """ + # Lazy import - only load OCI SDK when actually needed + import oci + + config = get_oci_config(region) + return oci.core.ComputeClient(config) + + +def get_all_region_keys(quiet: bool = False) -> dict[str, str]: + """ + Get all OCI regions with their official region keys from the OCI API. + + The region key is the 3-letter code (e.g., 'ORD' for us-chicago-1) + that OCI uses in its API responses. This is the authoritative source + for region codes rather than hardcoding a mapping. + + Args: + quiet (bool): Suppress debug messages + + Returns: + dict: Dictionary mapping region_name -> region_key (e.g., 'us-chicago-1' -> 'ORD') + """ + try: + identity = create_identity_client() + + # Get all regions - this includes their official region keys + all_regions = identity.list_regions().data + + region_key_map = {} + for region in all_regions: + region_key_map[region.name] = region.key + + if not quiet: + print( + f"Loaded {len(region_key_map)} region key mappings from OCI API", + file=sys.stderr, + ) + + return region_key_map + + except Exception as e: + if not quiet: + print( + f"Warning: Could not load region keys from OCI API: {e}", + file=sys.stderr, + ) + print("Using fallback region key generation", file=sys.stderr) + return {} + + +def get_region_kconfig_name( + region_name: str, region_key_map: Optional[dict[str, str]] = None +) -> str: + """ + Convert OCI region name to Kconfig region constant name. + + Uses the official region key from the OCI API when available, + falling back to a generated name if the API is not accessible. + + Args: + region_name (str): OCI region name (e.g., 'us-chicago-1') + region_key_map (dict): Optional mapping from region_name to region_key. + If None, generates from region name. + + Returns: + str: Kconfig constant name (e.g., 'ORD' for us-chicago-1) + """ + if region_key_map and region_name in region_key_map: + return region_key_map[region_name] + + # Fallback: generate from region name + # Take first 3 letters of the location part + parts = region_name.split("-") + if len(parts) >= 2: + return parts[1][:3].upper() + return region_name[:3].upper() From 76594d568b42dd93859717c50fb51d7007c8188a Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sun, 19 Oct 2025 11:30:49 -0400 Subject: [PATCH 02/11] terraform/oci: Remove the kconfigs/regions subdirectory Luis convinced me that placing each region in its own subdirectory does not make dynamically generating Kconfig menus any simpler. I'm making this change now so we have a cleaner diff to compare the current menu file with the dynamically-generated one. Signed-off-by: Chuck Lever --- terraform/oci/kconfigs/Kconfig.location | 262 +++++++++++++++++- .../kconfigs/regions/Kconfig.ap-hyderabad-1 | 28 -- .../oci/kconfigs/regions/Kconfig.ap-mumbai-1 | 27 -- .../kconfigs/regions/Kconfig.ca-montreal-1 | 28 -- .../oci/kconfigs/regions/Kconfig.ca-toronto-1 | 28 -- .../oci/kconfigs/regions/Kconfig.us-ashburn-1 | 36 --- .../oci/kconfigs/regions/Kconfig.us-chicago-1 | 36 --- .../oci/kconfigs/regions/Kconfig.us-phoenix-1 | 36 --- .../oci/kconfigs/regions/Kconfig.us-sanjose-1 | 28 -- 9 files changed, 254 insertions(+), 255 deletions(-) delete mode 100644 terraform/oci/kconfigs/regions/Kconfig.ap-hyderabad-1 delete mode 100644 terraform/oci/kconfigs/regions/Kconfig.ap-mumbai-1 delete mode 100644 terraform/oci/kconfigs/regions/Kconfig.ca-montreal-1 delete mode 100644 terraform/oci/kconfigs/regions/Kconfig.ca-toronto-1 delete mode 100644 terraform/oci/kconfigs/regions/Kconfig.us-ashburn-1 delete mode 100644 terraform/oci/kconfigs/regions/Kconfig.us-chicago-1 delete mode 100644 terraform/oci/kconfigs/regions/Kconfig.us-phoenix-1 delete mode 100644 terraform/oci/kconfigs/regions/Kconfig.us-sanjose-1 diff --git a/terraform/oci/kconfigs/Kconfig.location b/terraform/oci/kconfigs/Kconfig.location index eb5bac8d9..1d7de2868 100644 --- a/terraform/oci/kconfigs/Kconfig.location +++ b/terraform/oci/kconfigs/Kconfig.location @@ -42,14 +42,260 @@ config TERRAFORM_OCI_REGION_SJC endchoice -source "terraform/oci/kconfigs/regions/Kconfig.ap-hyderabad-1" -source "terraform/oci/kconfigs/regions/Kconfig.ap-mumbai-1" -source "terraform/oci/kconfigs/regions/Kconfig.ca-montreal-1" -source "terraform/oci/kconfigs/regions/Kconfig.ca-toronto-1" -source "terraform/oci/kconfigs/regions/Kconfig.us-ashburn-1" -source "terraform/oci/kconfigs/regions/Kconfig.us-chicago-1" -source "terraform/oci/kconfigs/regions/Kconfig.us-phoenix-1" -source "terraform/oci/kconfigs/regions/Kconfig.us-sanjose-1" +if TERRAFORM_OCI_REGION_HYD + +config TERRAFORM_OCI_REGION + string + output yaml + default "ap-hyderabad-1" + +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_HYD_AD1 + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +config TERRAFORM_OCI_REGION_HYD_AD1 + bool "1" + +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml + default 1 if TERRAFORM_OCI_REGION_HYD_1_AD1 + +endif # TERRAFORM_OCI_REGION_HYD_1 + +if TERRAFORM_OCI_REGION_BOM + +config TERRAFORM_OCI_REGION + string + output yaml + default "ap-mumbai-1" +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_BOM_AD1 + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +config TERRAFORM_OCI_REGION_BOM_AD1 + bool "1" + +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml + default 1 if TERRAFORM_OCI_REGION_BOM_AD1 + +endif # TERRAFORM_OCI_REGION_BOM + +if TERRAFORM_OCI_REGION_YUL + +config TERRAFORM_OCI_REGION + string + output yaml + default "ca-montreal-1" + +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_YUL_AD1 + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +config TERRAFORM_OCI_REGION_YUL_AD1 + bool "1" + +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml + default 1 if TERRAFORM_OCI_REGION_YUL_AD1 + +endif # TERRAFORM_OCI_REGION_YUL + +if TERRAFORM_OCI_REGION_YYZ + +config TERRAFORM_OCI_REGION + string + output yaml + default "ca-toronto-1" + +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_YYZ_AD1 + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +config TERRAFORM_OCI_REGION_YYZ_AD1 + bool "1" + +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml + default 1 if TERRAFORM_OCI_REGION_YYZ_AD1 + +endif # TERRAFORM_OCI_REGION_YYZ + +if TERRAFORM_OCI_REGION_IAD + +config TERRAFORM_OCI_REGION + string + output yaml + default "us-ashburn-1" + +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_IAD_AD1 + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +config TERRAFORM_OCI_REGION_IAD_AD1 + bool "1" + +config TERRAFORM_OCI_REGION_IAD_AD2 + bool "2" + +config TERRAFORM_OCI_REGION_IAD_AD3 + bool "3" + +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml + default 1 if TERRAFORM_OCI_REGION_IAD_AD1 + default 2 if TERRAFORM_OCI_REGION_IAD_AD2 + default 3 if TERRAFORM_OCI_REGION_IAD_AD3 + +endif # TERRAFORM_OCI_REGION_IAD + +if TERRAFORM_OCI_REGION_ORD + +config TERRAFORM_OCI_REGION + string + output yaml + default "us-chicago-1" + +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_ORD_AD1 + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +config TERRAFORM_OCI_REGION_ORD_AD1 + bool "1" + +config TERRAFORM_OCI_REGION_ORD_AD2 + bool "2" + +config TERRAFORM_OCI_REGION_ORD_AD3 + bool "3" + +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml + default 1 if TERRAFORM_OCI_REGION_ORD_AD1 + default 2 if TERRAFORM_OCI_REGION_ORD_AD2 + default 3 if TERRAFORM_OCI_REGION_ORD_AD3 + +endif # TERRAFORM_OCI_REGION_ORD + +if TERRAFORM_OCI_REGION_PHX + +config TERRAFORM_OCI_REGION + string + output yaml + default "us-phoenix-1" + +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_PHX_AD1 + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +config TERRAFORM_OCI_REGION_PHX_AD1 + bool "1" + +config TERRAFORM_OCI_REGION_PHX_AD2 + bool "2" + +config TERRAFORM_OCI_REGION_PHX_AD3 + bool "3" + +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml + default 1 if TERRAFORM_OCI_REGION_PHX_AD1 + default 2 if TERRAFORM_OCI_REGION_PHX_AD2 + default 3 if TERRAFORM_OCI_REGION_PHX_AD3 + +endif # TERRAFORM_OCI_REGION_PHX + +if TERRAFORM_OCI_REGION_SJC + +config TERRAFORM_OCI_REGION + string + output yaml + default "us-sanjose-1" + +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_SJC_AD1 + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +config TERRAFORM_OCI_REGION_SJC_AD1 + bool "1" + +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml + default 1 if TERRAFORM_OCI_REGION_SJC_AD1 + +endif # TERRAFORM_OCI_REGION_SJC config TERRAFORM_OCI_COMPARTMENT_NAME string "OCI compartment name" diff --git a/terraform/oci/kconfigs/regions/Kconfig.ap-hyderabad-1 b/terraform/oci/kconfigs/regions/Kconfig.ap-hyderabad-1 deleted file mode 100644 index f4ac37ef3..000000000 --- a/terraform/oci/kconfigs/regions/Kconfig.ap-hyderabad-1 +++ /dev/null @@ -1,28 +0,0 @@ -if TERRAFORM_OCI_REGION_HYD - -config TERRAFORM_OCI_REGION - string - output yaml - default "ap-hyderabad-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_HYD_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_HYD_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_HYD_1_AD1 - -endif # TERRAFORM_OCI_REGION_HYD_1 diff --git a/terraform/oci/kconfigs/regions/Kconfig.ap-mumbai-1 b/terraform/oci/kconfigs/regions/Kconfig.ap-mumbai-1 deleted file mode 100644 index f05b595c3..000000000 --- a/terraform/oci/kconfigs/regions/Kconfig.ap-mumbai-1 +++ /dev/null @@ -1,27 +0,0 @@ -if TERRAFORM_OCI_REGION_BOM - -config TERRAFORM_OCI_REGION - string - output yaml - default "ap-mumbai-1" -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_BOM_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_BOM_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_BOM_AD1 - -endif # TERRAFORM_OCI_REGION_BOM diff --git a/terraform/oci/kconfigs/regions/Kconfig.ca-montreal-1 b/terraform/oci/kconfigs/regions/Kconfig.ca-montreal-1 deleted file mode 100644 index ce71f531e..000000000 --- a/terraform/oci/kconfigs/regions/Kconfig.ca-montreal-1 +++ /dev/null @@ -1,28 +0,0 @@ -if TERRAFORM_OCI_REGION_YUL - -config TERRAFORM_OCI_REGION - string - output yaml - default "ca-montreal-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_YUL_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_YUL_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_YUL_AD1 - -endif # TERRAFORM_OCI_REGION_YUL diff --git a/terraform/oci/kconfigs/regions/Kconfig.ca-toronto-1 b/terraform/oci/kconfigs/regions/Kconfig.ca-toronto-1 deleted file mode 100644 index 16053e94e..000000000 --- a/terraform/oci/kconfigs/regions/Kconfig.ca-toronto-1 +++ /dev/null @@ -1,28 +0,0 @@ -if TERRAFORM_OCI_REGION_YYZ - -config TERRAFORM_OCI_REGION - string - output yaml - default "ca-toronto-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_YYZ_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_YYZ_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_YYZ_AD1 - -endif # TERRAFORM_OCI_REGION_YYZ diff --git a/terraform/oci/kconfigs/regions/Kconfig.us-ashburn-1 b/terraform/oci/kconfigs/regions/Kconfig.us-ashburn-1 deleted file mode 100644 index 9aa4d2714..000000000 --- a/terraform/oci/kconfigs/regions/Kconfig.us-ashburn-1 +++ /dev/null @@ -1,36 +0,0 @@ -if TERRAFORM_OCI_REGION_IAD - -config TERRAFORM_OCI_REGION - string - output yaml - default "us-ashburn-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_IAD_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_IAD_AD1 - bool "1" - -config TERRAFORM_OCI_REGION_IAD_AD2 - bool "2" - -config TERRAFORM_OCI_REGION_IAD_AD3 - bool "3" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_IAD_AD1 - default 2 if TERRAFORM_OCI_REGION_IAD_AD2 - default 3 if TERRAFORM_OCI_REGION_IAD_AD3 - -endif # TERRAFORM_OCI_REGION_IAD diff --git a/terraform/oci/kconfigs/regions/Kconfig.us-chicago-1 b/terraform/oci/kconfigs/regions/Kconfig.us-chicago-1 deleted file mode 100644 index 19c3b50c2..000000000 --- a/terraform/oci/kconfigs/regions/Kconfig.us-chicago-1 +++ /dev/null @@ -1,36 +0,0 @@ -if TERRAFORM_OCI_REGION_ORD - -config TERRAFORM_OCI_REGION - string - output yaml - default "us-chicago-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_ORD_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_ORD_AD1 - bool "1" - -config TERRAFORM_OCI_REGION_ORD_AD2 - bool "2" - -config TERRAFORM_OCI_REGION_ORD_AD3 - bool "3" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_ORD_AD1 - default 2 if TERRAFORM_OCI_REGION_ORD_AD2 - default 3 if TERRAFORM_OCI_REGION_ORD_AD3 - -endif # TERRAFORM_OCI_REGION_ORD diff --git a/terraform/oci/kconfigs/regions/Kconfig.us-phoenix-1 b/terraform/oci/kconfigs/regions/Kconfig.us-phoenix-1 deleted file mode 100644 index eb8021191..000000000 --- a/terraform/oci/kconfigs/regions/Kconfig.us-phoenix-1 +++ /dev/null @@ -1,36 +0,0 @@ -if TERRAFORM_OCI_REGION_PHX - -config TERRAFORM_OCI_REGION - string - output yaml - default "us-phoenix-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_PHX_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_PHX_AD1 - bool "1" - -config TERRAFORM_OCI_REGION_PHX_AD2 - bool "2" - -config TERRAFORM_OCI_REGION_PHX_AD3 - bool "3" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_PHX_AD1 - default 2 if TERRAFORM_OCI_REGION_PHX_AD2 - default 3 if TERRAFORM_OCI_REGION_PHX_AD3 - -endif # TERRAFORM_OCI_REGION_PHX diff --git a/terraform/oci/kconfigs/regions/Kconfig.us-sanjose-1 b/terraform/oci/kconfigs/regions/Kconfig.us-sanjose-1 deleted file mode 100644 index 69b4035f2..000000000 --- a/terraform/oci/kconfigs/regions/Kconfig.us-sanjose-1 +++ /dev/null @@ -1,28 +0,0 @@ -if TERRAFORM_OCI_REGION_SJC - -config TERRAFORM_OCI_REGION - string - output yaml - default "us-sanjose-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_SJC_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_SJC_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_SJC_AD1 - -endif # TERRAFORM_OCI_REGION_SJC From b473b39e5ce629c31025ab4960154d02c4d5a16a Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sat, 18 Oct 2025 17:32:37 -0400 Subject: [PATCH 03/11] terraform/oci: Generate Kconfig.locations dynamically Duplicate the same functionality as is already provided for AWS. The generated region menu includes only the regions to which the user tenancy is subscribed. Unfortunately the region friend names (ie, city name, etc.) are not available through OCI's API. Therefore a separate file is maintained with the mapping of region codes to human-friendly region descriptions. The region_friendly_names.yml file contains detailed inline documentation for this process. No script is provided because the information comes from documentation, not the API. However, updating the dictionary can be handled by an AI if desired. Generated-by: Claude AI Signed-off-by: Chuck Lever --- terraform/oci/scripts/ad.j2 | 42 ++ terraform/oci/scripts/gen_kconfig_location | 476 ++++++++++++++++++ .../oci/scripts/region_friendly_names.yml | 94 ++++ terraform/oci/scripts/regions.j2 | 24 + 4 files changed, 636 insertions(+) create mode 100644 terraform/oci/scripts/ad.j2 create mode 100755 terraform/oci/scripts/gen_kconfig_location create mode 100644 terraform/oci/scripts/region_friendly_names.yml create mode 100644 terraform/oci/scripts/regions.j2 diff --git a/terraform/oci/scripts/ad.j2 b/terraform/oci/scripts/ad.j2 new file mode 100644 index 000000000..8ff062ec6 --- /dev/null +++ b/terraform/oci/scripts/ad.j2 @@ -0,0 +1,42 @@ +if TERRAFORM_OCI_REGION_{{ region_code }} + +config TERRAFORM_OCI_REGION + string + output yaml + default "{{ region_name }}" + +choice + prompt "Availability Domain" + default TERRAFORM_OCI_REGION_{{ region_code }}_AD{{ ads[0]['number'] if ads else '1' }} + help + The number of the Availability Domain. This number + corresponds to the integer at the end of the Availability + Domain name. + + The OCI Fault Domain is chosen automatically. + +{% if ads %} +{% for ad in ads %} +config TERRAFORM_OCI_REGION_{{ region_code }}_AD{{ ad['number'] }} + bool "{{ ad['number'] }}" + +{% endfor %} +{% else %} +config TERRAFORM_OCI_REGION_{{ region_code }}_AD1 + bool "1" + +{% endif %} +endchoice + +config TERRAFORM_OCI_AD_NUMBER + int + output yaml +{% if ads %} +{% for ad in ads %} + default {{ ad['number'] }} if TERRAFORM_OCI_REGION_{{ region_code }}_AD{{ ad['number'] }} +{% endfor %} +{% else %} + default 1 +{% endif %} + +endif # TERRAFORM_OCI_REGION_{{ region_code }} diff --git a/terraform/oci/scripts/gen_kconfig_location b/terraform/oci/scripts/gen_kconfig_location new file mode 100755 index 000000000..17ec8266c --- /dev/null +++ b/terraform/oci/scripts/gen_kconfig_location @@ -0,0 +1,476 @@ +#!/usr/bin/env python3 +# ex: set filetype=python: + +""" +Retrieve region and availability domain information from OCI. Use +it to construct the "locations" Kconfig menu. + +Region Friendly Names: + Region friendly names (e.g., "US Midwest (Chicago)") are maintained + in the region_friendly_names.yml file in the same directory as this + script. This makes it easier to update the friendly names when Oracle + adds new regions or when you want to customize the display names. + + To update region friendly names: + 1. Edit terraform/oci/scripts/region_friendly_names.yml + 2. Add or modify entries following the existing format + 3. Run this script to regenerate Kconfig.location + + The YAML file contains detailed instructions for how to find and add + new region information. If a region is not found in the YAML file, + the script will auto-generate a friendly name from the region identifier. + +Usage: + # Generate complete Kconfig.location file + ./gen_kconfig_location > ../kconfigs/Kconfig.location + + # List all available regions + ./gen_kconfig_location --regions + + # Get details for a specific region + ./gen_kconfig_location us-chicago-1 +""" + +import os +import sys +import argparse + +import oci +from oci.exceptions import ServiceError + +from oci_common import ( + get_default_region, + get_jinja2_environment, + load_yaml_config, + create_identity_client, + get_oci_config, +) + + +def load_region_friendly_names(): + """ + Load region friendly names from the YAML configuration file. + + The friendly names are maintained in region_friendly_names.yml to make + it easier to update when Oracle adds new regions. The YAML file contains + the canonical mapping from OCI region identifiers to human-readable + display names. + + To update the friendly names: + 1. Edit terraform/oci/scripts/region_friendly_names.yml + 2. Add or modify entries following the existing format + 3. Regenerate Kconfig.location by running this script + + See region_friendly_names.yml for detailed update instructions. + + Returns: + dict: Dictionary mapping region names to friendly display names + """ + return load_yaml_config("region_friendly_names.yml") + + +def get_region_code(regions, region_name): + """ + Get the 3-letter code for a region by looking it up in the regions list. + + Args: + regions (list): List of region dictionaries + region_name (str): OCI region name (e.g., 'us-chicago-1') + + Returns: + str: 3-letter code (e.g., 'ORD') from OCI's official region_key + """ + for region in regions: + if region["region_name"] == region_name: + return region["region_code"] + + # Fallback if region not found (should not happen in normal operation) + # Take first 3 letters of the location part + parts = region_name.split("-") + if len(parts) >= 2: + return parts[1][:3].upper() + return region_name[:3].upper() + + +def get_region_friendly_name(region_name, friendly_names=None): + """ + Get a friendly display name for a region. + + Region friendly names are loaded from region_friendly_names.yml. + If a region is not found in the YAML file, an auto-generated name + is returned. + + The YAML file can be updated to add new regions or customize names. + See load_region_friendly_names() for update instructions. + + Args: + region_name (str): OCI region name (e.g., 'us-chicago-1') + friendly_names (dict): Optional pre-loaded friendly names dict. + If None, names will be loaded from YAML. + + Returns: + str: Friendly name (e.g., 'US Midwest (Chicago)') + """ + # Load friendly names from YAML if not provided + if friendly_names is None: + friendly_names = load_region_friendly_names() + + # Look up the friendly name in the loaded data + if region_name in friendly_names: + return friendly_names[region_name] + + # Auto-generate if not in map + parts = region_name.split("-") + if len(parts) >= 2: + location = parts[1].title() + return f"{parts[0].upper()} ({location})" + return region_name + + +def get_all_regions(): + """ + Retrieve the list of all OCI regions in the OC1 realm. + + Returns all regions available in OCI and marks which ones the tenancy + is subscribed to, making the subscription status field meaningful. + + Returns: + list: sorted list of dictionaries each containing a region + """ + try: + config = get_oci_config() + identity = create_identity_client() + + # Get all regions in the OC1 realm + all_regions = identity.list_regions().data + + # Get region subscriptions to determine which regions are subscribed + region_subscriptions = identity.list_region_subscriptions( + config["tenancy"] + ).data + + # Create a mapping of subscribed regions for quick lookup + subscribed_regions = {} + home_region = None + for subscription in region_subscriptions: + subscribed_regions[subscription.region_name] = subscription.status + if subscription.is_home_region: + home_region = subscription.region_name + + # Load friendly names once for efficiency + friendly_names = load_region_friendly_names() + + regions = [] + for region in all_regions: + region_name = region.name + is_subscribed = region_name in subscribed_regions + regions.append( + { + "region_name": region_name, + "region_code": region.key, + "friendly_name": get_region_friendly_name( + region_name, friendly_names + ), + "status": subscribed_regions.get(region_name, "NOT_SUBSCRIBED"), + "is_home_region": region_name == home_region, + "is_subscribed": is_subscribed, + } + ) + + return sorted(regions, key=lambda x: x["region_name"]) + + except oci.exceptions.ConfigFileNotFound: + print( + "Error: OCI config file not found. Please configure OCI CLI.", + file=sys.stderr, + ) + return [] + except Exception as e: + print(f"Error retrieving OCI regions: {e}", file=sys.stderr) + return [] + + +def get_region_info(regions, region_name, quiet=False): + """ + Get detailed information about a specific region including availability domains. + + Args: + regions (list): List of all regions + region_name (str): OCI region name (e.g., 'us-chicago-1') + quiet (bool): Suppress debug messages + + Returns: + dict: Dictionary containing region information and availability domains + """ + try: + if not quiet: + print(f"Querying information for region {region_name}...", file=sys.stderr) + + region_info = next( + filter(lambda x: x["region_name"] == region_name, regions), None + ) + if not region_info: + if not quiet: + print(f"Region {region_name} was not found", file=sys.stderr) + return None + + # Create identity client for the specific region + identity = create_identity_client(region_name) + config = get_oci_config(region_name) + + # List availability domains + availability_domains = identity.list_availability_domains( + config["tenancy"] + ).data + + ad_list = [] + for ad in availability_domains: + # Extract AD number from name (e.g., "MhqG:US-CHICAGO-1-AD-1" -> 1) + ad_name = ad.name + ad_number = ad_name.split("-")[-1] if "-" in ad_name else "1" + + ad_info = { + "name": ad_name, + "number": ad_number, + } + ad_list.append(ad_info) + + result = { + "region_name": region_info["region_name"], + "region_code": region_info["region_code"], + "friendly_name": region_info["friendly_name"], + "status": region_info.get("status", "READY"), + "is_home_region": region_info.get("is_home_region", False), + "availability_domain_count": len(ad_list), + "availability_domains": sorted(ad_list, key=lambda x: x["number"]), + } + + if not quiet: + print( + f"Found {len(ad_list)} availability domains in {region_name}", + file=sys.stderr, + ) + + return result + + except ServiceError as e: + print(f"OCI API Error: {e.message}", file=sys.stderr) + return None + except Exception as e: + print(f"Unexpected error: {e}", file=sys.stderr) + return None + + +def output_region_kconfig(region_info): + """Output region information in Kconfig format.""" + environment = get_jinja2_environment() + template = environment.get_template("ad.j2") + print( + template.render( + region_code=region_info["region_code"], + region_name=region_info["region_name"], + ads=region_info["availability_domains"], + ) + ) + + +def output_region_raw(region_info, quiet=False): + """Output region information in table format.""" + if not quiet: + print(f"Region: {region_info['region_name']}") + print(f"Code: {region_info['region_code']}") + print(f"Friendly Name: {region_info['friendly_name']}") + print(f"Status: {region_info['status']}") + print(f"Home Region: {region_info['is_home_region']}") + print(f"Availability Domains: {region_info['availability_domain_count']}") + + print(f"{'AD Name':<40} {'AD Number':<10}") + print("-" * 50) + + for ad in region_info["availability_domains"]: + print(f"{ad['name']:<40} {ad['number']:<10}") + + +def output_regions_kconfig(regions): + """Output available regions in kconfig format.""" + environment = get_jinja2_environment() + template = environment.get_template("regions.j2") + print( + template.render( + default_region=get_region_code(regions, get_default_region()), + regions=regions, + ) + ) + + +def output_regions_raw(regions, quiet=False): + """Output available regions in table format.""" + if not quiet: + print(f"Available OCI regions ({len(regions)}):\n") + print(f"{'Region Name':<20} {'Code':<8} {'Status':<12} {'Home':<8}") + print("-" * 50) + + for region in regions: + status = region.get("status", "Unknown") + is_home = "Yes" if region.get("is_home_region", False) else "No" + print( + f"{region['region_name']:<20} {region['region_code']:<8} {status:<12} {is_home:<8}" + ) + + +def output_locations_kconfig(regions, include_unsubscribed=False): + """ + Output the complete locations menu in Kconfig format. + + Args: + regions (list): List of all regions + include_unsubscribed (bool): Include non-subscribed regions in output + """ + environment = get_jinja2_environment() + + # Filter to subscribed regions only unless --include-unsubscribed is specified + # (can't deploy to non-subscribed regions, so they shouldn't be in Kconfig by default) + if include_unsubscribed: + kconfig_regions = regions + else: + kconfig_regions = [r for r in regions if r.get("is_subscribed", False)] + + # Output the region choice menu + template = environment.get_template("regions.j2") + print( + template.render( + default_region=get_region_code(kconfig_regions, get_default_region()), + regions=kconfig_regions, + ) + ) + + # Output each region's availability domain configuration + # Note: Can only query AD info for subscribed regions + template = environment.get_template("ad.j2") + for region in kconfig_regions: + # For non-subscribed regions, create a default AD configuration + # (API will fail with auth error for non-subscribed regions) + if not region.get("is_subscribed", True): + # Default to 1 availability domain for unsubscribed regions + region_info = { + "region_name": region["region_name"], + "region_code": region["region_code"], + "friendly_name": region["friendly_name"], + "status": region.get("status", "NOT_SUBSCRIBED"), + "is_home_region": False, + "availability_domain_count": 1, + "availability_domains": [ + { + "name": f"{region['region_name'].upper()}-AD-1", + "number": "1", + } + ], + } + else: + region_info = get_region_info(kconfig_regions, region["region_name"], True) + + if region_info: + print() + print( + template.render( + region_code=region_info["region_code"], + region_name=region_info["region_name"], + ads=region_info["availability_domains"], + ) + ) + + # Output the compartment name configuration + print() + print("config TERRAFORM_OCI_COMPARTMENT_NAME") + print('\tstring "OCI compartment name"') + print("\toutput yaml") + print("\thelp") + print("\t The compartment name where your instances are to be created.") + + +def parse_arguments(): + """Parse command line arguments.""" + parser = argparse.ArgumentParser( + description="Get OCI region and availability domain information", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + python %(prog)s --regions + python %(prog)s us-chicago-1 + python %(prog)s ap-mumbai-1 --quiet + python %(prog)s --include-unsubscribed > kconfigs/Kconfig.location + """, + ) + parser.add_argument( + "region_name", + nargs="?", + help="OCI region name (e.g., us-chicago-1, ap-mumbai-1)", + ) + + parser.add_argument( + "--format", + "-f", + choices=["raw", "kconfig"], + default="kconfig", + help="Output format (default: kconfig)", + ) + parser.add_argument( + "--quiet", "-q", action="store_true", help="Suppress informational messages" + ) + parser.add_argument( + "--regions", action="store_true", help="List all available OCI regions" + ) + parser.add_argument( + "--include-unsubscribed", + action="store_true", + help="Include non-subscribed regions in Kconfig output (default: subscribed only)", + ) + return parser.parse_args() + + +def main(): + """Main function to run the program.""" + args = parse_arguments() + + if not args.quiet: + print("Fetching list of OCI region subscriptions...", file=sys.stderr) + regions = get_all_regions() + if not regions: + sys.exit(1) + + if args.regions: + if args.format == "kconfig": + output_regions_kconfig(regions) + else: + output_regions_raw(regions, args.quiet) + return + + if args.region_name: + if not args.quiet: + print( + f"Fetching information for region {args.region_name}...", + file=sys.stderr, + ) + + region_info = get_region_info(regions, args.region_name, args.quiet) + if region_info: + if args.format == "kconfig": + output_region_kconfig(region_info) + else: + output_region_raw(region_info, args.quiet) + else: + print( + f"Could not retrieve information for region '{args.region_name}'.", + file=sys.stderr, + ) + print( + "Try running with --regions to see available regions.", file=sys.stderr + ) + sys.exit(1) + return + + output_locations_kconfig(regions, args.include_unsubscribed) + + +if __name__ == "__main__": + main() diff --git a/terraform/oci/scripts/region_friendly_names.yml b/terraform/oci/scripts/region_friendly_names.yml new file mode 100644 index 000000000..1e61f3bff --- /dev/null +++ b/terraform/oci/scripts/region_friendly_names.yml @@ -0,0 +1,94 @@ +# OCI Region Friendly Names +# +# This file maps OCI region identifiers to human-friendly display names +# used in the kdevops Kconfig menus. +# +# Canonical Source: +# https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm +# (Official Oracle Cloud Infrastructure Regions and Availability Domains page) +# +# IMPORTANT: This URL points to HTML documentation, not an API. The +# documentation format and content can change at any time. Use the OCI +# CLI for programmatic access: oci iam region list +# +# Last Verified: 2025-10-19 +# Total Regions: 41 +# +# Format: +# region-identifier: "Friendly Display Name" +# +# Ordering Requirement: +# The regions below are maintained in the same order as they appear in +# Oracle's official documentation table. This makes verification easier +# and provides a consistent ordering for the generated Kconfig. +# +# How to update this file: +# ----------------------- +# When Oracle adds new regions or you want to customize the display names: +# +# 1. Find the official region identifier from OCI: +# $ oci iam region-subscription list +# +# 2. Look up the region's friendly name from Oracle's documentation: +# https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm +# +# 3. Add a new entry following the format above. Use the pattern: +# " ()" +# +# Examples: +# - "US West (Phoenix)" +# - "Europe (Frankfurt)" +# - "Asia Pacific (Tokyo)" +# +# 4. Maintain the same order as shown in Oracle's documentation table. +# +# 5. Update the "Last Verified" date and "Total Regions" count above. +# +# 6. After updating this file, regenerate the Kconfig.location file: +# $ cd terraform/oci/scripts +# $ ./gen_kconfig_location > ../kconfigs/Kconfig.location +# +# Region Mappings: +# ---------------- + +ap-sydney-1: "Australia East (Sydney)" +ap-melbourne-1: "Australia Southeast (Melbourne)" +sa-saopaulo-1: "Brazil East (Sao Paulo)" +sa-vinhedo-1: "Brazil Southeast (Vinhedo)" +ca-montreal-1: "Canada Southeast (Montreal)" +ca-toronto-1: "Canada Southeast (Toronto)" +sa-santiago-1: "Chile Central (Santiago)" +sa-valparaiso-1: "Chile West (Valparaiso)" +sa-bogota-1: "Colombia Central (Bogota)" +eu-paris-1: "France Central (Paris)" +eu-marseille-1: "France South (Marseille)" +eu-frankfurt-1: "Germany Central (Frankfurt)" +ap-hyderabad-1: "India South (Hyderabad)" +ap-mumbai-1: "India West (Mumbai)" +ap-batam-1: "Indonesia North (Batam)" +il-jerusalem-1: "Israel Central (Jerusalem)" +eu-milan-1: "Italy Northwest (Milan)" +ap-osaka-1: "Japan Central (Osaka)" +ap-tokyo-1: "Japan East (Tokyo)" +mx-queretaro-1: "Mexico Central (Queretaro)" +mx-monterrey-1: "Mexico Northeast (Monterrey)" +eu-amsterdam-1: "Netherlands Northwest (Amsterdam)" +me-riyadh-1: "Saudi Arabia Central (Riyadh)" +me-jeddah-1: "Saudi Arabia West (Jeddah)" +eu-jovanovac-1: "Serbia Central (Jovanovac)" +ap-singapore-1: "Singapore (Singapore)" +ap-singapore-2: "Singapore West (Singapore)" +af-johannesburg-1: "South Africa Central (Johannesburg)" +ap-seoul-1: "South Korea Central (Seoul)" +ap-chuncheon-1: "South Korea North (Chuncheon)" +eu-madrid-1: "Spain Central (Madrid)" +eu-stockholm-1: "Sweden Central (Stockholm)" +eu-zurich-1: "Switzerland North (Zurich)" +me-abudhabi-1: "UAE Central (Abu Dhabi)" +me-dubai-1: "UAE East (Dubai)" +uk-london-1: "UK South (London)" +uk-cardiff-1: "UK West (Newport)" +us-ashburn-1: "US East (Ashburn)" +us-chicago-1: "US Midwest (Chicago)" +us-phoenix-1: "US West (Phoenix)" +us-sanjose-1: "US West (San Jose)" diff --git a/terraform/oci/scripts/regions.j2 b/terraform/oci/scripts/regions.j2 new file mode 100644 index 000000000..cc1198853 --- /dev/null +++ b/terraform/oci/scripts/regions.j2 @@ -0,0 +1,24 @@ +choice + prompt "OCI Region" + default TERRAFORM_OCI_REGION_{{ default_region }} + help + A region is a collection of geographically co-located data + centers that share data and hardware resources. For more + information: + + https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm + + Using this menu, select the region in which you wish to + deploy your kdevops resources. Your tenancy must be + subscribed to the region you select here. Use: + + $ oci iam region-subscription list + + for a list of regions to which your tenancy subscribes. + +{% for region in regions %} +config TERRAFORM_OCI_REGION_{{ region['region_code'] }} + bool "{{ region['friendly_name'] }}" + +{% endfor %} +endchoice From b72c2d04a263a886667284afc4b511fc33f1d5f6 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 21 Oct 2025 15:46:13 -0400 Subject: [PATCH 04/11] generate_cloud_configs.py: Add dynamic menu generation for OCI Start introducing OCI support to the dynamic menu generate targets by adding the location menu to the cloud_configs.py script. This support is intended to work like the reference implementation under terraform/lambdalabs/ Signed-off-by: Chuck Lever --- .gitignore | 1 + scripts/dynamic-cloud-kconfig.Makefile | 29 ++- scripts/generate_cloud_configs.py | 53 ++++- terraform/oci/Kconfig | 8 +- terraform/oci/kconfigs/Kconfig.location | 304 ------------------------ 5 files changed, 84 insertions(+), 311 deletions(-) delete mode 100644 terraform/oci/kconfigs/Kconfig.location diff --git a/.gitignore b/.gitignore index 251a5ce53..ad6202208 100644 --- a/.gitignore +++ b/.gitignore @@ -122,6 +122,7 @@ terraform/aws/kconfigs/Kconfig.instance.generated terraform/aws/kconfigs/Kconfig.location.generated terraform/aws/scripts/__pycache__/ +terraform/oci/kconfigs/Kconfig.location.generated terraform/oci/scripts/__pycache__/ .cloud.initialized diff --git a/scripts/dynamic-cloud-kconfig.Makefile b/scripts/dynamic-cloud-kconfig.Makefile index d3225076f..07dc578a7 100644 --- a/scripts/dynamic-cloud-kconfig.Makefile +++ b/scripts/dynamic-cloud-kconfig.Makefile @@ -20,8 +20,14 @@ AWS_KCONFIG_LOCATION := $(AWS_KCONFIG_DIR)/Kconfig.location.generated AWS_KCONFIGS := $(AWS_KCONFIG_AMI) $(AWS_KCONFIG_INSTANCE) $(AWS_KCONFIG_LOCATION) +# OCI dynamic configuration +OCI_KCONFIG_DIR := terraform/oci/kconfigs +OCI_KCONFIG_LOCATION := $(OCI_KCONFIG_DIR)/Kconfig.location.generated + +OCI_KCONFIGS := $(OCI_KCONFIG_LOCATION) + # Add generated files to mrproper clean list -KDEVOPS_MRPROPER += $(LAMBDALABS_KCONFIGS) $(AWS_KCONFIGS) +KDEVOPS_MRPROPER += $(LAMBDALABS_KCONFIGS) $(AWS_KCONFIGS) $(OCI_KCONFIGS) # Touch Lambda Labs generated files so Kconfig can source them # This ensures the files exist (even if empty) before Kconfig runs @@ -32,7 +38,11 @@ dynamic_lambdalabs_kconfig_touch: dynamic_aws_kconfig_touch: $(Q)touch $(AWS_KCONFIGS) -DYNAMIC_KCONFIG += dynamic_lambdalabs_kconfig_touch dynamic_aws_kconfig_touch +# Touch OCI generated files so Kconfig can source them +dynamic_oci_kconfig_touch: + $(Q)touch $(OCI_KCONFIGS) + +DYNAMIC_KCONFIG += dynamic_lambdalabs_kconfig_touch dynamic_aws_kconfig_touch dynamic_oci_kconfig_touch # Lambda Labs targets use --provider argument for efficiency cloud-config-lambdalabs: @@ -42,6 +52,10 @@ cloud-config-lambdalabs: cloud-config-aws: $(Q)python3 scripts/generate_cloud_configs.py --provider aws +# OCI targets use --provider argument for efficiency +cloud-config-oci: + $(Q)python3 scripts/generate_cloud_configs.py --provider oci + # Clean Lambda Labs generated files clean-cloud-config-lambdalabs: $(Q)rm -f $(LAMBDALABS_KCONFIGS) @@ -50,7 +64,11 @@ clean-cloud-config-lambdalabs: clean-cloud-config-aws: $(Q)rm -f $(AWS_KCONFIGS) -DYNAMIC_CLOUD_KCONFIG += cloud-config-lambdalabs cloud-config-aws +# Clean OCI generated files +clean-cloud-config-oci: + $(Q)rm -f $(OCI_KCONFIGS) + +DYNAMIC_CLOUD_KCONFIG += cloud-config-lambdalabs cloud-config-aws cloud-config-oci cloud-config-help: @echo "Cloud-specific dynamic kconfig targets:" @@ -72,4 +90,7 @@ cloud-list-all: $(Q)chmod +x scripts/cloud_list_all.sh $(Q)scripts/cloud_list_all.sh -PHONY += cloud-config cloud-config-lambdalabs cloud-config-aws clean-cloud-config clean-cloud-config-lambdalabs clean-cloud-config-aws cloud-config-help cloud-list-all +PHONY += cloud-config clean-cloud-config cloud-config-help cloud-list-all +PHONY += cloud-config-aws clean-cloud-config-aws +PHONY += cloud-config-lambdalabs clean-cloud-config-lambdalabs +PHONY += cloud-config-oci clean-cloud-config-oci diff --git a/scripts/generate_cloud_configs.py b/scripts/generate_cloud_configs.py index 8c039f534..e9953c42e 100755 --- a/scripts/generate_cloud_configs.py +++ b/scripts/generate_cloud_configs.py @@ -147,6 +147,50 @@ def generate_aws_kconfig() -> bool: return all_success +def generate_oci_kconfig() -> bool: + """ + Generate OCI Kconfig files. + Returns True on success, False on failure. + """ + script_dir = os.path.dirname(os.path.abspath(__file__)) + project_root = os.path.dirname(script_dir) + oci_scripts_dir = os.path.join(project_root, "terraform", "oci", "scripts") + oci_kconfigs_dir = os.path.join(project_root, "terraform", "oci", "kconfigs") + + # Define the script-to-output mapping + scripts_to_run = [ + ("gen_kconfig_location", "Kconfig.location.generated"), + ] + + all_success = True + + for script_name, kconfig_file in scripts_to_run: + script_path = os.path.join(oci_scripts_dir, script_name) + output_path = os.path.join(oci_kconfigs_dir, kconfig_file) + + # Run the script and capture its output + result = subprocess.run( + [script_path], + capture_output=True, + text=True, + check=False, + ) + + if result.returncode == 0: + # Write the output to the corresponding Kconfig file + try: + with open(output_path, "w") as f: + f.write(result.stdout) + except IOError as e: + print(f"Error writing {kconfig_file}: {e}", file=sys.stderr) + all_success = False + else: + print(f"Error running {script_name}: {result.stderr}", file=sys.stderr) + all_success = False + + return all_success + + def process_lambdalabs(): """Process Lambda Labs configuration.""" # Generate Kconfig files first @@ -186,8 +230,13 @@ def process_gce(): def process_oci(): - """Process OCI configuration (placeholder).""" - print("⚠ OCI: Dynamic configuration not yet implemented") + """Process OCI configuration.""" + kconfig_generated = generate_oci_kconfig() + if kconfig_generated: + print("✓ OCI: Kconfig files generated successfully") + else: + print("⚠ OCI: Failed to generate Kconfig files - using defaults") + print() def main(): diff --git a/terraform/oci/Kconfig b/terraform/oci/Kconfig index 566442868..38531b08e 100644 --- a/terraform/oci/Kconfig +++ b/terraform/oci/Kconfig @@ -1,7 +1,13 @@ +# OCI provider configuration +# +# This file sources dynamically Kconfig menus. Run +# 'make cloud-config-oci' to populate the .generated files +# with current OCI resource information. + if TERRAFORM_OCI menu "Resource location" -source "terraform/oci/kconfigs/Kconfig.location" +source "terraform/oci/kconfigs/Kconfig.location.generated" endmenu menu "Compute" source "terraform/oci/kconfigs/Kconfig.compute" diff --git a/terraform/oci/kconfigs/Kconfig.location b/terraform/oci/kconfigs/Kconfig.location deleted file mode 100644 index 1d7de2868..000000000 --- a/terraform/oci/kconfigs/Kconfig.location +++ /dev/null @@ -1,304 +0,0 @@ -choice - prompt "OCI Region" - default TERRAFORM_OCI_REGION_ORD - help - A region is a collection of geographically co-located data - centers that share data and hardware resources. For more - information: - - https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm - - Using this menu, select the region in which you wish to - deploy your kdevops resources. Your tenancy must be - subscribed to the region you select here. Use: - - $ oci iam region-subscription list - - for a list of regions to which your tenancy subscribes. - -config TERRAFORM_OCI_REGION_HYD - bool "India South (Hyderabad)" - -config TERRAFORM_OCI_REGION_BOM - bool "India West (Mumbai)" - -config TERRAFORM_OCI_REGION_YUL - bool "Canada Southeast (Montreal)" - -config TERRAFORM_OCI_REGION_YYZ - bool "Canada Southeast (Toronto)" - -config TERRAFORM_OCI_REGION_IAD - bool "US East (Ashburn)" - -config TERRAFORM_OCI_REGION_ORD - bool "US Midwest (Chicago)" - -config TERRAFORM_OCI_REGION_PHX - bool "US West (Phoenix)" - -config TERRAFORM_OCI_REGION_SJC - bool "US West (San Jose)" - -endchoice - -if TERRAFORM_OCI_REGION_HYD - -config TERRAFORM_OCI_REGION - string - output yaml - default "ap-hyderabad-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_HYD_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_HYD_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_HYD_1_AD1 - -endif # TERRAFORM_OCI_REGION_HYD_1 - -if TERRAFORM_OCI_REGION_BOM - -config TERRAFORM_OCI_REGION - string - output yaml - default "ap-mumbai-1" -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_BOM_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_BOM_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_BOM_AD1 - -endif # TERRAFORM_OCI_REGION_BOM - -if TERRAFORM_OCI_REGION_YUL - -config TERRAFORM_OCI_REGION - string - output yaml - default "ca-montreal-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_YUL_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_YUL_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_YUL_AD1 - -endif # TERRAFORM_OCI_REGION_YUL - -if TERRAFORM_OCI_REGION_YYZ - -config TERRAFORM_OCI_REGION - string - output yaml - default "ca-toronto-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_YYZ_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_YYZ_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_YYZ_AD1 - -endif # TERRAFORM_OCI_REGION_YYZ - -if TERRAFORM_OCI_REGION_IAD - -config TERRAFORM_OCI_REGION - string - output yaml - default "us-ashburn-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_IAD_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_IAD_AD1 - bool "1" - -config TERRAFORM_OCI_REGION_IAD_AD2 - bool "2" - -config TERRAFORM_OCI_REGION_IAD_AD3 - bool "3" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_IAD_AD1 - default 2 if TERRAFORM_OCI_REGION_IAD_AD2 - default 3 if TERRAFORM_OCI_REGION_IAD_AD3 - -endif # TERRAFORM_OCI_REGION_IAD - -if TERRAFORM_OCI_REGION_ORD - -config TERRAFORM_OCI_REGION - string - output yaml - default "us-chicago-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_ORD_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_ORD_AD1 - bool "1" - -config TERRAFORM_OCI_REGION_ORD_AD2 - bool "2" - -config TERRAFORM_OCI_REGION_ORD_AD3 - bool "3" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_ORD_AD1 - default 2 if TERRAFORM_OCI_REGION_ORD_AD2 - default 3 if TERRAFORM_OCI_REGION_ORD_AD3 - -endif # TERRAFORM_OCI_REGION_ORD - -if TERRAFORM_OCI_REGION_PHX - -config TERRAFORM_OCI_REGION - string - output yaml - default "us-phoenix-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_PHX_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_PHX_AD1 - bool "1" - -config TERRAFORM_OCI_REGION_PHX_AD2 - bool "2" - -config TERRAFORM_OCI_REGION_PHX_AD3 - bool "3" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_PHX_AD1 - default 2 if TERRAFORM_OCI_REGION_PHX_AD2 - default 3 if TERRAFORM_OCI_REGION_PHX_AD3 - -endif # TERRAFORM_OCI_REGION_PHX - -if TERRAFORM_OCI_REGION_SJC - -config TERRAFORM_OCI_REGION - string - output yaml - default "us-sanjose-1" - -choice - prompt "Availability Domain" - default TERRAFORM_OCI_REGION_SJC_AD1 - help - The number of the Availability Domain. This number - corresponds to the integer at the end of the Availability - Domain name. - - The OCI Fault Domain is chosen automatically. - -config TERRAFORM_OCI_REGION_SJC_AD1 - bool "1" - -endchoice - -config TERRAFORM_OCI_AD_NUMBER - int - output yaml - default 1 if TERRAFORM_OCI_REGION_SJC_AD1 - -endif # TERRAFORM_OCI_REGION_SJC - -config TERRAFORM_OCI_COMPARTMENT_NAME - string "OCI compartment name" - output yaml - help - The compartment name where your instances are to be created. From 3087928af6229fe0bf65d54a4f6b68e2ab3156c5 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sun, 19 Oct 2025 11:54:19 -0400 Subject: [PATCH 05/11] terraform/oci: Split Kconfig.compute into two files I'm about to add a script to dynamically generate the shape menu and another script to dynamically generate the OS image menu. It will be easier if these menus were in separate files. Signed-off-by: Chuck Lever --- terraform/oci/Kconfig | 5 ++- terraform/oci/kconfigs/Kconfig.image | 38 ++++++++++++++++++ .../{Kconfig.compute => Kconfig.shape} | 39 ------------------- 3 files changed, 42 insertions(+), 40 deletions(-) create mode 100644 terraform/oci/kconfigs/Kconfig.image rename terraform/oci/kconfigs/{Kconfig.compute => Kconfig.shape} (54%) diff --git a/terraform/oci/Kconfig b/terraform/oci/Kconfig index 38531b08e..d2c00c428 100644 --- a/terraform/oci/Kconfig +++ b/terraform/oci/Kconfig @@ -10,7 +10,10 @@ menu "Resource location" source "terraform/oci/kconfigs/Kconfig.location.generated" endmenu menu "Compute" -source "terraform/oci/kconfigs/Kconfig.compute" +comment "Shape selection" +source "terraform/oci/kconfigs/Kconfig.shape" +comment "OS image selection" +source "terraform/oci/kconfigs/Kconfig.image" endmenu menu "Storage" source "terraform/oci/kconfigs/Kconfig.storage" diff --git a/terraform/oci/kconfigs/Kconfig.image b/terraform/oci/kconfigs/Kconfig.image new file mode 100644 index 000000000..b67165db3 --- /dev/null +++ b/terraform/oci/kconfigs/Kconfig.image @@ -0,0 +1,38 @@ +choice + prompt "Distribution" + default TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX + help + Select the Linux distribution to install on each instance. + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX + bool "Oracle Linux" + help + Select this if you want to use a release of Oracle Linux + as the operating system in your instances. + +config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU + bool "Ubuntu" + help + Select this if you want to use a release of Ubuntu Linux + as the operating system in your instances. + +config TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM + bool "Custom image OCID" + help + Select this if you want to enter a specific OCID for + an OS image. Use this if you wish to use a custom or + marketplace image not included in the fixed choices in + this menu. + + The image you specify must reside in the same region as + your instances. + + More image choices are available: + + https://docs.oracle.com/en-us/iaas/images/ + +endchoice + +source "terraform/oci/kconfigs/images/Kconfig.OracleLinux" +source "terraform/oci/kconfigs/images/Kconfig.Ubuntu" +source "terraform/oci/kconfigs/images/Kconfig.custom" diff --git a/terraform/oci/kconfigs/Kconfig.compute b/terraform/oci/kconfigs/Kconfig.shape similarity index 54% rename from terraform/oci/kconfigs/Kconfig.compute rename to terraform/oci/kconfigs/Kconfig.shape index c847726a5..0aeea361c 100644 --- a/terraform/oci/kconfigs/Kconfig.compute +++ b/terraform/oci/kconfigs/Kconfig.shape @@ -38,42 +38,3 @@ endchoice source "terraform/oci/kconfigs/shapes/Kconfig.flex" source "terraform/oci/kconfigs/shapes/Kconfig.generic" source "terraform/oci/kconfigs/shapes/Kconfig.bm" - -choice - prompt "Distribution" - default TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX - help - Select the Linux distribution to install on each instance. - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX - bool "Oracle Linux" - help - Select this if you want to use a release of Oracle Linux - as the operating system in your instances. - -config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU - bool "Ubuntu" - help - Select this if you want to use a release of Ubuntu Linux - as the operating system in your instances. - -config TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM - bool "Custom image OCID" - help - Select this if you want to enter a specific OCID for - an OS image. Use this if you wish to use a custom or - marketplace image not included in the fixed choices in - this menu. - - The image you specify must reside in the same region as - your instances. - - More image choices are available: - - https://docs.oracle.com/en-us/iaas/images/ - -endchoice - -source "terraform/oci/kconfigs/images/Kconfig.OracleLinux" -source "terraform/oci/kconfigs/images/Kconfig.Ubuntu" -source "terraform/oci/kconfigs/images/Kconfig.custom" From f139363e139457d0a5eabb3cfddf85fef18fc891 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sun, 19 Oct 2025 11:58:59 -0400 Subject: [PATCH 06/11] terraform/oci: Remove the kconfigs/shapes subdirectory Instead of sourcing files in a subdirectory, move the content of those files right into Kconfig.shapes. This will make it easier to examine the differences between the current menu content and the dynamically-generated content. Signed-off-by: Chuck Lever --- terraform/oci/kconfigs/Kconfig.shape | 252 +++++++++++++++++- terraform/oci/kconfigs/shapes/Kconfig.bm | 83 ------ terraform/oci/kconfigs/shapes/Kconfig.flex | 104 -------- terraform/oci/kconfigs/shapes/Kconfig.generic | 48 ---- 4 files changed, 243 insertions(+), 244 deletions(-) delete mode 100644 terraform/oci/kconfigs/shapes/Kconfig.bm delete mode 100644 terraform/oci/kconfigs/shapes/Kconfig.flex delete mode 100644 terraform/oci/kconfigs/shapes/Kconfig.generic diff --git a/terraform/oci/kconfigs/Kconfig.shape b/terraform/oci/kconfigs/Kconfig.shape index 0aeea361c..5d719d0c3 100644 --- a/terraform/oci/kconfigs/Kconfig.shape +++ b/terraform/oci/kconfigs/Kconfig.shape @@ -11,6 +11,12 @@ choice Which shapes are available is limited by your subscription and what hardware has been deployed in your selected region. +config TERRAFORM_OCI_SHAPE_FAMILY_GENERIC + bool "Generic shapes" + help + These shapes are recommended for developers who do not + require a specific model of CPU for their workflows. + config TERRAFORM_OCI_SHAPE_FAMILY_FLEX bool "Flex shapes" help @@ -19,12 +25,6 @@ config TERRAFORM_OCI_SHAPE_FAMILY_FLEX per instance. The network bandwidth and number of VNICs scale proportionately with the number of OCPUs. -config TERRAFORM_OCI_SHAPE_FAMILY_GENERIC - bool "Generic shapes" - help - These shapes are recommended for developers who do not - require a specific model of CPU for their workflows. - config TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL bool "Bare metal" help @@ -35,6 +35,240 @@ config TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL endchoice -source "terraform/oci/kconfigs/shapes/Kconfig.flex" -source "terraform/oci/kconfigs/shapes/Kconfig.generic" -source "terraform/oci/kconfigs/shapes/Kconfig.bm" +if TERRAFORM_OCI_SHAPE_FAMILY_GENERIC + +choice + prompt "OCI shape" + default TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC + help + Select the basic hardware capabilities that are in each + instance. + +config TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC + bool "VM.Standard.x86.Generic" + depends on TARGET_ARCH_X86_64 + +endchoice + +config TERRAFORM_OCI_SHAPE + string + output yaml + default "VM.Standard.x86.Generic" if TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC + +config TERRAFORM_OCI_INSTANCE_FLEX_OCPUS + int "Instance CPU count" + output yaml + default 2 + help + The Oracle CPU (OCPU) represents physical CPU cores and is + the unit of measurement for CPUs on x86 CPUs (AMD and + Intel) and Arm CPUs (OCI Ampere Compute). A virtual CPU + (vCPU), the industry-standard for measuring compute + resources, represents one execution thread of a physical + CPU core. + + Most CPU architectures, including x86, runs two threads + per physical core, so one OCPU is the equal of two vCPUs + for x86-based compute. For OCI Compute, the minimum unit + of provisioning starts from one OCPU on both X86 (Intel + and AMD) and OCI Ampere Compute processors. + +config TERRAFORM_OCI_INSTANCE_FLEX_MEMORY_IN_GBS + int "Instance memory size" + output yaml + default 4 + help + Memory per instance, in GiBs. The minimum value for this + setting is a multiple of the number of OCPUS in each + instance. + +endif # TERRAFORM_OCI_SHAPE_FAMILY_GENERIC + +if TERRAFORM_OCI_SHAPE_FAMILY_FLEX + +choice + prompt "OCI shape" + default TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX + help + Select the basic hardware capabilities that are in each + instance. For more detail, see: + + https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#flexible + +config TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX + bool "VM.Standard3.Flex" + depends on TARGET_ARCH_X86_64 + help + Selecting this option provisions each guest with between 1 + and 32 OCPUs (physical cores) and up to 512MB of memory. + +config TERRAFORM_OCI_SHAPE_VM_STANDARD_E4_FLEX + bool "VM.Standard.E4.Flex" + depends on TARGET_ARCH_X86_64 + help + Selecting this option provisions each guest with between 1 + and 114 OCPUs (physical AMD cores) and up to 1760MB of memory. + +config TERRAFORM_OCI_SHAPE_VM_STANDARD_E5_FLEX + bool "VM.Standard.E5.Flex" + depends on TARGET_ARCH_X86_64 + help + Selecting this option provisions each guest with between 1 + and 94 OCPUs (physical AMD cores) and up to 1048MB of memory. + +config TERRAFORM_OCI_SHAPE_VM_STANDARD_A1_FLEX + bool "VM.Standard.A1.Flex" + depends on TARGET_ARCH_ARM64 + help + Selecting this option provisions each guest with between 1 + and 80 OCPUs (physical ARM cores) and up to 512MB of memory. + +config TERRAFORM_OCI_SHAPE_VM_STANDARD_A2_FLEX + bool "VM.Standard.A2.Flex" + depends on TARGET_ARCH_ARM64 + help + Selecting this option provisions each guest with between 1 + and 78 OCPUs (physical ARM cores) and up to 946MB of memory. + +config TERRAFORM_OCI_SHAPE_VM_DENSEIO_E4_FLEX + bool "VM.DenseIO.E4.Flex" + depends on TARGET_ARCH_X86_64 + help + Selecting this option provisions each instance with either + 8 OCPUs and 128 GB memory, 16 OCPUs and 256 GB memory, or + 32 OCPUs and 512 GB memory. CPUs are based on the AMD + x86_64 platform. + +config TERRAFORM_OCI_SHAPE_VM_OPTIMIZED3_FLEX + bool "VM.Optimized3.Flex" + depends on TARGET_ARCH_X86_64 + help + Selecting this option provisions each instance with up to + 18 OCPUS. The memory provisioned for each instance is + typically matches a multiple of the number of OCPUS. + +endchoice + +config TERRAFORM_OCI_SHAPE + string + output yaml + default "VM.Standard3.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX + default "VM.Standard.E4.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_E4_FLEX + default "VM.Standard.E5.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_E5_FLEX + default "VM.Standard.A1.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_A1_FLEX + default "VM.Standard.A2.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_A2_FLEX + default "VM.DenseIO.E4.Flex" if TERRAFORM_OCI_SHAPE_VM_DENSEIO_E4_FLEX + default "VM.Optimized3.Flex" if TERRAFORM_OCI_SHAPE_VM_OPTIMIZED3_FLEX + +config TERRAFORM_OCI_INSTANCE_FLEX_OCPUS + int "Instance CPU count" + output yaml + default 2 + help + The Oracle CPU (OCPU) represents physical CPU cores and is + the unit of measurement for CPUs on x86 CPUs (AMD and + Intel) and Arm CPUs (OCI Ampere Compute). A virtual CPU + (vCPU), the industry-standard for measuring compute + resources, represents one execution thread of a physical + CPU core. + + Most CPU architectures, including x86, runs two threads + per physical core, so one OCPU is the equal of two vCPUs + for x86-based compute. For OCI Compute, the minimum unit + of provisioning starts from one OCPU on both X86 (Intel + and AMD) and OCI Ampere Compute processors. + +config TERRAFORM_OCI_INSTANCE_FLEX_MEMORY_IN_GBS + int "Instance memory size" + output yaml + default 4 + help + Memory per instance, in GiBs. The minimum value for this + setting is a multiple of the number of OCPUS in each + instance. + +endif # TERRAFORM_OCI_SHAPE_FAMILY_FLEX + +if TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL + +choice + prompt "OCI shape" + default TERRAFORM_OCI_SHAPE_BM_STANDARD3 + help + Select the basic hardware capabilities that are in each + instance. For more details, see: + + https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#baremetalshapes + +config TERRAFORM_OCI_SHAPE_BM_STANDARD3 + bool "BM.Standard3" + depends on TARGET_ARCH_X86_64 + help + X9-based standard compute. Processor: Intel Xeon Platinum + 8358. Base frequency 2.6 GHz, max turbo frequency 3.4 GHz. + +config TERRAFORM_OCI_SHAPE_BM_STANDARD_E4 + bool "BM.Standard.E4" + depends on TARGET_ARCH_X86_64 + help + E4-based standard compute. Processor: AMD EPYC 7J13. Base + frequency 2.55 GHz, max boost frequency 3.5 GHz. + +config TERRAFORM_OCI_SHAPE_BM_STANDARD_E5 + bool "BM.Standard.E5" + depends on TARGET_ARCH_X86_64 + help + E5-based standard compute. Processor: AMD EPYC 9J14. Base + frequency 2.4 GHz, max boost frequency 3.7 GHz. + +config TERRAFORM_OCI_SHAPE_BM_STANDARD_A1 + bool "BM.Standard.A1" + depends on TARGET_ARCH_ARM64 + help + OCI Ampere A1 Compute Arm-based standard compute. Each + OCPU corresponds to a single hardware execution thread. + Processor: Ampere Altra Q80-30. Max frequency 3.0 GHz. + +config TERRAFORM_OCI_SHAPE_BM_DENSEIO_E4 + bool "BM.DenseIO.E4" + depends on TARGET_ARCH_X86_64 + help + E4-based dense I/O compute. Processor: AMD EPYC 7J13. + Base frequency 2.55 GHz, max boost frequency 3.5 GHz. + +config TERRAFORM_OCI_SHAPE_BM_DENSEIO_E5 + bool "BM.DenseIO.E5" + depends on TARGET_ARCH_X86_64 + help + E5-based dense I/O compute. Processor: AMD EPYC 9J14. + Base frequency 2.4 GHz, max boost frequency 3.7 GHz. + +config TERRAFORM_OCI_SHAPE_BM_OPTIMIZED3 + bool "BM.Optimized3" + depends on TARGET_ARCH_X86_64 + help + Processor: Intel Xeon 6354. Base frequency 3.0 GHz, max + turbo frequency 3.6 GHz. + +config TERRAFORM_OCI_SHAPE_BM_HPC_E5 + bool "BM.HPC.E5" + depends on TARGET_ARCH_X86_64 + help + Processor: AMD EPYC 9J14. Base frequency 2.4 GHz, max + boost frequency 3.7 GHz. + +endchoice + +config TERRAFORM_OCI_SHAPE + string + output yaml + default "BM.Standard3" if TERRAFORM_OCI_SHAPE_BM_STANDARD3 + default "BM.Standard.E4" if TERRAFORM_OCI_SHAPE_BM_STANDARD_E4 + default "BM.Standard.E5" if TERRAFORM_OCI_SHAPE_BM_STANDARD_E5 + default "BM.Standard.A1" if TERRAFORM_OCI_SHAPE_BM_STANDARD_A1 + default "BM.DenseIO.E4" if TERRAFORM_OCI_SHAPE_BM_DENSEIO_E4 + default "BM.DenseIO.E5" if TERRAFORM_OCI_SHAPE_BM_DENSEIO_E5 + default "BM.Optimized3" if TERRAFORM_OCI_SHAPE_BM_OPTIMIZED3 + default "BM.HPC.E5" if TERRAFORM_OCI_SHAPE_BM_HPC_E5 + +endif # TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL diff --git a/terraform/oci/kconfigs/shapes/Kconfig.bm b/terraform/oci/kconfigs/shapes/Kconfig.bm deleted file mode 100644 index 40ef4502b..000000000 --- a/terraform/oci/kconfigs/shapes/Kconfig.bm +++ /dev/null @@ -1,83 +0,0 @@ -if TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL - -choice - prompt "OCI shape" - default TERRAFORM_OCI_SHAPE_BM_STANDARD3 - help - Select the basic hardware capabilities that are in each - instance. For more details, see: - - https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#baremetalshapes - -config TERRAFORM_OCI_SHAPE_BM_STANDARD3 - bool "BM.Standard3" - depends on TARGET_ARCH_X86_64 - help - X9-based standard compute. Processor: Intel Xeon Platinum - 8358. Base frequency 2.6 GHz, max turbo frequency 3.4 GHz. - -config TERRAFORM_OCI_SHAPE_BM_STANDARD_E4 - bool "BM.Standard.E4" - depends on TARGET_ARCH_X86_64 - help - E4-based standard compute. Processor: AMD EPYC 7J13. Base - frequency 2.55 GHz, max boost frequency 3.5 GHz. - -config TERRAFORM_OCI_SHAPE_BM_STANDARD_E5 - bool "BM.Standard.E5" - depends on TARGET_ARCH_X86_64 - help - E5-based standard compute. Processor: AMD EPYC 9J14. Base - frequency 2.4 GHz, max boost frequency 3.7 GHz. - -config TERRAFORM_OCI_SHAPE_BM_STANDARD_A1 - bool "BM.Standard.A1" - depends on TARGET_ARCH_ARM64 - help - OCI Ampere A1 Compute Arm-based standard compute. Each - OCPU corresponds to a single hardware execution thread. - Processor: Ampere Altra Q80-30. Max frequency 3.0 GHz. - -config TERRAFORM_OCI_SHAPE_BM_DENSEIO_E4 - bool "BM.DenseIO.E4" - depends on TARGET_ARCH_X86_64 - help - E4-based dense I/O compute. Processor: AMD EPYC 7J13. - Base frequency 2.55 GHz, max boost frequency 3.5 GHz. - -config TERRAFORM_OCI_SHAPE_BM_DENSEIO_E5 - bool "BM.DenseIO.E5" - depends on TARGET_ARCH_X86_64 - help - E5-based dense I/O compute. Processor: AMD EPYC 9J14. - Base frequency 2.4 GHz, max boost frequency 3.7 GHz. - -config TERRAFORM_OCI_SHAPE_BM_OPTIMIZED3 - bool "BM.Optimized3" - depends on TARGET_ARCH_X86_64 - help - Processor: Intel Xeon 6354. Base frequency 3.0 GHz, max - turbo frequency 3.6 GHz. - -config TERRAFORM_OCI_SHAPE_BM_HPC_E5 - bool "BM.HPC.E5" - depends on TARGET_ARCH_X86_64 - help - Processor: AMD EPYC 9J14. Base frequency 2.4 GHz, max - boost frequency 3.7 GHz. - -endchoice - -config TERRAFORM_OCI_SHAPE - string - output yaml - default "BM.Standard3" if TERRAFORM_OCI_SHAPE_BM_STANDARD3 - default "BM.Standard.E4" if TERRAFORM_OCI_SHAPE_BM_STANDARD_E4 - default "BM.Standard.E5" if TERRAFORM_OCI_SHAPE_BM_STANDARD_E5 - default "BM.Standard.A1" if TERRAFORM_OCI_SHAPE_BM_STANDARD_A1 - default "BM.DenseIO.E4" if TERRAFORM_OCI_SHAPE_BM_DENSEIO_E4 - default "BM.DenseIO.E5" if TERRAFORM_OCI_SHAPE_BM_DENSEIO_E5 - default "BM.Optimized3" if TERRAFORM_OCI_SHAPE_BM_OPTIMIZED3 - default "BM.HPC.E5" if TERRAFORM_OCI_SHAPE_BM_HPC_E5 - -endif # TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL diff --git a/terraform/oci/kconfigs/shapes/Kconfig.flex b/terraform/oci/kconfigs/shapes/Kconfig.flex deleted file mode 100644 index 67d50604b..000000000 --- a/terraform/oci/kconfigs/shapes/Kconfig.flex +++ /dev/null @@ -1,104 +0,0 @@ -if TERRAFORM_OCI_SHAPE_FAMILY_FLEX - -choice - prompt "OCI shape" - default TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX - help - Select the basic hardware capabilities that are in each - instance. For more detail, see: - - https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#flexible - -config TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX - bool "VM.Standard3.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each guest with between 1 - and 32 OCPUs (physical cores) and up to 512MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_E4_FLEX - bool "VM.Standard.E4.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each guest with between 1 - and 114 OCPUs (physical AMD cores) and up to 1760MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_E5_FLEX - bool "VM.Standard.E5.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each guest with between 1 - and 94 OCPUs (physical AMD cores) and up to 1048MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_A1_FLEX - bool "VM.Standard.A1.Flex" - depends on TARGET_ARCH_ARM64 - help - Selecting this option provisions each guest with between 1 - and 80 OCPUs (physical ARM cores) and up to 512MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_A2_FLEX - bool "VM.Standard.A2.Flex" - depends on TARGET_ARCH_ARM64 - help - Selecting this option provisions each guest with between 1 - and 78 OCPUs (physical ARM cores) and up to 946MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_DENSEIO_E4_FLEX - bool "VM.DenseIO.E4.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each instance with either - 8 OCPUs and 128 GB memory, 16 OCPUs and 256 GB memory, or - 32 OCPUs and 512 GB memory. CPUs are based on the AMD - x86_64 platform. - -config TERRAFORM_OCI_SHAPE_VM_OPTIMIZED3_FLEX - bool "VM.Optimized3.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each instance with up to - 18 OCPUS. The memory provisioned for each instance is - typically matches a multiple of the number of OCPUS. - -endchoice - -config TERRAFORM_OCI_SHAPE - string - output yaml - default "VM.Standard3.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX - default "VM.Standard.E4.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_E4_FLEX - default "VM.Standard.E5.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_E5_FLEX - default "VM.Standard.A1.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_A1_FLEX - default "VM.Standard.A2.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_A2_FLEX - default "VM.DenseIO.E4.Flex" if TERRAFORM_OCI_SHAPE_VM_DENSEIO_E4_FLEX - default "VM.Optimized3.Flex" if TERRAFORM_OCI_SHAPE_VM_OPTIMIZED3_FLEX - -config TERRAFORM_OCI_INSTANCE_FLEX_OCPUS - int "Instance CPU count" - output yaml - default 2 - help - The Oracle CPU (OCPU) represents physical CPU cores and is - the unit of measurement for CPUs on x86 CPUs (AMD and - Intel) and Arm CPUs (OCI Ampere Compute). A virtual CPU - (vCPU), the industry-standard for measuring compute - resources, represents one execution thread of a physical - CPU core. - - Most CPU architectures, including x86, runs two threads - per physical core, so one OCPU is the equal of two vCPUs - for x86-based compute. For OCI Compute, the minimum unit - of provisioning starts from one OCPU on both X86 (Intel - and AMD) and OCI Ampere Compute processors. - -config TERRAFORM_OCI_INSTANCE_FLEX_MEMORY_IN_GBS - int "Instance memory size" - output yaml - default 4 - help - Memory per instance, in GiBs. The minimum value for this - setting is a multiple of the number of OCPUS in each - instance. - -endif # TERRAFORM_OCI_SHAPE_FAMILY_FLEX diff --git a/terraform/oci/kconfigs/shapes/Kconfig.generic b/terraform/oci/kconfigs/shapes/Kconfig.generic deleted file mode 100644 index b6893a97c..000000000 --- a/terraform/oci/kconfigs/shapes/Kconfig.generic +++ /dev/null @@ -1,48 +0,0 @@ -if TERRAFORM_OCI_SHAPE_FAMILY_GENERIC - -choice - prompt "OCI shape" - default TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC - help - Select the basic hardware capabilities that are in each - instance. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC - bool "VM.Standard.x86.Generic" - depends on TARGET_ARCH_X86_64 - -endchoice - -config TERRAFORM_OCI_SHAPE - string - output yaml - default "VM.Standard.x86.Generic" if TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC - -config TERRAFORM_OCI_INSTANCE_FLEX_OCPUS - int "Instance CPU count" - output yaml - default 2 - help - The Oracle CPU (OCPU) represents physical CPU cores and is - the unit of measurement for CPUs on x86 CPUs (AMD and - Intel) and Arm CPUs (OCI Ampere Compute). A virtual CPU - (vCPU), the industry-standard for measuring compute - resources, represents one execution thread of a physical - CPU core. - - Most CPU architectures, including x86, runs two threads - per physical core, so one OCPU is the equal of two vCPUs - for x86-based compute. For OCI Compute, the minimum unit - of provisioning starts from one OCPU on both X86 (Intel - and AMD) and OCI Ampere Compute processors. - -config TERRAFORM_OCI_INSTANCE_FLEX_MEMORY_IN_GBS - int "Instance memory size" - output yaml - default 4 - help - Memory per instance, in GiBs. The minimum value for this - setting is a multiple of the number of OCPUS in each - instance. - -endif # TERRAFORM_OCI_SHAPE_FAMILY_GENERIC From 033c69d229e9a14888b07718be408ce05f90cec7 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sun, 19 Oct 2025 12:04:59 -0400 Subject: [PATCH 07/11] terraform/oci: Generate Kconfig.shapes dynamically Duplicate the same functionality as is already provided for AWS. The generated shape menu includes shapes that are available in the region or regions that the user tenancy is subscribed to. A "Generic" family is retained for users who simply want to specify a memory size and CPU count and go on their merry way. Generated-by: Claude AI Signed-off-by: Chuck Lever --- terraform/oci/scripts/bare_metal_shapes.j2 | 69 ++ terraform/oci/scripts/catalog_shapes.yml | 171 ++++ terraform/oci/scripts/fixed_shapes.j2 | 70 ++ terraform/oci/scripts/flex_shapes.j2 | 97 +++ terraform/oci/scripts/gen_kconfig_shape | 950 +++++++++++++++++++++ terraform/oci/scripts/generic_family.j2 | 51 ++ terraform/oci/scripts/shape_families.j2 | 44 + terraform/oci/scripts/shape_family.j2 | 57 ++ 8 files changed, 1509 insertions(+) create mode 100644 terraform/oci/scripts/bare_metal_shapes.j2 create mode 100644 terraform/oci/scripts/catalog_shapes.yml create mode 100644 terraform/oci/scripts/fixed_shapes.j2 create mode 100644 terraform/oci/scripts/flex_shapes.j2 create mode 100755 terraform/oci/scripts/gen_kconfig_shape create mode 100644 terraform/oci/scripts/generic_family.j2 create mode 100644 terraform/oci/scripts/shape_families.j2 create mode 100644 terraform/oci/scripts/shape_family.j2 diff --git a/terraform/oci/scripts/bare_metal_shapes.j2 b/terraform/oci/scripts/bare_metal_shapes.j2 new file mode 100644 index 000000000..771678a3e --- /dev/null +++ b/terraform/oci/scripts/bare_metal_shapes.j2 @@ -0,0 +1,69 @@ +if TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL + +choice + prompt "OCI shape" +{% if shapes and shapes | length > 0 %} + default TERRAFORM_OCI_SHAPE_{{ shapes[0]['shape_name'].upper().replace('.', '_').replace('-', '_') }} +{% else %} + default TERRAFORM_OCI_SHAPE_BM_STANDARD3 +{% endif %} + help + Select the basic hardware capabilities that are in each + instance. For more details, see: + + https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#baremetalshapes + +{% for shape in shapes %} +{# Validate required fields are present #} +{% if 'shape_name' not in shape or 'cpu_isa' not in shape %} +{# Skip malformed shape entries #} +{% continue %} +{% endif %} +config TERRAFORM_OCI_SHAPE_{{ shape['shape_name'].upper().replace('.', '_').replace('-', '_') }} + bool "{{ shape['shape_name'] }}" +{% if shape['cpu_isa'] == 'x86_64' %} + depends on TARGET_ARCH_X86_64 +{% elif shape['cpu_isa'] == 'arm64' %} + depends on TARGET_ARCH_ARM64 +{% endif %} + help +{% if 'processor' in shape %} + Processor: {{ shape['processor'] }} +{% else %} + Bare metal instance. +{% endif %} +{% if shape.get('memory_gb', 'Flexible') != 'Flexible' and shape.get('ocpus', 'Flexible') != 'Flexible' %} + + OCPU count: {{ shape['ocpus'] }} + Memory: {{ shape['memory_gb'] }} GB +{% endif %} + Architecture: {{ shape['cpu_isa'] }} +{% if shape.get('network_performance', 'Not specified') != 'Not specified' %} + Network: {{ shape['network_performance'] }} +{% endif %} +{% if shape.get('storage', 'Block storage only') != 'Block storage only' %} + Local storage: {{ shape['storage'] }} +{% endif %} +{% if shape.get('gpu', 'None') != 'None' %} + GPU: {{ shape['gpu'] }} +{% endif %} +{% if shape.get('is_catalog_shape', False) %} + + NOTE: This shape may require service limit increases and may not + be available in all regions. Contact Oracle support to request + access if needed. +{% endif %} + +{% endfor %} +endchoice + +config TERRAFORM_OCI_SHAPE + string + output yaml +{% for shape in shapes %} +{% if 'shape_name' in shape and 'cpu_isa' in shape %} + default "{{ shape['shape_name'] }}" if TERRAFORM_OCI_SHAPE_{{ shape['shape_name'].upper().replace('.', '_').replace('-', '_') }} +{% endif %} +{% endfor %} + +endif # TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL diff --git a/terraform/oci/scripts/catalog_shapes.yml b/terraform/oci/scripts/catalog_shapes.yml new file mode 100644 index 000000000..6c3b221e9 --- /dev/null +++ b/terraform/oci/scripts/catalog_shapes.yml @@ -0,0 +1,171 @@ +# OCI Catalog Shapes +# +# This file contains well-known OCI compute shapes that may not be visible +# via the OCI API. These shapes typically require service limit increases or +# are in limited availability. +# +# Purpose: +# The --include-catalog option in gen_kconfig_shape merges these shapes +# with API-discovered shapes to provide a complete menu of shapes that +# users can request access to. +# +# Canonical Sources: +# https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm +# (Official Oracle Cloud Infrastructure Compute Shapes documentation) +# +# Note: Shape availability varies by region and requires proper service +# limits. Use the OCI console to check availability and request limit +# increases if needed. +# +# Last Updated: 2025-10-21 +# Total Catalog Shapes: 11 +# +# Format: +# shape-name: +# architectures: [x86_64|arm64] +# is_flex: true|false # Optional, indicates flexible shapes +# is_bare_metal: true|false # Optional, indicates bare metal shapes +# has_gpu: true|false # Optional, indicates GPU shapes +# description: "Human-readable description" +# +# Selection Criteria for Catalog Shapes: +# --------------------------------------- +# A shape should be in this catalog if it meets these criteria: +# +# 1. NOT visible via standard OCI API query: +# $ cd terraform/oci/scripts +# $ ./gen_kconfig_shape --families --format raw +# If the shape family does NOT appear in the output, it's a catalog candidate. +# +# 2. Documented in Oracle's official compute shapes reference: +# https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm +# +# 3. Requires service limit increases or has limited regional availability: +# - DenseIO shapes (local NVMe storage) - often require limit increases +# - GPU shapes (NVIDIA GPUs) - limited availability, require special quotas +# - HPC shapes (high-performance computing) - specialty shapes with restrictions +# +# 4. Generally available (not preview/beta shapes that may be discontinued) +# +# How to update this file: +# ----------------------- +# When Oracle adds new shapes or you want to include additional catalog shapes: +# +# 1. Check if the shape is already API-visible in your tenancy: +# $ cd terraform/oci/scripts +# $ ./gen_kconfig_shape --families --format raw | grep -i "FAMILY_NAME" +# +# If found in API output, DO NOT add to catalog (API discovery handles it). +# If NOT found, proceed to step 2. +# +# 2. Verify the shape exists in Oracle's documentation: +# https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm +# +# Look for shape specifications including: +# - Architecture (x86_64 or arm64) +# - Whether it's Flex (flexible sizing) +# - Whether it's bare metal (BM prefix) +# - GPU information if applicable +# +# 3. Add the entry following the format specification above. +# +# Architecture detection rules: +# - Shapes with A1, A2 in name: arm64 (Ampere) +# - Shapes with AMD/Intel processors: x86_64 +# - Check Oracle docs if uncertain +# +# Type detection rules: +# - Name ends with .Flex: set is_flex: true +# - Name starts with BM.: set is_bare_metal: true +# - Contains GPU in name: set has_gpu: true +# +# 4. Update the "Last Updated" date and "Total Catalog Shapes" count above. +# +# 5. Test that the shape loads correctly: +# $ cd terraform/oci/scripts +# $ ./gen_kconfig_shape --include-catalog --families --format raw | grep "SHAPE_NAME" +# Verify the shape appears with a '*' indicating it's from the catalog. +# +# 6. Regenerate Kconfig.shape: +# $ ./gen_kconfig_shape --include-catalog > ../kconfigs/Kconfig.shape +# +# Example Decision Process: +# ------------------------- +# Q: Should I add VM.Standard.E5.Flex to the catalog? +# A: No. This shape is widely available and appears in standard API queries. +# Run ./gen_kconfig_shape --families to verify it's already discovered. +# +# Q: Should I add BM.GPU.H100.8 (hypothetical new GPU shape)? +# A: Yes, if: +# - It doesn't appear in ./gen_kconfig_shape --families output +# - It's documented at the Oracle reference URL above +# - It's a specialty shape (GPU = yes, requires quotas) +# +# Q: How do I know if a shape needs is_flex vs is_bare_metal? +# A: Check the shape name: +# - Ends with .Flex → is_flex: true +# - Starts with BM. → is_bare_metal: true +# - Can be both (e.g., BM.Something.Flex would have both set to true) +# +# Catalog Shape Definitions: +# -------------------------- + +# DenseIO Shapes - High I/O with local NVMe storage +VM.DenseIO.E4.Flex: + architectures: [x86_64] + is_flex: true + description: "DenseIO E4 Flex with local NVMe storage" + +BM.DenseIO1.36: + architectures: [x86_64] + is_bare_metal: true + description: "DenseIO1 bare metal with local NVMe storage" + +BM.DenseIO2.52: + architectures: [x86_64] + is_bare_metal: true + description: "DenseIO2 bare metal with local NVMe storage" + +VM.DenseIO.A2.Flex: + architectures: [arm64] + is_flex: true + description: "DenseIO A2 Flex ARM with local NVMe storage" + +# GPU Shapes - For AI/ML and graphics workloads +VM.GPU.A10.1: + architectures: [x86_64] + has_gpu: true + description: "1x NVIDIA A10 GPU" + +VM.GPU.A10.2: + architectures: [x86_64] + has_gpu: true + description: "2x NVIDIA A10 GPUs" + +BM.GPU.A10.4: + architectures: [x86_64] + is_bare_metal: true + has_gpu: true + description: "4x NVIDIA A10 GPUs" + +BM.GPU4.8: + architectures: [x86_64] + is_bare_metal: true + has_gpu: true + description: "8x NVIDIA A100 GPUs" + +VM.GPU.GU1.1: + architectures: [x86_64] + has_gpu: true + description: "1x NVIDIA P100 GPU" + +VM.GPU.GU1.2: + architectures: [x86_64] + has_gpu: true + description: "2x NVIDIA P100 GPUs" + +BM.GPU.GM4.8: + architectures: [x86_64] + is_bare_metal: true + has_gpu: true + description: "8x NVIDIA V100 GPUs" diff --git a/terraform/oci/scripts/fixed_shapes.j2 b/terraform/oci/scripts/fixed_shapes.j2 new file mode 100644 index 000000000..3b2be1bc4 --- /dev/null +++ b/terraform/oci/scripts/fixed_shapes.j2 @@ -0,0 +1,70 @@ +if TERRAFORM_OCI_SHAPE_FAMILY_FIXED + +choice + prompt "OCI shape" +{% if shapes and shapes | length > 0 %} + default TERRAFORM_OCI_SHAPE_{{ shapes[0]['shape_name'].upper().replace('.', '_').replace('-', '_') }} +{% else %} + default TERRAFORM_OCI_SHAPE_VM_STANDARD2_1 +{% endif %} + help + Select the specific shape configuration. Fixed shapes have + predetermined OCPU and memory configurations optimized for + common workload patterns. For more details, see: + + https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm + +{% for shape in shapes %} +{# Validate required fields are present and have valid values for fixed shapes #} +{% if 'shape_name' not in shape or 'ocpus' not in shape or 'memory_gb' not in shape or 'cpu_isa' not in shape %} +{# Skip malformed shape entries #} +{% continue %} +{% endif %} +{% if shape['ocpus'] == 'Flexible' or shape['memory_gb'] == 'Flexible' %} +{# Skip flex shapes that were incorrectly categorized as fixed #} +{% continue %} +{% endif %} +config TERRAFORM_OCI_SHAPE_{{ shape['shape_name'].upper().replace('.', '_').replace('-', '_') }} + bool "{{ shape['shape_name'] }}" +{% if shape['cpu_isa'] == 'x86_64' %} + depends on TARGET_ARCH_X86_64 +{% elif shape['cpu_isa'] == 'arm64' %} + depends on TARGET_ARCH_ARM64 +{% endif %} + help +{% if 'processor' in shape %} + Processor: {{ shape['processor'] }} + +{% endif %} + OCPU count: {{ shape['ocpus'] }} + Memory: {{ shape['memory_gb'] }} GB + Architecture: {{ shape['cpu_isa'] }} +{% if shape.get('network_performance', 'Not specified') != 'Not specified' %} + Network: {{ shape['network_performance'] }} +{% endif %} +{% if shape.get('storage', 'Block storage only') != 'Block storage only' %} + Local storage: {{ shape['storage'] }} +{% endif %} +{% if shape.get('gpu', 'None') != 'None' %} + GPU: {{ shape['gpu'] }} +{% endif %} +{% if shape.get('is_catalog_shape', False) %} + + NOTE: This shape may require service limit increases and may not + be available in all regions. Contact Oracle support to request + access if needed. +{% endif %} + +{% endfor %} +endchoice + +config TERRAFORM_OCI_SHAPE + string + output yaml +{% for shape in shapes %} +{% if 'shape_name' in shape and 'ocpus' in shape and 'memory_gb' in shape and shape['ocpus'] != 'Flexible' and shape['memory_gb'] != 'Flexible' %} + default "{{ shape['shape_name'] }}" if TERRAFORM_OCI_SHAPE_{{ shape['shape_name'].upper().replace('.', '_').replace('-', '_') }} +{% endif %} +{% endfor %} + +endif # TERRAFORM_OCI_SHAPE_FAMILY_FIXED diff --git a/terraform/oci/scripts/flex_shapes.j2 b/terraform/oci/scripts/flex_shapes.j2 new file mode 100644 index 000000000..be2c2197c --- /dev/null +++ b/terraform/oci/scripts/flex_shapes.j2 @@ -0,0 +1,97 @@ +if TERRAFORM_OCI_SHAPE_FAMILY_FLEX + +choice + prompt "OCI shape" +{% if shapes and shapes | length > 0 %} + default TERRAFORM_OCI_SHAPE_{{ shapes[0]['shape_name'].upper().replace('.', '_').replace('-', '_') }} +{% else %} + default TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX +{% endif %} + help + Select the basic hardware capabilities that are in each + instance. For more detail, see: + + https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#flexible + +{% for shape in shapes %} +{# Validate required fields are present #} +{% if 'shape_name' not in shape or 'cpu_isa' not in shape %} +{# Skip malformed shape entries #} +{% continue %} +{% endif %} +config TERRAFORM_OCI_SHAPE_{{ shape['shape_name'].upper().replace('.', '_').replace('-', '_') }} + bool "{{ shape['shape_name'] }}" +{% if shape['cpu_isa'] == 'x86_64' %} + depends on TARGET_ARCH_X86_64 +{% elif shape['cpu_isa'] == 'arm64' %} + depends on TARGET_ARCH_ARM64 +{% endif %} + help + {{ shape['processor'] if 'processor' in shape else 'Flexible shape: OCPU and memory can be customized.' }} + +{% if 'ocpu_min' in shape and 'ocpu_max' in shape %} + OCPU range: {{ shape['ocpu_min'] }} to {{ shape['ocpu_max'] }} +{% endif %} +{% if 'memory_per_ocpu_min' in shape and 'memory_per_ocpu_max' in shape %} + Memory per OCPU: {{ shape['memory_per_ocpu_min'] }} to {{ shape['memory_per_ocpu_max'] }} GB +{% endif %} +{% if 'memory_min' in shape and 'memory_max' in shape %} + Total memory range: {{ shape['memory_min'] }} to {{ shape['memory_max'] }} GB +{% endif %} + Architecture: {{ shape['cpu_isa'] }} +{% if shape.get('network_performance', 'Not specified') != 'Not specified' %} + Network: {{ shape['network_performance'] }} +{% endif %} +{% if shape.get('storage', 'Block storage only') != 'Block storage only' %} + Local storage: {{ shape['storage'] }} +{% endif %} +{% if shape.get('gpu', 'None') != 'None' %} + GPU: {{ shape['gpu'] }} +{% endif %} +{% if shape.get('is_catalog_shape', False) %} + + NOTE: This shape may require service limit increases and may not + be available in all regions. Contact Oracle support to request + access if needed. +{% endif %} + +{% endfor %} +endchoice + +config TERRAFORM_OCI_SHAPE + string + output yaml +{% for shape in shapes %} +{% if 'shape_name' in shape and 'cpu_isa' in shape %} + default "{{ shape['shape_name'] }}" if TERRAFORM_OCI_SHAPE_{{ shape['shape_name'].upper().replace('.', '_').replace('-', '_') }} +{% endif %} +{% endfor %} + +config TERRAFORM_OCI_INSTANCE_FLEX_OCPUS + int "Instance CPU count" + output yaml + default 2 + help + The Oracle CPU (OCPU) represents physical CPU cores and is + the unit of measurement for CPUs on x86 CPUs (AMD and + Intel) and Arm CPUs (OCI Ampere Compute). A virtual CPU + (vCPU), the industry-standard for measuring compute + resources, represents one execution thread of a physical + CPU core. + + Most CPU architectures, including x86, run two threads + per physical core, so one OCPU is the equal of two vCPUs + for x86-based compute. For OCI Compute, the minimum unit + of provisioning starts from one OCPU on both X86 (Intel + and AMD) and OCI Ampere Compute processors. + +config TERRAFORM_OCI_INSTANCE_FLEX_MEMORY_IN_GBS + int "Instance memory size" + output yaml + default 4 + help + Memory per instance, in GiBs. The minimum value for this + setting is a multiple of the number of OCPUs in each + instance. + +endif # TERRAFORM_OCI_SHAPE_FAMILY_FLEX diff --git a/terraform/oci/scripts/gen_kconfig_shape b/terraform/oci/scripts/gen_kconfig_shape new file mode 100755 index 000000000..09dd6d6fe --- /dev/null +++ b/terraform/oci/scripts/gen_kconfig_shape @@ -0,0 +1,950 @@ +#!/usr/bin/env python3 +# ex: set filetype=python: + +""" +Retrieve compute shape information from OCI. Use it to construct the "shapes" +Kconfig menu. + +OCI shapes represent compute instance configurations with varying combinations +of CPU, memory, storage, and networking capacity. This script queries the OCI +API to discover available shapes and generates Kconfig menu entries for them. + +Shape Discovery: + By default, this script aggregates shapes from all subscribed regions to + provide a comprehensive list of shapes actually available in your tenancy. + + The --include-catalog option adds well-known shapes (like DenseIO, GPU shapes) + that may require service limit increases or are in limited availability. + +Usage: + # Generate shapes Kconfig from all subscribed regions (default) + ./gen_kconfig_shape > ../kconfigs/Kconfig.shapes + + # Include catalog shapes that may need service limits + ./gen_kconfig_shape --include-catalog > ../kconfigs/Kconfig.shapes + + # List all available shape families + ./gen_kconfig_shape --families + + # Get details for a specific shape family + ./gen_kconfig_shape VM.Standard.E4 +""" + +import sys +import os +import argparse + +import oci +from oci.exceptions import ServiceError, ConfigFileNotFound + +from oci_common import ( + get_default_region, + get_default_compartment, + get_subscribed_regions, + get_jinja2_environment, + load_yaml_config, + create_compute_client, +) + + +def get_all_shapes(compartment_ocid, regions=None, quiet=False): + """ + Get all available compute shapes across specified regions. + + Args: + compartment_ocid (str): OCI compartment OCID + regions (list): List of region names to query. If None, uses default region. + quiet (bool): Suppress debug messages + + Returns: + list: List of shape objects aggregated from all regions (deduplicated by name) + """ + if regions is None: + regions = [get_default_region()] + + all_shapes = {} # Use dict to deduplicate by shape name + + for region in regions: + if not quiet: + print(f"Fetching shapes from {region}...", file=sys.stderr) + + try: + compute = create_compute_client(region) + + shapes_response = compute.list_shapes(compartment_ocid) + shapes = shapes_response.data + + # Add shapes to dict, using shape name as key to deduplicate + for shape in shapes: + if shape.shape not in all_shapes: + all_shapes[shape.shape] = shape + + if not quiet: + print(f" Found {len(shapes)} shapes in {region}", file=sys.stderr) + + except ConfigFileNotFound: + print( + "Error: OCI config file not found. Please configure OCI CLI.", + file=sys.stderr, + ) + return [] + except ServiceError as e: + print(f" Warning: Could not query {region}: {e.message}", file=sys.stderr) + continue + except Exception as e: + print(f" Warning: Error querying {region}: {e}", file=sys.stderr) + continue + + if not quiet: + print( + f"\nTotal unique shapes across all regions: {len(all_shapes)}", + file=sys.stderr, + ) + + return list(all_shapes.values()) + + +def get_catalog_shapes(): + """ + Return a list of well-known OCI shapes that may not be visible via API. + + These shapes may require service limit increases or are in limited + availability. They are included to provide a complete menu of shapes + that users can request access to. + + The catalog is loaded from catalog_shapes.yml to make it easier to + update when Oracle adds new shapes. See catalog_shapes.yml for + instructions on how to update the catalog. + + Returns: + dict: Dictionary mapping shape names to their basic properties + """ + return load_yaml_config("catalog_shapes.yml") + + +def merge_catalog_shapes(api_shapes, quiet=False): + """ + Merge API-discovered shapes with catalog shapes. + + Args: + api_shapes (list): Shapes discovered via API + quiet (bool): Suppress debug messages + + Returns: + list: Combined list of API shapes plus catalog shapes (deduplicated) + """ + # Create a dict from API shapes + shapes_dict = {shape.shape: shape for shape in api_shapes} + + catalog = get_catalog_shapes() + added_count = 0 + + # Mark all API shapes as not from catalog + for shape in shapes_dict.values(): + shape.is_catalog_shape = False + + # Add catalog shapes that aren't already in API results + for shape_name, properties in catalog.items(): + if shape_name not in shapes_dict: + # Create a minimal shape object with catalog properties + # We'll use a simple namespace object to mimic OCI shape structure + from types import SimpleNamespace + + catalog_shape = SimpleNamespace( + shape=shape_name, + processor_description=properties.get("description", ""), + memory_in_gbs=0, # Will show as "Flexible" or unknown + ocpus=0, # Will show as "Flexible" or unknown + gpus=1 if properties.get("has_gpu", False) else 0, + is_catalog_shape=True, # Mark as catalog shape + ) + shapes_dict[shape_name] = catalog_shape + added_count += 1 + + if not quiet and added_count > 0: + print(f"Added {added_count} shapes from catalog", file=sys.stderr) + + return list(shapes_dict.values()) + + +def parse_all_shape_families(shapes, quiet=False): + """ + Extract shape families from the list of shapes. + + OCI shape names follow a pattern like "VM.Standard.E4.Flex" or + "BM.Standard2.52". This function groups shapes by their family + prefix (e.g., "VM.Standard.E4" or "BM.Standard2"). + + Args: + shapes (list): List of shape objects from OCI API + quiet (bool): Suppress debug messages + + Returns: + dict: Dictionary with family info including count of shapes per family + """ + families = {} + seen_shapes = set() + + for shape in shapes: + shape_name = shape.shape + + # Skip duplicate shape names + if shape_name in seen_shapes: + continue + seen_shapes.add(shape_name) + + # Parse shape family from name + # Examples: + # VM.Standard.E4.Flex -> VM.Standard.E4 + # VM.Standard3.Flex -> VM.Standard3 + # BM.Standard2.52 -> BM.Standard2 + parts = shape_name.split(".") + + # Determine family based on shape naming patterns + if len(parts) >= 3: + # Handle patterns like VM.Standard.E4.Flex or VM.Standard.A1.Flex + if parts[-1] == "Flex": + family = ".".join(parts[:-1]) # VM.Standard.E4 + else: + # Handle fixed shapes like BM.Standard2.52 + family = ".".join(parts[:-1]) # BM.Standard2 + elif len(parts) == 2: + # Handle patterns like VM.Standard3.Flex -> VM.Standard3 + family = ".".join(parts) + else: + family = shape_name + + if family not in families: + families[family] = { + "family_name": family, + "shape_count": 0, + "has_gpu": False, + "architectures": set(), + "is_flex": False, + "is_bare_metal": False, + "has_catalog_shapes": False, + } + + families[family]["shape_count"] += 1 + + # Determine if it's a flex shape + if ".Flex" in shape_name or shape_name.endswith(".Flex"): + families[family]["is_flex"] = True + + # Determine if it's bare metal + if shape_name.startswith("BM."): + families[family]["is_bare_metal"] = True + + # Check for GPU + if hasattr(shape, "gpus") and shape.gpus > 0: + families[family]["has_gpu"] = True + + # Check if this shape is from catalog + if getattr(shape, "is_catalog_shape", False): + families[family]["has_catalog_shapes"] = True + + # Get processor architecture + if hasattr(shape, "processor_description"): + proc_desc = shape.processor_description.lower() + if "amd" in proc_desc or "intel" in proc_desc or "x86" in proc_desc: + families[family]["architectures"].add("x86_64") + elif "arm" in proc_desc or "ampere" in proc_desc: + families[family]["architectures"].add("arm64") + else: + families[family]["architectures"].add("x86_64") # Default to x86_64 + else: + # Default architecture based on shape naming + if "A1" in shape_name or "A2" in shape_name: + families[family]["architectures"].add("arm64") + else: + families[family]["architectures"].add("x86_64") + + # Convert architecture sets to sorted lists for JSON serialization + for family in families.values(): + family["architectures"] = sorted(list(family["architectures"])) + + return families + + +def get_gpu_info(shape): + """ + Extract GPU information from shape data. + + Args: + shape: Shape object from OCI API + + Returns: + str: Formatted GPU information string + """ + if not hasattr(shape, "gpus") or shape.gpus == 0: + return "None" + + gpu_count = shape.gpus + + # Try to get GPU description if available + gpu_desc = getattr(shape, "gpu_description", None) + if gpu_desc: + if gpu_count > 1: + return f"{gpu_count}x {gpu_desc}" + return gpu_desc + + # Fallback to just count + if gpu_count > 1: + return f"{gpu_count}x GPU" + return "GPU" + + +def extract_cpu_architecture(shape): + """ + Determine CPU architecture from shape information. + + Args: + shape: Shape object from OCI API + + Returns: + str: CPU architecture ('arm64' or 'x86_64') + """ + shape_name = shape.shape + cpu_isa = "x86_64" # Default + + # Check processor description + if hasattr(shape, "processor_description"): + proc_desc = shape.processor_description.lower() + if "arm" in proc_desc or "ampere" in proc_desc: + return "arm64" + elif "amd" in proc_desc or "intel" in proc_desc: + return "x86_64" + + # Fall back to shape naming patterns + if "A1" in shape_name or "A2" in shape_name: + return "arm64" + + return cpu_isa + + +def extract_memory_info(shape): + """ + Extract memory information from shape data. + + Args: + shape: Shape object from OCI API + + Returns: + dict: Dictionary with memory_gb and optional flex memory ranges + """ + memory_info = { + "memory_gb": 0, + } + + if hasattr(shape, "memory_in_gbs"): + memory_info["memory_gb"] = shape.memory_in_gbs + elif hasattr(shape, "memory_options"): + # Flex shapes have memory options + if hasattr(shape.memory_options, "default_per_ocpu_in_g_bs"): + # For flex shapes, use a default OCPU count to show typical memory + default_ocpus = 1 + if hasattr(shape, "ocpus"): + default_ocpus = shape.ocpus + memory_info["memory_gb"] = ( + shape.memory_options.default_per_ocpu_in_g_bs * default_ocpus + ) + + # Extract min/max memory per OCPU for flex shapes + if hasattr(shape.memory_options, "min_per_ocpu_in_g_bs"): + memory_info["memory_per_ocpu_min"] = ( + shape.memory_options.min_per_ocpu_in_g_bs + ) + if hasattr(shape.memory_options, "max_per_ocpu_in_g_bs"): + memory_info["memory_per_ocpu_max"] = ( + shape.memory_options.max_per_ocpu_in_g_bs + ) + if hasattr(shape.memory_options, "min_in_g_bs"): + memory_info["memory_min"] = shape.memory_options.min_in_g_bs + if hasattr(shape.memory_options, "max_in_g_bs"): + memory_info["memory_max"] = shape.memory_options.max_in_g_bs + + return memory_info + + +def extract_ocpu_info(shape): + """ + Extract OCPU information from shape data. + + Args: + shape: Shape object from OCI API + + Returns: + dict: Dictionary with ocpus and optional flex OCPU ranges + """ + ocpu_info = { + "ocpus": 0, + } + + if hasattr(shape, "ocpus"): + ocpu_info["ocpus"] = shape.ocpus + elif hasattr(shape, "ocpu_options"): + # Flex shapes have OCPU options + if hasattr(shape.ocpu_options, "min"): + ocpu_info["ocpus"] = shape.ocpu_options.min + ocpu_info["ocpu_min"] = shape.ocpu_options.min + if hasattr(shape.ocpu_options, "max"): + ocpu_info["ocpu_max"] = shape.ocpu_options.max + + return ocpu_info + + +def extract_network_info(shape): + """ + Extract network bandwidth information from shape data. + + Args: + shape: Shape object from OCI API + + Returns: + str: Network bandwidth description + """ + if hasattr(shape, "networking_bandwidth_in_gbps"): + return f"{shape.networking_bandwidth_in_gbps} Gbps" + elif hasattr(shape, "max_vnic_attachments"): + return f"{shape.max_vnic_attachments} VNICs" + return "Not specified" + + +def extract_storage_info(shape): + """ + Extract storage information from shape data. + + Args: + shape: Shape object from OCI API + + Returns: + str: Storage description + """ + if hasattr(shape, "local_disks") and shape.local_disks > 0: + disk_size = getattr(shape, "local_disks_total_size_in_gbs", 0) + return f"{disk_size} GB local storage ({shape.local_disks} disks)" + return "Block storage only" + + +def extract_shape_info(shape): + """ + Extract detailed information from a single shape object. + + Args: + shape: Shape object from OCI API + + Returns: + dict: Dictionary containing shape information + """ + shape_name = shape.shape + + # Extract various aspects of the shape + cpu_isa = extract_cpu_architecture(shape) + gpu_info = get_gpu_info(shape) + memory_info = extract_memory_info(shape) + ocpu_info = extract_ocpu_info(shape) + network_bandwidth = extract_network_info(shape) + storage = extract_storage_info(shape) + + # Build the hardware info dictionary + hardware_info = { + "shape_name": shape_name, + "ocpus": ocpu_info["ocpus"] if ocpu_info["ocpus"] > 0 else "Flexible", + "memory_gb": memory_info["memory_gb"] + if memory_info["memory_gb"] > 0 + else "Flexible", + "cpu_isa": cpu_isa, + "gpu": gpu_info, + "network_performance": network_bandwidth, + "storage": storage, + "is_flex": ".Flex" in shape_name or shape_name.endswith(".Flex"), + "is_bare_metal": shape_name.startswith("BM."), + "is_catalog_shape": getattr(shape, "is_catalog_shape", False), + } + + # Add flex shape ranges if available + for key in ["ocpu_min", "ocpu_max"]: + if key in ocpu_info: + hardware_info[key] = ocpu_info[key] + + for key in [ + "memory_min", + "memory_max", + "memory_per_ocpu_min", + "memory_per_ocpu_max", + ]: + if key in memory_info: + hardware_info[key] = memory_info[key] + + # Add processor description if available + if hasattr(shape, "processor_description"): + hardware_info["processor"] = shape.processor_description + + return hardware_info + + +def get_shape_family_info(family_name, shapes, region, quiet=False): + """ + Get shape information for a specific OCI shape family. + + Args: + family_name (str): Shape family name (e.g., 'VM.Standard.E4', 'BM.Standard2') + shapes (list): List of all shapes + region (str): OCI region being queried + quiet (bool): Suppress debug messages + + Returns: + list: List of dictionaries containing shape information + """ + family_shapes = [] + + for shape in shapes: + shape_name = shape.shape + + # Match shapes that belong to this family + if shape_name.startswith(family_name): + family_shapes.append(shape) + + if not family_shapes: + if not quiet: + print(f"No shapes found starting with '{family_name}'.", file=sys.stderr) + return [] + + if not quiet: + print( + f"Found {len(family_shapes)} shapes in family '{family_name}'", + file=sys.stderr, + ) + + shape_info = [] + seen_shapes = set() + + for shape in family_shapes: + shape_name = shape.shape + + # Skip duplicate shape names (OCI API may return same shape multiple times) + if shape_name in seen_shapes: + continue + seen_shapes.add(shape_name) + + # Get processor architecture + cpu_isa = "x86_64" # Default + if hasattr(shape, "processor_description"): + proc_desc = shape.processor_description.lower() + if "arm" in proc_desc or "ampere" in proc_desc: + cpu_isa = "arm64" + elif "amd" in proc_desc or "intel" in proc_desc: + cpu_isa = "x86_64" + + # Shape naming patterns for ARM detection + if "A1" in shape_name or "A2" in shape_name: + cpu_isa = "arm64" + + gpu_info = get_gpu_info(shape) + + # Get memory in GB + memory_gb = 0 + memory_min = None + memory_max = None + memory_per_ocpu_min = None + memory_per_ocpu_max = None + if hasattr(shape, "memory_in_gbs"): + memory_gb = shape.memory_in_gbs + elif hasattr(shape, "memory_options"): + # Flex shapes have memory options + if hasattr(shape.memory_options, "default_per_ocpu_in_g_bs"): + # For flex shapes, use a default OCPU count to show typical memory + default_ocpus = 1 + if hasattr(shape, "ocpus"): + default_ocpus = shape.ocpus + memory_gb = ( + shape.memory_options.default_per_ocpu_in_g_bs * default_ocpus + ) + # Extract min/max memory per OCPU for flex shapes + if hasattr(shape.memory_options, "min_per_ocpu_in_g_bs"): + memory_per_ocpu_min = shape.memory_options.min_per_ocpu_in_g_bs + if hasattr(shape.memory_options, "max_per_ocpu_in_g_bs"): + memory_per_ocpu_max = shape.memory_options.max_per_ocpu_in_g_bs + if hasattr(shape.memory_options, "min_in_g_bs"): + memory_min = shape.memory_options.min_in_g_bs + if hasattr(shape.memory_options, "max_in_g_bs"): + memory_max = shape.memory_options.max_in_g_bs + + # Get OCPU count + ocpus = 0 + ocpu_min = None + ocpu_max = None + if hasattr(shape, "ocpus"): + ocpus = shape.ocpus + elif hasattr(shape, "ocpu_options"): + # Flex shapes have OCPU options + if hasattr(shape.ocpu_options, "min"): + ocpus = shape.ocpu_options.min + ocpu_min = shape.ocpu_options.min + if hasattr(shape.ocpu_options, "max"): + ocpu_max = shape.ocpu_options.max + + # Network bandwidth + network_bandwidth = "Not specified" + if hasattr(shape, "networking_bandwidth_in_gbps"): + network_bandwidth = f"{shape.networking_bandwidth_in_gbps} Gbps" + elif hasattr(shape, "max_vnic_attachments"): + network_bandwidth = f"{shape.max_vnic_attachments} VNICs" + + # Storage + storage = "Block storage only" + if hasattr(shape, "local_disks") and shape.local_disks > 0: + disk_size = getattr(shape, "local_disks_total_size_in_gbs", 0) + storage = f"{disk_size} GB local storage ({shape.local_disks} disks)" + + hardware_info = { + "shape_name": shape_name, + "ocpus": ocpus if ocpus > 0 else "Flexible", + "memory_gb": memory_gb if memory_gb > 0 else "Flexible", + "cpu_isa": cpu_isa, + "gpu": gpu_info, + "network_performance": network_bandwidth, + "storage": storage, + "is_flex": ".Flex" in shape_name or shape_name.endswith(".Flex"), + "is_bare_metal": shape_name.startswith("BM."), + "is_catalog_shape": getattr(shape, "is_catalog_shape", False), + } + + # Add flex shape ranges if available + if ocpu_min is not None: + hardware_info["ocpu_min"] = ocpu_min + if ocpu_max is not None: + hardware_info["ocpu_max"] = ocpu_max + if memory_min is not None: + hardware_info["memory_min"] = memory_min + if memory_max is not None: + hardware_info["memory_max"] = memory_max + if memory_per_ocpu_min is not None: + hardware_info["memory_per_ocpu_min"] = memory_per_ocpu_min + if memory_per_ocpu_max is not None: + hardware_info["memory_per_ocpu_max"] = memory_per_ocpu_max + + # Add processor description if available + if hasattr(shape, "processor_description"): + hardware_info["processor"] = shape.processor_description + + shape_info.append(hardware_info) + + # Sort by memory size (handling 'Flexible' string) + def sort_key(x): + mem = x["memory_gb"] + return (0, 0) if mem == "Flexible" else (1, float(mem)) + + return sorted(shape_info, key=sort_key) + + +def group_shapes_by_type(shapes, region): + """ + Group shapes by type (flex, fixed, bare_metal). + + Args: + shapes (list): List of all shapes + region (str): OCI region being queried + + Returns: + dict: Dictionary with 'flex', 'fixed', and 'bare_metal' keys containing shape lists + """ + flex_shapes = [] + fixed_shapes = [] + bare_metal_shapes = [] + seen_shapes = set() + + for shape in shapes: + shape_name = shape.shape + + # Skip duplicate shape names + if shape_name in seen_shapes: + continue + seen_shapes.add(shape_name) + + # Extract shape information directly (O(1) operation per shape) + info = extract_shape_info(shape) + + # Categorize by type + if info["is_flex"]: + flex_shapes.append(info) + elif info["is_bare_metal"]: + bare_metal_shapes.append(info) + else: + # Fixed shapes: VM shapes that are not flex + if shape_name.startswith("VM."): + fixed_shapes.append(info) + + # Sort shapes within each category + def sort_key(x): + # Sort by shape name + return x["shape_name"] + + flex_shapes.sort(key=sort_key) + fixed_shapes.sort(key=sort_key) + bare_metal_shapes.sort(key=sort_key) + + return { + "flex": flex_shapes, + "fixed": fixed_shapes, + "bare_metal": bare_metal_shapes, + } + + +def output_shapes_kconfig(shapes, region): + """Output shapes menu in Kconfig format.""" + environment = get_jinja2_environment() + + # Output the top-level choice menu (GENERIC, FLEX, FIXED, BARE_METAL) + template = environment.get_template("shape_families.j2") + print(template.render()) + print() + + # Output the GENERIC family submenu + template = environment.get_template("generic_family.j2") + print(template.render()) + print() + + # Group shapes by type + shape_groups = group_shapes_by_type(shapes, region) + + # Output FLEX shapes submenu + if shape_groups["flex"]: + template = environment.get_template("flex_shapes.j2") + print(template.render(shapes=shape_groups["flex"])) + print() + + # Output FIXED shapes submenu + if shape_groups["fixed"]: + template = environment.get_template("fixed_shapes.j2") + print(template.render(shapes=shape_groups["fixed"])) + print() + + # Output BARE_METAL shapes submenu + if shape_groups["bare_metal"]: + template = environment.get_template("bare_metal_shapes.j2") + print(template.render(shapes=shape_groups["bare_metal"])) + print() + + +def output_families_kconfig(shapes): + """Output shape families in Kconfig format.""" + families = parse_all_shape_families(shapes) + sorted_families = sorted(families.values(), key=lambda x: x["family_name"]) + + environment = get_jinja2_environment() + + template = environment.get_template("shape_families.j2") + print( + template.render( + sorted_families=sorted_families, + ) + ) + + +def output_families_raw(shapes, region, quiet=False): + """Output available shape families in table format.""" + families = parse_all_shape_families(shapes) + + if not quiet: + print(f"Available shape families in {region}:\n") + + print(f"{'Family':<25} {'Count':<6} {'GPU':<5} {'Type':<12} {'Architectures':<20}") + print("-" * 75) + + sorted_families = sorted(families.values(), key=lambda x: x["family_name"]) + has_any_catalog = False + for family in sorted_families: + gpu_indicator = "Yes" if family["has_gpu"] else "No" + architectures = ", ".join(family["architectures"]) + + shape_type = [] + if family["is_flex"]: + shape_type.append("Flex") + if family["is_bare_metal"]: + shape_type.append("Bare Metal") + if not shape_type: + shape_type.append("Fixed") + shape_type_str = ", ".join(shape_type) + + family_name = family["family_name"] + if family.get("has_catalog_shapes", False): + family_name = family_name + " *" + has_any_catalog = True + + print( + f"{family_name:<25} " + f"{family['shape_count']:<6} " + f"{gpu_indicator:<5} " + f"{shape_type_str:<12} " + f"{architectures:<20}" + ) + + if has_any_catalog: + print("\n* Contains catalog shapes - may require service limit increases") + + if not quiet: + print(f"\nFound {len(families)} shape families", file=sys.stderr) + + +def output_family_kconfig(family_name, shapes): + """Output results in kconfig format.""" + environment = get_jinja2_environment() + template = environment.get_template("shape_family.j2") + print( + template.render( + family_name=family_name.upper().replace(".", "_").replace("-", "_"), + shapes=shapes, + ) + ) + + +def output_family_raw(shapes, quiet=False): + """Output results in table format.""" + if not quiet: + print(f"Found {len(shapes)} shapes:\n") + + print( + f"{'Shape Name':<30} {'OCPUs':<10} {'Memory (GB)':<15} {'CPU ISA':<10} {'GPU':<25} {'Storage':<30}" + ) + print("-" * 130) + + for shape in shapes: + shape_name = shape["shape_name"] + if shape.get("is_catalog_shape", False): + shape_name = shape_name + " *" + print( + f"{shape_name:<30} " + f"{str(shape['ocpus']):<10} " + f"{str(shape['memory_gb']):<15} " + f"{shape['cpu_isa']:<10} " + f"{shape['gpu']:<25} " + f"{shape['storage']:<30}" + ) + + # Add note about catalog shapes if any are present + has_catalog = any(shape.get("is_catalog_shape", False) for shape in shapes) + if has_catalog: + print("\n* Catalog shape - may require service limit increases") + + +def parse_arguments(): + """Parse command line arguments.""" + parser = argparse.ArgumentParser( + description="Get OCI compute shape information including hardware specs", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Generate Kconfig from all subscribed regions (default) + python %(prog)s > ../kconfigs/Kconfig.shapes + + # Include catalog shapes (DenseIO, GPU, etc.) + python %(prog)s --include-catalog > ../kconfigs/Kconfig.shapes + + # Query specific shape family + python %(prog)s VM.Standard.E4 + + # List all available families + python %(prog)s --families --format raw + + # Query specific region only + python %(prog)s --region us-chicago-1 --families + """, + ) + parser.add_argument( + "family_name", + nargs="?", # Make family_name optional when using --families + help="Shape family name (e.g., VM.Standard.E4, VM.Standard3, BM.Standard2)", + ) + + parser.add_argument( + "--families", action="store_true", help="List all available shape families" + ) + parser.add_argument( + "--include-catalog", + action="store_true", + help="Include well-known shapes from catalog (DenseIO, GPU shapes) that may require service limits", + ) + parser.add_argument( + "--format", + "-f", + choices=["raw", "kconfig"], + default="kconfig", + help="Output format (default: kconfig)", + ) + parser.add_argument( + "--quiet", "-q", action="store_true", help="Suppress informational messages" + ) + parser.add_argument( + "--region", + "-r", + help="Query specific region only (default: aggregate from all subscribed regions)", + ) + return parser.parse_args() + + +def main(): + """Main function to run the program.""" + args = parse_arguments() + + compartment_ocid = get_default_compartment() + if not compartment_ocid: + print("Error: Could not determine compartment OCID", file=sys.stderr) + sys.exit(1) + + # Determine which regions to query + if args.region: + # Query specific region only + regions = [args.region] + region_desc = args.region + else: + # Query all subscribed regions (default) + regions = get_subscribed_regions(args.quiet) + region_desc = "all subscribed regions" + + # Get shapes from OCI API + shapes = get_all_shapes(compartment_ocid, regions, args.quiet) + if not shapes: + sys.exit(1) + + # Optionally merge with catalog shapes + if args.include_catalog: + shapes = merge_catalog_shapes(shapes, args.quiet) + + if args.families: + if args.format == "kconfig": + output_families_kconfig(shapes) + else: + output_families_raw(shapes, region_desc, args.quiet) + return + + if args.family_name: + if not args.quiet: + print( + f"Fetching information for the {args.family_name} family...", + file=sys.stderr, + ) + + family_shapes = get_shape_family_info( + args.family_name, shapes, region_desc, args.quiet + ) + + if not family_shapes: + print(f"No shapes found for family '{args.family_name}'.", file=sys.stderr) + print( + "Try running with --families to see available shape families.", + file=sys.stderr, + ) + sys.exit(1) + + if args.format == "kconfig": + output_family_kconfig(args.family_name, family_shapes) + else: + output_family_raw(family_shapes, args.quiet) + return + + output_shapes_kconfig(shapes, region_desc) + + +if __name__ == "__main__": + main() diff --git a/terraform/oci/scripts/generic_family.j2 b/terraform/oci/scripts/generic_family.j2 new file mode 100644 index 000000000..0833f75eb --- /dev/null +++ b/terraform/oci/scripts/generic_family.j2 @@ -0,0 +1,51 @@ +if TERRAFORM_OCI_SHAPE_FAMILY_GENERIC + +choice + prompt "OCI shape" + default TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC + help + Select the basic hardware capabilities that are in each + instance. + +config TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC + bool "VM.Standard.x86.Generic" + depends on TARGET_ARCH_X86_64 + help + Generic x86 shape that lets you customize CPU and memory + without choosing a specific CPU generation. + +endchoice + +config TERRAFORM_OCI_SHAPE + string + output yaml + default "VM.Standard.x86.Generic" if TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC + +config TERRAFORM_OCI_INSTANCE_FLEX_OCPUS + int "Instance CPU count" + output yaml + default 2 + help + An Oracle CPU (OCPU) represents a physical CPU core and is + the unit of measurement for CPUs on x86 CPUs (AMD and + Intel) and Arm CPUs (OCI Ampere Compute). A virtual CPU + (vCPU), the industry-standard for measuring compute + resources, represents one execution thread of a physical + CPU core. + + Most CPU architectures, including x86, run two threads + per physical core, so one OCPU is the equal of two vCPUs + for x86-based compute. For OCI Compute, the minimum unit + of provisioning starts from one OCPU on both X86 (Intel + and AMD) and OCI Ampere Compute processors. + +config TERRAFORM_OCI_INSTANCE_FLEX_MEMORY_IN_GBS + int "Instance memory size" + output yaml + default 4 + help + Memory per instance, in GiBs. The minimum value for this + setting is a multiple of the number of OCPUs in each + instance. + +endif # TERRAFORM_OCI_SHAPE_FAMILY_GENERIC diff --git a/terraform/oci/scripts/shape_families.j2 b/terraform/oci/scripts/shape_families.j2 new file mode 100644 index 000000000..fffa4c1dd --- /dev/null +++ b/terraform/oci/scripts/shape_families.j2 @@ -0,0 +1,44 @@ +choice + prompt "OCI shape family" + default TERRAFORM_OCI_SHAPE_FAMILY_FLEX + help + This option selects the class of virtual hardware (CPUs and + memory) to provision for each target node. Most CPU + architectures, including x86, run two threads per physical + core, so one OCPU is the equal of two vCPUs for x86-based + compute. + + Which shapes are available is limited by your subscription + and what hardware has been deployed in your selected region. + +config TERRAFORM_OCI_SHAPE_FAMILY_GENERIC + bool "Generic shapes" + help + These shapes are recommended for developers who do not + require a specific model of CPU for their workflows. + +config TERRAFORM_OCI_SHAPE_FAMILY_FLEX + bool "Flex shapes" + help + A flexible shape is a virtual machine that lets you + customize the number of OCPUs and the amount of memory + per instance. The network bandwidth and number of VNICs + scale proportionately with the number of OCPUs. + +config TERRAFORM_OCI_SHAPE_FAMILY_FIXED + bool "Fixed shapes" + help + A fixed shape is a virtual machine with a predetermined + number of OCPUs and amount of memory. These shapes offer + consistent performance characteristics with configurations + optimized for common workload patterns. + +config TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL + bool "Bare metal" + help + A bare metal shape is a whole physical machine without + virtualization. This gives deterministic performance + characteristics but is less configurable than a flex + shape. + +endchoice diff --git a/terraform/oci/scripts/shape_family.j2 b/terraform/oci/scripts/shape_family.j2 new file mode 100644 index 000000000..ec0c762ca --- /dev/null +++ b/terraform/oci/scripts/shape_family.j2 @@ -0,0 +1,57 @@ +if TERRAFORM_OCI_SHAPE_FAMILY_{{ family_name }} + +choice + prompt "Shape type" + default TERRAFORM_OCI_SHAPE_{{ shapes[0]['shape_name'].upper().replace('.', '_').replace('-', '_') }} + help + Select the specific shape configuration within this family. + Each shape provides different combinations of OCPUs, memory, + storage, and networking capacity. + +{% for shape in shapes %} +config TERRAFORM_OCI_SHAPE_{{ shape['shape_name'].upper().replace('.', '_').replace('-', '_') }} + bool "{{ shape['shape_name'] }}" +{% if 'x86_64' in shape['cpu_isa'] %} + depends on TARGET_ARCH_X86_64 +{% elif 'arm64' in shape['cpu_isa'] %} + depends on TARGET_ARCH_ARM64 +{% endif %} + help +{% if shape['is_flex'] %} + Flexible shape: OCPU and memory can be customized. +{% else %} + OCPU count: {{ shape['ocpus'] }} + Memory: {{ shape['memory_gb'] }} GB +{% endif %} + Architecture: {{ shape['cpu_isa'] }} + Network: {{ shape['network_performance'] }} +{% if shape['storage'] != 'Block storage only' %} + Local storage: {{ shape['storage'] }} +{% endif %} +{% if shape['gpu'] != 'None' %} + GPU: {{ shape['gpu'] }} +{% endif %} +{% if shape['is_bare_metal'] %} + Bare metal instance. +{% endif %} +{% if 'processor' in shape %} + Processor: {{ shape['processor'] }} +{% endif %} +{% if shape['is_catalog_shape'] %} + + NOTE: This shape may require service limit increases and may not + be available in all regions. Contact Oracle support to request + access if needed. +{% endif %} + +{% endfor %} +endchoice + +config TERRAFORM_OCI_SHAPE + string + output yaml +{% for shape in shapes %} + default "{{ shape['shape_name'] }}" if TERRAFORM_OCI_SHAPE_{{ shape['shape_name'].upper().replace('.', '_').replace('-', '_') }} +{% endfor %} + +endif # TERRAFORM_OCI_SHAPE_FAMILY_{{ family_name }} From 167d8babc869410e92573d38744b0eebb90b61b5 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 21 Oct 2025 16:01:36 -0400 Subject: [PATCH 08/11] Add Kconfig.shape.generated to generate_cloud_configs.py Teach "make cloud-config" and "make cloud-config-oci" to update the Kconfig.shape menu with dynamically discovered information. This information is based on what resources are available to the user's tenancy and region subscription. This support is intended to work like the reference implementation under terraform/lambdalabs/ Signed-off-by: Chuck Lever --- .gitignore | 1 + scripts/dynamic-cloud-kconfig.Makefile | 3 +- scripts/generate_cloud_configs.py | 1 + terraform/oci/Kconfig | 2 +- terraform/oci/kconfigs/Kconfig.shape | 274 ------------------------- 5 files changed, 5 insertions(+), 276 deletions(-) delete mode 100644 terraform/oci/kconfigs/Kconfig.shape diff --git a/.gitignore b/.gitignore index ad6202208..76c297edf 100644 --- a/.gitignore +++ b/.gitignore @@ -123,6 +123,7 @@ terraform/aws/kconfigs/Kconfig.location.generated terraform/aws/scripts/__pycache__/ terraform/oci/kconfigs/Kconfig.location.generated +terraform/oci/kconfigs/Kconfig.shape.generated terraform/oci/scripts/__pycache__/ .cloud.initialized diff --git a/scripts/dynamic-cloud-kconfig.Makefile b/scripts/dynamic-cloud-kconfig.Makefile index 07dc578a7..72ec94a54 100644 --- a/scripts/dynamic-cloud-kconfig.Makefile +++ b/scripts/dynamic-cloud-kconfig.Makefile @@ -23,8 +23,9 @@ AWS_KCONFIGS := $(AWS_KCONFIG_AMI) $(AWS_KCONFIG_INSTANCE) $(AWS_KCONFIG_LOCATIO # OCI dynamic configuration OCI_KCONFIG_DIR := terraform/oci/kconfigs OCI_KCONFIG_LOCATION := $(OCI_KCONFIG_DIR)/Kconfig.location.generated +OCI_KCONFIG_SHAPE := $(OCI_KCONFIG_DIR)/Kconfig.shape.generated -OCI_KCONFIGS := $(OCI_KCONFIG_LOCATION) +OCI_KCONFIGS := $(OCI_KCONFIG_LOCATION) $(OCI_KCONFIG_SHAPE) # Add generated files to mrproper clean list KDEVOPS_MRPROPER += $(LAMBDALABS_KCONFIGS) $(AWS_KCONFIGS) $(OCI_KCONFIGS) diff --git a/scripts/generate_cloud_configs.py b/scripts/generate_cloud_configs.py index e9953c42e..20041d6b7 100755 --- a/scripts/generate_cloud_configs.py +++ b/scripts/generate_cloud_configs.py @@ -160,6 +160,7 @@ def generate_oci_kconfig() -> bool: # Define the script-to-output mapping scripts_to_run = [ ("gen_kconfig_location", "Kconfig.location.generated"), + ("gen_kconfig_shape", "Kconfig.shape.generated"), ] all_success = True diff --git a/terraform/oci/Kconfig b/terraform/oci/Kconfig index d2c00c428..aabb751b1 100644 --- a/terraform/oci/Kconfig +++ b/terraform/oci/Kconfig @@ -11,7 +11,7 @@ source "terraform/oci/kconfigs/Kconfig.location.generated" endmenu menu "Compute" comment "Shape selection" -source "terraform/oci/kconfigs/Kconfig.shape" +source "terraform/oci/kconfigs/Kconfig.shape.generated" comment "OS image selection" source "terraform/oci/kconfigs/Kconfig.image" endmenu diff --git a/terraform/oci/kconfigs/Kconfig.shape b/terraform/oci/kconfigs/Kconfig.shape deleted file mode 100644 index 5d719d0c3..000000000 --- a/terraform/oci/kconfigs/Kconfig.shape +++ /dev/null @@ -1,274 +0,0 @@ -choice - prompt "OCI shape family" - default TERRAFORM_OCI_SHAPE_FAMILY_FLEX - help - This option selects the class of virtual hardware (CPUs and - memory) to provision for each target node. Most CPU - architectures, including x86, run two threads per physical - core, so one OCPU is the equal of two vCPUs for x86-based - compute. - - Which shapes are available is limited by your subscription - and what hardware has been deployed in your selected region. - -config TERRAFORM_OCI_SHAPE_FAMILY_GENERIC - bool "Generic shapes" - help - These shapes are recommended for developers who do not - require a specific model of CPU for their workflows. - -config TERRAFORM_OCI_SHAPE_FAMILY_FLEX - bool "Flex shapes" - help - A flexible shape is a virtual machine that lets you - customize the number of OCPUs and the amount of memory - per instance. The network bandwidth and number of VNICs - scale proportionately with the number of OCPUs. - -config TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL - bool "Bare metal" - help - A bare metal shape is a whole physical machine without - virtualization. This gives deterministic performance - characteristics but is less configurable than a flex - shape. - -endchoice - -if TERRAFORM_OCI_SHAPE_FAMILY_GENERIC - -choice - prompt "OCI shape" - default TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC - help - Select the basic hardware capabilities that are in each - instance. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC - bool "VM.Standard.x86.Generic" - depends on TARGET_ARCH_X86_64 - -endchoice - -config TERRAFORM_OCI_SHAPE - string - output yaml - default "VM.Standard.x86.Generic" if TERRAFORM_OCI_SHAPE_VM_STANDARD_X86_GENERIC - -config TERRAFORM_OCI_INSTANCE_FLEX_OCPUS - int "Instance CPU count" - output yaml - default 2 - help - The Oracle CPU (OCPU) represents physical CPU cores and is - the unit of measurement for CPUs on x86 CPUs (AMD and - Intel) and Arm CPUs (OCI Ampere Compute). A virtual CPU - (vCPU), the industry-standard for measuring compute - resources, represents one execution thread of a physical - CPU core. - - Most CPU architectures, including x86, runs two threads - per physical core, so one OCPU is the equal of two vCPUs - for x86-based compute. For OCI Compute, the minimum unit - of provisioning starts from one OCPU on both X86 (Intel - and AMD) and OCI Ampere Compute processors. - -config TERRAFORM_OCI_INSTANCE_FLEX_MEMORY_IN_GBS - int "Instance memory size" - output yaml - default 4 - help - Memory per instance, in GiBs. The minimum value for this - setting is a multiple of the number of OCPUS in each - instance. - -endif # TERRAFORM_OCI_SHAPE_FAMILY_GENERIC - -if TERRAFORM_OCI_SHAPE_FAMILY_FLEX - -choice - prompt "OCI shape" - default TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX - help - Select the basic hardware capabilities that are in each - instance. For more detail, see: - - https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#flexible - -config TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX - bool "VM.Standard3.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each guest with between 1 - and 32 OCPUs (physical cores) and up to 512MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_E4_FLEX - bool "VM.Standard.E4.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each guest with between 1 - and 114 OCPUs (physical AMD cores) and up to 1760MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_E5_FLEX - bool "VM.Standard.E5.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each guest with between 1 - and 94 OCPUs (physical AMD cores) and up to 1048MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_A1_FLEX - bool "VM.Standard.A1.Flex" - depends on TARGET_ARCH_ARM64 - help - Selecting this option provisions each guest with between 1 - and 80 OCPUs (physical ARM cores) and up to 512MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_STANDARD_A2_FLEX - bool "VM.Standard.A2.Flex" - depends on TARGET_ARCH_ARM64 - help - Selecting this option provisions each guest with between 1 - and 78 OCPUs (physical ARM cores) and up to 946MB of memory. - -config TERRAFORM_OCI_SHAPE_VM_DENSEIO_E4_FLEX - bool "VM.DenseIO.E4.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each instance with either - 8 OCPUs and 128 GB memory, 16 OCPUs and 256 GB memory, or - 32 OCPUs and 512 GB memory. CPUs are based on the AMD - x86_64 platform. - -config TERRAFORM_OCI_SHAPE_VM_OPTIMIZED3_FLEX - bool "VM.Optimized3.Flex" - depends on TARGET_ARCH_X86_64 - help - Selecting this option provisions each instance with up to - 18 OCPUS. The memory provisioned for each instance is - typically matches a multiple of the number of OCPUS. - -endchoice - -config TERRAFORM_OCI_SHAPE - string - output yaml - default "VM.Standard3.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD3_FLEX - default "VM.Standard.E4.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_E4_FLEX - default "VM.Standard.E5.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_E5_FLEX - default "VM.Standard.A1.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_A1_FLEX - default "VM.Standard.A2.Flex" if TERRAFORM_OCI_SHAPE_VM_STANDARD_A2_FLEX - default "VM.DenseIO.E4.Flex" if TERRAFORM_OCI_SHAPE_VM_DENSEIO_E4_FLEX - default "VM.Optimized3.Flex" if TERRAFORM_OCI_SHAPE_VM_OPTIMIZED3_FLEX - -config TERRAFORM_OCI_INSTANCE_FLEX_OCPUS - int "Instance CPU count" - output yaml - default 2 - help - The Oracle CPU (OCPU) represents physical CPU cores and is - the unit of measurement for CPUs on x86 CPUs (AMD and - Intel) and Arm CPUs (OCI Ampere Compute). A virtual CPU - (vCPU), the industry-standard for measuring compute - resources, represents one execution thread of a physical - CPU core. - - Most CPU architectures, including x86, runs two threads - per physical core, so one OCPU is the equal of two vCPUs - for x86-based compute. For OCI Compute, the minimum unit - of provisioning starts from one OCPU on both X86 (Intel - and AMD) and OCI Ampere Compute processors. - -config TERRAFORM_OCI_INSTANCE_FLEX_MEMORY_IN_GBS - int "Instance memory size" - output yaml - default 4 - help - Memory per instance, in GiBs. The minimum value for this - setting is a multiple of the number of OCPUS in each - instance. - -endif # TERRAFORM_OCI_SHAPE_FAMILY_FLEX - -if TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL - -choice - prompt "OCI shape" - default TERRAFORM_OCI_SHAPE_BM_STANDARD3 - help - Select the basic hardware capabilities that are in each - instance. For more details, see: - - https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm#baremetalshapes - -config TERRAFORM_OCI_SHAPE_BM_STANDARD3 - bool "BM.Standard3" - depends on TARGET_ARCH_X86_64 - help - X9-based standard compute. Processor: Intel Xeon Platinum - 8358. Base frequency 2.6 GHz, max turbo frequency 3.4 GHz. - -config TERRAFORM_OCI_SHAPE_BM_STANDARD_E4 - bool "BM.Standard.E4" - depends on TARGET_ARCH_X86_64 - help - E4-based standard compute. Processor: AMD EPYC 7J13. Base - frequency 2.55 GHz, max boost frequency 3.5 GHz. - -config TERRAFORM_OCI_SHAPE_BM_STANDARD_E5 - bool "BM.Standard.E5" - depends on TARGET_ARCH_X86_64 - help - E5-based standard compute. Processor: AMD EPYC 9J14. Base - frequency 2.4 GHz, max boost frequency 3.7 GHz. - -config TERRAFORM_OCI_SHAPE_BM_STANDARD_A1 - bool "BM.Standard.A1" - depends on TARGET_ARCH_ARM64 - help - OCI Ampere A1 Compute Arm-based standard compute. Each - OCPU corresponds to a single hardware execution thread. - Processor: Ampere Altra Q80-30. Max frequency 3.0 GHz. - -config TERRAFORM_OCI_SHAPE_BM_DENSEIO_E4 - bool "BM.DenseIO.E4" - depends on TARGET_ARCH_X86_64 - help - E4-based dense I/O compute. Processor: AMD EPYC 7J13. - Base frequency 2.55 GHz, max boost frequency 3.5 GHz. - -config TERRAFORM_OCI_SHAPE_BM_DENSEIO_E5 - bool "BM.DenseIO.E5" - depends on TARGET_ARCH_X86_64 - help - E5-based dense I/O compute. Processor: AMD EPYC 9J14. - Base frequency 2.4 GHz, max boost frequency 3.7 GHz. - -config TERRAFORM_OCI_SHAPE_BM_OPTIMIZED3 - bool "BM.Optimized3" - depends on TARGET_ARCH_X86_64 - help - Processor: Intel Xeon 6354. Base frequency 3.0 GHz, max - turbo frequency 3.6 GHz. - -config TERRAFORM_OCI_SHAPE_BM_HPC_E5 - bool "BM.HPC.E5" - depends on TARGET_ARCH_X86_64 - help - Processor: AMD EPYC 9J14. Base frequency 2.4 GHz, max - boost frequency 3.7 GHz. - -endchoice - -config TERRAFORM_OCI_SHAPE - string - output yaml - default "BM.Standard3" if TERRAFORM_OCI_SHAPE_BM_STANDARD3 - default "BM.Standard.E4" if TERRAFORM_OCI_SHAPE_BM_STANDARD_E4 - default "BM.Standard.E5" if TERRAFORM_OCI_SHAPE_BM_STANDARD_E5 - default "BM.Standard.A1" if TERRAFORM_OCI_SHAPE_BM_STANDARD_A1 - default "BM.DenseIO.E4" if TERRAFORM_OCI_SHAPE_BM_DENSEIO_E4 - default "BM.DenseIO.E5" if TERRAFORM_OCI_SHAPE_BM_DENSEIO_E5 - default "BM.Optimized3" if TERRAFORM_OCI_SHAPE_BM_OPTIMIZED3 - default "BM.HPC.E5" if TERRAFORM_OCI_SHAPE_BM_HPC_E5 - -endif # TERRAFORM_OCI_SHAPE_FAMILY_BARE_METAL From 39b2105ecd45b19a6429f4b4f3cc2ba29427dbd8 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sun, 19 Oct 2025 12:02:20 -0400 Subject: [PATCH 09/11] terraform/oci: Remove the kconfigs/images subdirectory Instead of sourcing files in a subdirectory, move the content of those files right into Kconfig.images. This will make it easier to examine the differences between the current menu content and the dynamically-generated content. Signed-off-by: Chuck Lever --- terraform/oci/kconfigs/Kconfig.image | 500 +++++++++++++++++- .../oci/kconfigs/images/Kconfig.OracleLinux | 312 ----------- terraform/oci/kconfigs/images/Kconfig.Ubuntu | 162 ------ terraform/oci/kconfigs/images/Kconfig.custom | 20 - 4 files changed, 497 insertions(+), 497 deletions(-) delete mode 100644 terraform/oci/kconfigs/images/Kconfig.OracleLinux delete mode 100644 terraform/oci/kconfigs/images/Kconfig.Ubuntu delete mode 100644 terraform/oci/kconfigs/images/Kconfig.custom diff --git a/terraform/oci/kconfigs/Kconfig.image b/terraform/oci/kconfigs/Kconfig.image index b67165db3..5bce58255 100644 --- a/terraform/oci/kconfigs/Kconfig.image +++ b/terraform/oci/kconfigs/Kconfig.image @@ -33,6 +33,500 @@ config TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM endchoice -source "terraform/oci/kconfigs/images/Kconfig.OracleLinux" -source "terraform/oci/kconfigs/images/Kconfig.Ubuntu" -source "terraform/oci/kconfigs/images/Kconfig.custom" +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX + +choice + prompt "OS release" + default TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_ARM64 if TARGET_ARCH_ARM64 + default TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_X86 if TARGET_ARCH_X86_64 + help + Select the release of Oracle Linux to install on each + instance. + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_X86 + bool "Oracle Linux 7.9 (x86)" + depends on TARGET_ARCH_X86_64 + help + (extended support) Oracle-Linux-7.9-2025.01.31-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oraclelinux-7x/oracle-linux-7-9-2025-01-31-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_GPU + bool "Oracle Linux 7.9 Gen2 GPU" + depends on TARGET_ARCH_X86_64 + help + (extended support) Oracle-Linux-7.9-Gen2-GPU-2025.01.31-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oraclelinux-7x/oracle-linux-7-9-gen2-gpu-2025-01-31-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_ARM64 + bool "Oracle Linux 7.9 (aarch64)" + depends on TARGET_ARCH_ARM64 + help + (extended support) Oracle-Linux-7.9-aarch64-2024.11.30-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oraclelinux-7x/oracle-linux-7-9-aarch64-2024-11-30-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_GPU + bool "Oracle Linux 8.10 Gen2 GPU" + depends on TARGET_ARCH_X86_64 + help + Oracle-Linux-8.10-Gen2-GPU-2025.03.18-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-8x/oracle-linux-8-10-gen2-gpu-2025-03-18-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_ARM64 + bool "Oracle Linux 8.10 (aarch64)" + depends on TARGET_ARCH_ARM64 + help + Oracle-Linux-8.10-aarch64-2025.03.18-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-8x/oracle-linux-8-10-aarch64-2025-03-18-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_X86 + bool "Oracle Linux 8.10 (x86)" + depends on TARGET_ARCH_X86_64 + help + Oracle-Linux-8.10-2025.03.18-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-8x/oracle-linux-8-10-2025-03-18-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_GPU + bool "Oracle Linux 9.5 Gen2 GPU" + depends on TARGET_ARCH_X86_64 + help + Oracle-Linux-9.5-Gen2-GPU-2025.03.18-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-5-gen2-gpu-2025-03-18-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_ARM64 + bool "Oracle Linux 9.5 (aarch64)" + depends on TARGET_ARCH_ARM64 + help + Oracle-Linux-9.5-aarch64-2025.03.18-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-5-aarch64-2025-03-18-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_X86 + bool "Oracle Linux 9.5 (x86)" + depends on TARGET_ARCH_X86_64 + help + Oracle-Linux-9.5-2025.03.18-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-5-2025-03-18-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_GPU + bool "Oracle Linux 9.6 Gen2 GPU" + depends on TARGET_ARCH_X86_64 + help + Oracle-Linux-9.6-Gen2-GPU-2025.06.17-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-6-gen2-gpu-2025-06-17-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_ARM64 + bool "Oracle Linux 9.6 (aarch64)" + depends on TARGET_ARCH_ARM64 + help + Oracle-Linux-9.6-aarch64-2025.06.17-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-6-aarch64-2025-06-17-0.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_X86 + bool "Oracle Linux 9.6 (x86)" + depends on TARGET_ARCH_X86_64 + help + Oracle-Linux-9.6-2025.06.17-0 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-6-2025-06-17-0.htm + +endchoice + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_X86 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaaw4cggpn2wh4jhwpkcjdzvyicfaqblwcc6xq5k4i2jxkg2bx4gm6a" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.iad.aaaaaaaaew4bboppacmw7pvlog5wvtygfxhrvv2bfanicvjj2ljrmvtkfdtq" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaokvcf2uuidul5n7ukneihfkrtrowlyoo22ceowanplkinmbftmca" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaaz2glfsxaks4mvrnx5dpcevkm4yo32bls4zkfg7brsklldwgtq2oq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaa7cuflxmluvu7lumzlz2lcrvhh7seamwsrpyvjfey2ed25pxw5lha" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaakb25v43zvj44zljk73p2j5e2ew2ycht5obleuy7ntj24pttc65ga" if TERRAFORM_OCI_REGION_SJC + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaxtpiye5nnlmdl4a4far26ywp4mw3xtuchg6texgrlrl435mgomaq" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaatvm5xr23xsvjofwybmqfixrsfk4442sjpckjccechfhqso5kt4ia" if TERRAFORM_OCI_REGION_PHX + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_X86 + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_GPU + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaan6dsfja3qduobzk72iw6ocofxesiufcgjckbxampnwuk2q76xiiq" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.iad.aaaaaaaavkrcpinzw6otfx4h5wdgfypy7pa43u5nxm3vyur3wmadfacg6yoq" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaakkooyvv6j3ovxkyath4sx66hzly7ayew4apczehvfkujmneaqmwq" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaal45sa5nortjwtxfnzcufq4ly5kq7dhshz3e37vumjk7arjknajwa" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaxyoh65vwphlena44mm5gh56bidphgarl5c5qhbuuzvgbc4oytxtq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaa7q72ht4bblpje2twwt6n5rstnbmmg3zsmrro35wj2jrfhwwtnoiq" if TERRAFORM_OCI_REGION_SJC + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaevcobrg3izf46fimhmz2xdsnagixvgokyysteuajsdyqdi4lnudq" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaaop2dgnaymj3azm4cm2awycupwldxrqu6h4loo6zfcyez6hfffadq" if TERRAFORM_OCI_REGION_PHX + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_GPU + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_ARM64 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaa7y3qbdzra44m52ugjy5bdnsczazugkspybkejbcebdjqklzcifwa" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.iad.aaaaaaaamawldxaesq2w6ypyu6dpwgccgn2llakpymzn2xhs2it3ao3kpeda" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaagd2ujisye2n4qrqxehgkfgqefbthic7pph4sdabdwe5hpjn2yxia" if TERRAFORM_OCI_REGION_SJC + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa267gephgrqd4dimf55szmw7gwqibqxkheyixbz3ptltspla6brnq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaboblnxwpnu7qujwuvbnawt7bvmmmnilhzah6qp44fppe2pggpviq" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.phx.aaaaaaaawn7p3y4k4nkqjvtjsvufmhz4g2ijthfp6vtcsly6qe37iliw3kcq" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaayxu334z7aijxckl66tne42zudtrqts2ju5iq7e2envn7tp7bvfjq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.us-chicago-1.aaaaaaaauvy56pg3en7rnmttztnm5naqopw7f4nug4a3bgy6nhed3e7s46fa" if TERRAFORM_OCI_REGION_ORD + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_ARM64 + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_GPU + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaag6nolpaijfzxqy6o4pufxqzmsb53wdhlmt47i6uy7qrlup22ghba" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaypx4qk7wgvoxp7ijpfgh2iyolrjawby5fe3bahhpq5jx6qzm6hlq" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaabcjwzgu4e3osnnot6f75b3pj5lyoyi6756u5ihqz6wdrx33t6wxa" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa2xegkn2nihnzhbtc2s7qimattaraxhb7l3ubcusg53izojyatalq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaasg53rljyobwumy3z4rqx6qbfjo5txibadwztq3kqg5mx3ispi2fq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaann7bi7eee2u2yeyuyidz4woqcegnywalip7umbod6aknztgkqpja" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaaj3uhqliqpetwozwm5hbfuqw4ubrhkg7pnez2lwwrlbibqe4o72ga" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaa6dl65tbhiirls2t427juav6d2fnjqjyattzzkssnjys3owsmwqfa" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_GPU + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_ARM64 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaaoqg3nzwxnkw66rf3f53nomqku3hruwjpdjxwq3i7w7uurkxntshq" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaa4zhvgsmsftn6j4bxlidb6zq2tziy6v4ylp3tpjwd5nvte2qj3fzq" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaarzkc66ki6qcbykys7hjhoy2avyfp5lj5mwtvbpu7ondaz2rs46ha" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaazoyranvzks4xlbfu5s3ylro5m246wja2j77d37a7y6oniq4scspq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaahhe6tyixhxyc5bv7dxejl4ools5h235ry5kfu6jgstnxqeavtugq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaa33kkau2zsjk4eias7pz6akuff4giijs4dbhzhzka5lbctk2d5da" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaa3zzp4jue2jp5wm2hesslxoq27qqrzxfwdxylcabkv3ginqacgqra" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaagnr4w7bpjky7twkpwn4oag55wqowqjlegqzmiqqha6aiylqu6tta" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_ARM64 + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_X86 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaa3rpjxl576g3nsurlkzqcsrhruo3frpmfzqjmntqcfaukmhzoeqqq" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaazviipxxkrka3pvwq4twxm4q2bpqyp6fvv7txx7jlvbxmvtuzfwga" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaaupsoxaochddlvom7joxo3457sw5bfprehlftrifg64zvyetpscga" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa6kzgiyrgaibzgkbcjybt7q7ripbp4qxybzci7z3cxq6jyoe6xnvq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaa4eqd3xzpt4wej2dhvbmn6qezgp6qs5rx2kvmu55dicdcgtko5o5q" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaarhsptzukiqy3zeo7e37yxvi2do3gs2xnymlhosz5dwf53dvgymjq" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaa6ihkh6yp6f2e2np4fkucu7rv7d3v6uogy7ya7osfmogkznjaveha" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaarj3piol7pdmcydvgryclnhdr2rce5ozvamumvb3l2fdodbq3wouq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_X86 + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_GPU + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaafpwtoai7qo6unslyke7nweznm6bof2g6kiyjkrlxfqqi7jtyv6rq" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaavopk6s6ejcwol4mivfaipbxk6fpmvynhwxtp65prjet6cyyi3e4a" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaajombg57yxesfnlsuq4zjp7uee552u2qolrol3vv26queht227mfq" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaaiyemvdwdvm2gaqr7qvioby5vwkvvl54lvaludny6gxqgx4hcxqra" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaf2dam6k3z45mkthh4ezalp5bidbk45rwdthvlu6uywg2f5wtb5ba" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaz5ewjpl7z3qgpjd5autfuxf3qzunzfsuokvqgv7auvjxdwevuyta" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaau4ebstxoehxcndmyypuup2u7dutsnem7iocf3wen3eq6loi3wbha" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaah2rydmd3v7fx24v3mfv4iobw4c6fonwoivkm3lcathnobijqwacq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_GPU + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_ARM64 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaavgibokwp4zsq76csi3huy722jmkjq2bnquhyc5loynon6vqyekmq" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaa4sfujzbvkgsbpeu2my2zvtszddoflbzpx7dmf7nq252q7tg4qsmq" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaa3is5zklasaldyvhbspwe3wep2mu3knhdlbhgn6gksgm54h2k3mya" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaajgecqb2h332aesfnke56zs7vhopawsos3vdm2vdzxv4bsi6rapxa" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaand6afptekvywnvosbbtiqkhwpdxpf4lqj77e7f7hp4z4mutfjnjq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaayl2scgs4qnzrkfyufmbvbtbxfbzkaoqifo76f4atetpwn77hj2ja" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaawvs4xn6dfl6oo45o2ntziecjy2cbet2mlidvx3ji62oi3jai4u5a" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaandckidue7lzzhey4u2s3m27rwigsholban3l2bvxe6oemakrqsmq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_ARM64 + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_X86 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaadgymvb6xuprmddif4jlfu5nzgxqun7rt6bevockugwa3mdhcde4q" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaoaz7xssmgj6qudbwdjbfxtgmqnslte7p5lt5vcz66w7ic7zrw7xq" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaad3yrq635f5swbg3g2iwtxvnxl2ytyrdkhurdizz4f6jf6miw4vma" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaao72nz2dewwn5ub6hpqgdedkhyxruebuifzrdj4upva645evvtmmq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaoxzvhrzruoandezl5itouxnrg32hay3zm4p3hkydqj3dxxdbpikq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaj7q7ofu4kqa5j3gm546xkin4hlf2gakcsbmxjcb4ghaf5irxuwyq" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaatf3vyxzq3pv5jugwixnmnmh7aivqyhtlwalmgwquvp7c4npuy2ba" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaaopxntceb4zygnto7tbi7ezxptoxp3m72jz5ttpp5zfg4iklupr4q" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_X86 + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_GPU + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaaxetvxo7pwc2uoj7gel5yyrroofgm6wgito7g6lvu4rcyzjetlmta" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaju6ud4bzvkwzphlaw4tt27mx374t4eoq36vufk6qavpwc2imis7a" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaaxtx5e3vilq727xx2f32ad72l46gt2tvanlqfoi7mkrbae4zafeea" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaayfjxrv3z5quvwn4sbwxalxct6ic67otjvjgub2rdh5b3rsugbqya" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaa6amxhb4uxcyjnztvyjmvwo2cv3aencrpwo2ltqf5g4fjt4iddmuq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaowpmyyvgx232gettpqyeb5vxyfhaapcwuftqczcisyfprbnwyqsa" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaa6lrr64teb63cmprsnmlozagcmcmqedg6ubjsij7vszptipgzpedq" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaab77uhcrbou4iqji3qah6ync663l6inyjqnwa66q4suscxtdb3aya" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_GPU + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_ARM64 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaarth4ajbp464qwkcwfmzqkzmgamnuiuot354oe437quz7dt47g2gq" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaa4ly37lnuij6u5irxnqxvcy7pi2mhmioc7o6jwm6sudex5rtqatda" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaaaawp4x63fjccfs2cwdq63ofvftcktl56xp2afophsp4xvemr52ba" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa76hls27mlpe5ietuukxidsc5czy3332z5vjoys5nc7gp74fhtena" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaamh6uuodtwvl2n2vijgrzfn4qgnud4cikdveeeoqbuulecvv6z5fa" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaqtbcyvi5blheqy4ryj5zy4xbgab4gg5lu4ryfdezipxwrzn7xzca" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaayh2t6irbplharxvcfcpzopxl5ojk3gm3jtthnonhvd4pupliie5a" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaa3gmh6j33rmb2z5vd52lb6dyvn6iy24kryhvhqe546rwtbbypzltq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_ARM64 + +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_X86 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.us-chicago-1.aaaaaaaaxglgurk3cbsfgzrknz6bm4745br6sflp73pymuhu7nu3bg324goa" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaafigfhiva5nurwfo2yjp2mfvzcjdhqxbclxp2mvtm4kk44qnu5lra" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.phx.aaaaaaaanoh2ncjgaee7kxlkkeify2hux7nqcrfn4fjacruqupzlm6572zwa" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaanobby7pyz667w7mupftxwfa67sz5rpb3cm3eecgjq5sxpmxg5moq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaakdieboyxlwwrs5mbbshzl3or3xh4vgn7n2gve5pfdkvgtcwdiopq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaahagfoemyqlfb5mwp3umst7h7tbzetf3eoehz5lvm3mdtofkgeuta" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.iad.aaaaaaaafjz2wgkvdamf3epnseff5aybkefqpqmbx5ol6xklszeatspdwswa" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaaztvaby7stzck64mwfze6rosjs53dlg4umqxz3p4h3dqavo2zhirq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_X86 + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX + +if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU + +choice + prompt "OS release" + default TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_ARM64 if TARGET_ARCH_ARM64 + default TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_X86 if TARGET_ARCH_X86_64 + help + Select the release of Ubuntu to install on each instance. + +config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_ARM64 + bool "Ubuntu 20.04 (aarch64)" + depends on TARGET_ARCH_ARM64 + help + Canonical-Ubuntu-20.04-aarch64-2025.01.31-1 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/ubuntu-2004/canonical-ubuntu-20-04-aarch64-2025-01-31-1.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_X86 + bool "Ubuntu 20.04 (x86)" + depends on TARGET_ARCH_X86_64 + help + Canonical-Ubuntu-20.04-2025.01.31-1 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/ubuntu-2004/canonical-ubuntu-20-04-2025-01-31-1.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_ARM64 + bool "Ubuntu 22.04 (aarch64)" + depends on TARGET_ARCH_ARM64 + help + Canonical-Ubuntu-22.04-aarch64-2025.01.31-1 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/ubuntu-2204/canonical-ubuntu-22-04-aarch64-2025-01-31-1.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_X86 + bool "Ubuntu 22.04 (x86)" + depends on TARGET_ARCH_X86_64 + help + Canonical-Ubuntu-22.04-2025.01.31-1 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/ubuntu-2204/canonical-ubuntu-22-04-2025-01-31-1.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_ARM64 + bool "Ubuntu 24.04 (aarch64)" + depends on TARGET_ARCH_ARM64 + help + Canonical-Ubuntu-24.04-aarch64-2025.01.31-1 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/ubuntu-2404/canonical-ubuntu-24-04-aarch64-2025-01-31-1.htm + +config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_X86 + bool "Ubuntu 24.04 (x86)" + depends on TARGET_ARCH_X86_64 + help + Canonical-Ubuntu-24.04-2025.01.31-1 + + Image release notes: + https://docs.oracle.com/en-us/iaas/images/ubuntu-2404/canonical-ubuntu-24-04-2025-01-31-1.htm + +endchoice + +if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_ARM64 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaawnlatjgnpqmaercoleknle5nml47l23iwnxi7ba4xup5ajyarv6q" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaawkgecsy7fbxqeus5zpw5n7ykyeugzizcehrildz7pzavfjrcsswa" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaesuvbpyo4lpim5xxx3lwj4lcppfkzp6tsape336epukyndi2pora" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaoox5ewo5bq67sr2spakzdiw4rrxjlgbr25ucqwglb4aonastyhzq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.iad.aaaaaaaan5qjp6hcvi2ry24zp233wlotljj4llfghqbyn2yoon6wnc3se6pa" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-chicago-1.aaaaaaaa7habuxhtxdty52x47eq27lq7gjweoun4urafpv2s6ysggbp6nrxa" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.phx.aaaaaaaaji2v46qtemmx7bpuoomw2uvrsatvgxrlnp3orvdptbl6ppbal67q" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaa2dt3oqmhwwd3z2o3wynfltfa3rms6pc2uhvr2kmjmmyvqr2li7pq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_ARM64 + +if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_X86 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa3uvxetf4g6beur4qn2ublcl6set7qtda2rcfcv5h7vul6aut2q7q" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaj276t4bm4hyqyu44mjcuzndgn6lku4th3nfaglwpiyzsp6lozqlq" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaagkdbfci5rxx5yikkifi7culqosi7r623osdzqv25rkanxd66dbq" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaafbbzzsemfbol5vvyevlmqxhcv6avfo5z6larkuty4safdn3epoha" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.iad.aaaaaaaaw65jff6tnjbr7x2c2lr3qlf46l2sthpuidxaurmar2oxjmqry3qa" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-chicago-1.aaaaaaaagyn7e55mr27m7ttkp2exvdix4ugfl2jbl66xognsge44vuqat4ma" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.phx.aaaaaaaazjumsfmhi2tztgs7wuhesifaj2fw47xmyycltazjmr5xa6k7do7q" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaaka77df4vad27cm7oamg3zji6ir5zrvbwbkm7ks7rvucd3bwsbqnq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_X86 + +if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_ARM64 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaaca7s2s5pgnooszcjysi7pknrimayqjds6knvjascphe2r767m6vq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaamvlfwzlzk6jkyuhoylf6k3n5r7tz6m2lvf5fqjdpsrdwqk2dtcqa" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaai6c6hx7wvx5l3oikjcv7am3n23etmbuu3byic3grzhx5ylthigca" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaa7fy2cysnjwlpoghk5ax65jmvyteg4bjmji6xmm4gti6xg4kmgfia" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.iad.aaaaaaaaq3uhgye3ryjqjcnnmtk5u4ipa5ffhxawa6nvgelzccz5x3pfel4a" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-chicago-1.aaaaaaaar5u2rj2ahg2btnlmnxhzijozcuqb5lhjit327wesufuhjkytfwha" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.phx.aaaaaaaa7f6r242tdb2roknj3odb264g2tduvc2je2u4kbp3hqatiy4sngcq" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaax6vsn7c34viq7yfu3j3v554x6dulorapywrorheltorxoi5on4dq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_ARM64 + +if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_X86 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaalldybw6d43ihqwcqeeedsncrl4s7qfczeqwq2eb5cohxj2gyp72q" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaooprivsfvvblwxhl2oww3djmz4mnjxjqczxunvahu5dvt3dwlfka" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaadstv5y7ovuhvg354zu4mocto6eyy4frnnfartpl34hmaupg6upka" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaf6wyj6ap2frgctd7xj7pkxwvj7gowxinvy6xbjzz3z4cv2d5ycfa" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.iad.aaaaaaaablkb5j2kdyqehb7qp2scdyuwslknidn4a53qzje2fxcbw3ji5gta" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-chicago-1.aaaaaaaa3dfmmuqlupm4gruk5weh5mncxbmfzn36uoj2relmdwvud44zc3ea" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.phx.aaaaaaaaccxuq5zox772ncsaggg52xngwcipzfqoqwu7x73owhvd7ula7xpa" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaappswsfuaodghkbps5kjh3bhjxxpaig56wiirxhjlo5tktsuypkha" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_X86 + +if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_ARM64 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaagkujhljfnogpc4zmmith4sbyh32ltdnxrjx7wksssyv3yv3xkasq" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaat27vwnwxtqovgbceettrrkmvlgwgyn3vj7rhyblih7omqhi4cioa" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaayojwvhljgwqgpdyqcqdjh4jgbcfd6hu2axdogi4c3si5stmdcjxa" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaj4vzogabouc3ypajurmwx53juolg745la7mmi4qj3grijoaziwlq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.iad.aaaaaaaahga37ytba47p2msqzbh5erbqvniyybcvteuh646vgyw4tltustka" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-chicago-1.aaaaaaaasghgl3azcm2kjya2p7urk4nnpfjlrxlfeosn5jc6hm5epn7gkrra" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.phx.aaaaaaaag7js2gmz5yrqtnnjirri52hyqvsymn7gp5a7gwg5jtd2jowpi7tq" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaatsp47wenhtuubuusyi2pgohpnal5fz6jyz4ur5n4juwhj2n2egpq" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_ARM64 + +if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_X86 + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml + default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaakzztav5leofa43dcc7uecenhjhazdxlaj7u3kgnfsu65fcw6c5wa" if TERRAFORM_OCI_REGION_HYD + default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaayvok7wg6qwbf2nfeohcqroie2eyplrlxsuwjut7rdugg7jftk7pa" if TERRAFORM_OCI_REGION_BOM + default "ocid1.image.oc1.ca-montreal-1.aaaaaaaa33jzjdmexcf5zaiia2mhjou5xsgatzaqm4mwgqejp2f77bnjhwpa" if TERRAFORM_OCI_REGION_YUL + default "ocid1.image.oc1.ca-toronto-1.aaaaaaaadtwzeffczkghs325xbzeocp4i7ghpeims5insf6a65kxcpmk4bwq" if TERRAFORM_OCI_REGION_YYZ + default "ocid1.image.oc1.iad.aaaaaaaaaja5re7chpwbyrdk57xya7qoxdktskrn5lph7fsuai5zccaefawa" if TERRAFORM_OCI_REGION_IAD + default "ocid1.image.oc1.us-chicago-1.aaaaaaaaslqsnubarsgmpktkbewqedpf76vp6e5k7nafoxpx3aaryag2a6ba" if TERRAFORM_OCI_REGION_ORD + default "ocid1.image.oc1.phx.aaaaaaaapplpp6okoc73a23mdag6k6mwgscofpx2p7bcigeo3ztjktsd53pa" if TERRAFORM_OCI_REGION_PHX + default "ocid1.image.oc1.us-sanjose-1.aaaaaaaaebdhewufiuvsm6kh2eccurg5zdchwfr24heayt4h4bwenee3lwka" if TERRAFORM_OCI_REGION_SJC + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_X86 + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU + +if TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM + +config TERRAFORM_OCI_OS_IMAGE_OCID + string "OS image OCID" + output yaml + help + An image is a template of a virtual hard drive. It + contains the operating system and other software for each + instance. Select an image by specifying the OCID of the + image to use. You can select: + + - An older release than the latest image release + - An older operating system release + - A custom-made image + + More detail is available: + + https://docs.oracle.com/en-us/iaas/Content/Compute/References/bringyourownimage.htm + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM diff --git a/terraform/oci/kconfigs/images/Kconfig.OracleLinux b/terraform/oci/kconfigs/images/Kconfig.OracleLinux deleted file mode 100644 index 9c48be5b9..000000000 --- a/terraform/oci/kconfigs/images/Kconfig.OracleLinux +++ /dev/null @@ -1,312 +0,0 @@ -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX - -choice - prompt "OS release" - default TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_ARM64 if TARGET_ARCH_ARM64 - default TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_X86 if TARGET_ARCH_X86_64 - help - Select the release of Oracle Linux to install on each - instance. - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_X86 - bool "Oracle Linux 7.9 (x86)" - depends on TARGET_ARCH_X86_64 - help - (extended support) Oracle-Linux-7.9-2025.01.31-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oraclelinux-7x/oracle-linux-7-9-2025-01-31-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_GPU - bool "Oracle Linux 7.9 Gen2 GPU" - depends on TARGET_ARCH_X86_64 - help - (extended support) Oracle-Linux-7.9-Gen2-GPU-2025.01.31-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oraclelinux-7x/oracle-linux-7-9-gen2-gpu-2025-01-31-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_ARM64 - bool "Oracle Linux 7.9 (aarch64)" - help - (extended support) Oracle-Linux-7.9-aarch64-2024.11.30-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oraclelinux-7x/oracle-linux-7-9-aarch64-2024-11-30-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_GPU - bool "Oracle Linux 8.10 Gen2 GPU" - depends on TARGET_ARCH_X86_64 - help - Oracle-Linux-8.10-Gen2-GPU-2025.03.18-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-8x/oracle-linux-8-10-gen2-gpu-2025-03-18-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_ARM64 - bool "Oracle Linux 8.10 (aarch64)" - depends on TARGET_ARCH_ARM64 - help - Oracle-Linux-8.10-aarch64-2025.03.18-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-8x/oracle-linux-8-10-aarch64-2025-03-18-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_X86 - bool "Oracle Linux 8.10 (x86)" - depends on TARGET_ARCH_X86_64 - help - Oracle-Linux-8.10-2025.03.18-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-8x/oracle-linux-8-10-2025-03-18-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_GPU - bool "Oracle Linux 9.5 Gen2 GPU" - depends on TARGET_ARCH_X86_64 - help - Oracle-Linux-9.5-Gen2-GPU-2025.03.18-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-5-gen2-gpu-2025-03-18-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_ARM64 - bool "Oracle Linux 9.5 (aarch64)" - depends on TARGET_ARCH_ARM64 - help - Oracle-Linux-9.5-aarch64-2025.03.18-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-5-aarch64-2025-03-18-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_X86 - bool "Oracle Linux 9.5 (x86)" - depends on TARGET_ARCH_X86_64 - help - Oracle-Linux-9.5-2025.03.18-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-5-2025-03-18-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_GPU - bool "Oracle Linux 9.6 Gen2 GPU" - depends on TARGET_ARCH_X86_64 - help - Oracle-Linux-9.6-Gen2-GPU-2025.06.17-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-6-gen2-gpu-2025-06-17-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_ARM64 - bool "Oracle Linux 9.6 (aarch64)" - depends on TARGET_ARCH_ARM64 - help - Oracle-Linux-9.6-aarch64-2025.06.17-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-6-aarch64-2025-06-17-0.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_X86 - bool "Oracle Linux 9.6 (x86)" - depends on TARGET_ARCH_X86_64 - help - Oracle-Linux-9.6-2025.06.17-0 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/oracle-linux-9x/oracle-linux-9-6-2025-06-17-0.htm - -endchoice - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_X86 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaaw4cggpn2wh4jhwpkcjdzvyicfaqblwcc6xq5k4i2jxkg2bx4gm6a" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.iad.aaaaaaaaew4bboppacmw7pvlog5wvtygfxhrvv2bfanicvjj2ljrmvtkfdtq" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaokvcf2uuidul5n7ukneihfkrtrowlyoo22ceowanplkinmbftmca" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaaz2glfsxaks4mvrnx5dpcevkm4yo32bls4zkfg7brsklldwgtq2oq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaa7cuflxmluvu7lumzlz2lcrvhh7seamwsrpyvjfey2ed25pxw5lha" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaakb25v43zvj44zljk73p2j5e2ew2ycht5obleuy7ntj24pttc65ga" if TERRAFORM_OCI_REGION_SJC - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaxtpiye5nnlmdl4a4far26ywp4mw3xtuchg6texgrlrl435mgomaq" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaatvm5xr23xsvjofwybmqfixrsfk4442sjpckjccechfhqso5kt4ia" if TERRAFORM_OCI_REGION_PHX - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_X86 - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_GPU - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaan6dsfja3qduobzk72iw6ocofxesiufcgjckbxampnwuk2q76xiiq" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.iad.aaaaaaaavkrcpinzw6otfx4h5wdgfypy7pa43u5nxm3vyur3wmadfacg6yoq" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaakkooyvv6j3ovxkyath4sx66hzly7ayew4apczehvfkujmneaqmwq" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaal45sa5nortjwtxfnzcufq4ly5kq7dhshz3e37vumjk7arjknajwa" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaxyoh65vwphlena44mm5gh56bidphgarl5c5qhbuuzvgbc4oytxtq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaa7q72ht4bblpje2twwt6n5rstnbmmg3zsmrro35wj2jrfhwwtnoiq" if TERRAFORM_OCI_REGION_SJC - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaevcobrg3izf46fimhmz2xdsnagixvgokyysteuajsdyqdi4lnudq" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaaop2dgnaymj3azm4cm2awycupwldxrqu6h4loo6zfcyez6hfffadq" if TERRAFORM_OCI_REGION_PHX - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_GPU - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_ARM64 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaa7y3qbdzra44m52ugjy5bdnsczazugkspybkejbcebdjqklzcifwa" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.iad.aaaaaaaamawldxaesq2w6ypyu6dpwgccgn2llakpymzn2xhs2it3ao3kpeda" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaagd2ujisye2n4qrqxehgkfgqefbthic7pph4sdabdwe5hpjn2yxia" if TERRAFORM_OCI_REGION_SJC - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa267gephgrqd4dimf55szmw7gwqibqxkheyixbz3ptltspla6brnq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaboblnxwpnu7qujwuvbnawt7bvmmmnilhzah6qp44fppe2pggpviq" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.phx.aaaaaaaawn7p3y4k4nkqjvtjsvufmhz4g2ijthfp6vtcsly6qe37iliw3kcq" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaayxu334z7aijxckl66tne42zudtrqts2ju5iq7e2envn7tp7bvfjq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.us-chicago-1.aaaaaaaauvy56pg3en7rnmttztnm5naqopw7f4nug4a3bgy6nhed3e7s46fa" if TERRAFORM_OCI_REGION_ORD - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_7_9_ARM64 - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_GPU - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaag6nolpaijfzxqy6o4pufxqzmsb53wdhlmt47i6uy7qrlup22ghba" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaypx4qk7wgvoxp7ijpfgh2iyolrjawby5fe3bahhpq5jx6qzm6hlq" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaabcjwzgu4e3osnnot6f75b3pj5lyoyi6756u5ihqz6wdrx33t6wxa" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa2xegkn2nihnzhbtc2s7qimattaraxhb7l3ubcusg53izojyatalq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaasg53rljyobwumy3z4rqx6qbfjo5txibadwztq3kqg5mx3ispi2fq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaann7bi7eee2u2yeyuyidz4woqcegnywalip7umbod6aknztgkqpja" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaaj3uhqliqpetwozwm5hbfuqw4ubrhkg7pnez2lwwrlbibqe4o72ga" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaa6dl65tbhiirls2t427juav6d2fnjqjyattzzkssnjys3owsmwqfa" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_GPU - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_ARM64 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaaoqg3nzwxnkw66rf3f53nomqku3hruwjpdjxwq3i7w7uurkxntshq" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaa4zhvgsmsftn6j4bxlidb6zq2tziy6v4ylp3tpjwd5nvte2qj3fzq" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaarzkc66ki6qcbykys7hjhoy2avyfp5lj5mwtvbpu7ondaz2rs46ha" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaazoyranvzks4xlbfu5s3ylro5m246wja2j77d37a7y6oniq4scspq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaahhe6tyixhxyc5bv7dxejl4ools5h235ry5kfu6jgstnxqeavtugq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaa33kkau2zsjk4eias7pz6akuff4giijs4dbhzhzka5lbctk2d5da" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaa3zzp4jue2jp5wm2hesslxoq27qqrzxfwdxylcabkv3ginqacgqra" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaagnr4w7bpjky7twkpwn4oag55wqowqjlegqzmiqqha6aiylqu6tta" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_ARM64 - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_X86 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaa3rpjxl576g3nsurlkzqcsrhruo3frpmfzqjmntqcfaukmhzoeqqq" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaazviipxxkrka3pvwq4twxm4q2bpqyp6fvv7txx7jlvbxmvtuzfwga" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaaupsoxaochddlvom7joxo3457sw5bfprehlftrifg64zvyetpscga" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa6kzgiyrgaibzgkbcjybt7q7ripbp4qxybzci7z3cxq6jyoe6xnvq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaa4eqd3xzpt4wej2dhvbmn6qezgp6qs5rx2kvmu55dicdcgtko5o5q" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaarhsptzukiqy3zeo7e37yxvi2do3gs2xnymlhosz5dwf53dvgymjq" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaa6ihkh6yp6f2e2np4fkucu7rv7d3v6uogy7ya7osfmogkznjaveha" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaarj3piol7pdmcydvgryclnhdr2rce5ozvamumvb3l2fdodbq3wouq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_8_10_X86 - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_GPU - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaafpwtoai7qo6unslyke7nweznm6bof2g6kiyjkrlxfqqi7jtyv6rq" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaavopk6s6ejcwol4mivfaipbxk6fpmvynhwxtp65prjet6cyyi3e4a" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaajombg57yxesfnlsuq4zjp7uee552u2qolrol3vv26queht227mfq" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaaiyemvdwdvm2gaqr7qvioby5vwkvvl54lvaludny6gxqgx4hcxqra" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaf2dam6k3z45mkthh4ezalp5bidbk45rwdthvlu6uywg2f5wtb5ba" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaz5ewjpl7z3qgpjd5autfuxf3qzunzfsuokvqgv7auvjxdwevuyta" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaau4ebstxoehxcndmyypuup2u7dutsnem7iocf3wen3eq6loi3wbha" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaah2rydmd3v7fx24v3mfv4iobw4c6fonwoivkm3lcathnobijqwacq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_GPU - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_ARM64 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaavgibokwp4zsq76csi3huy722jmkjq2bnquhyc5loynon6vqyekmq" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaa4sfujzbvkgsbpeu2my2zvtszddoflbzpx7dmf7nq252q7tg4qsmq" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaa3is5zklasaldyvhbspwe3wep2mu3knhdlbhgn6gksgm54h2k3mya" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaajgecqb2h332aesfnke56zs7vhopawsos3vdm2vdzxv4bsi6rapxa" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaand6afptekvywnvosbbtiqkhwpdxpf4lqj77e7f7hp4z4mutfjnjq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaayl2scgs4qnzrkfyufmbvbtbxfbzkaoqifo76f4atetpwn77hj2ja" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaawvs4xn6dfl6oo45o2ntziecjy2cbet2mlidvx3ji62oi3jai4u5a" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaandckidue7lzzhey4u2s3m27rwigsholban3l2bvxe6oemakrqsmq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_ARM64 - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_X86 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaadgymvb6xuprmddif4jlfu5nzgxqun7rt6bevockugwa3mdhcde4q" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaoaz7xssmgj6qudbwdjbfxtgmqnslte7p5lt5vcz66w7ic7zrw7xq" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaad3yrq635f5swbg3g2iwtxvnxl2ytyrdkhurdizz4f6jf6miw4vma" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaao72nz2dewwn5ub6hpqgdedkhyxruebuifzrdj4upva645evvtmmq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaoxzvhrzruoandezl5itouxnrg32hay3zm4p3hkydqj3dxxdbpikq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaj7q7ofu4kqa5j3gm546xkin4hlf2gakcsbmxjcb4ghaf5irxuwyq" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaatf3vyxzq3pv5jugwixnmnmh7aivqyhtlwalmgwquvp7c4npuy2ba" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaaopxntceb4zygnto7tbi7ezxptoxp3m72jz5ttpp5zfg4iklupr4q" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_5_X86 - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_GPU - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaaxetvxo7pwc2uoj7gel5yyrroofgm6wgito7g6lvu4rcyzjetlmta" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaju6ud4bzvkwzphlaw4tt27mx374t4eoq36vufk6qavpwc2imis7a" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaaxtx5e3vilq727xx2f32ad72l46gt2tvanlqfoi7mkrbae4zafeea" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaayfjxrv3z5quvwn4sbwxalxct6ic67otjvjgub2rdh5b3rsugbqya" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaa6amxhb4uxcyjnztvyjmvwo2cv3aencrpwo2ltqf5g4fjt4iddmuq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaowpmyyvgx232gettpqyeb5vxyfhaapcwuftqczcisyfprbnwyqsa" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaa6lrr64teb63cmprsnmlozagcmcmqedg6ubjsij7vszptipgzpedq" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaab77uhcrbou4iqji3qah6ync663l6inyjqnwa66q4suscxtdb3aya" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_GPU - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_ARM64 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaarth4ajbp464qwkcwfmzqkzmgamnuiuot354oe437quz7dt47g2gq" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaa4ly37lnuij6u5irxnqxvcy7pi2mhmioc7o6jwm6sudex5rtqatda" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaaaawp4x63fjccfs2cwdq63ofvftcktl56xp2afophsp4xvemr52ba" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa76hls27mlpe5ietuukxidsc5czy3332z5vjoys5nc7gp74fhtena" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaamh6uuodtwvl2n2vijgrzfn4qgnud4cikdveeeoqbuulecvv6z5fa" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaqtbcyvi5blheqy4ryj5zy4xbgab4gg5lu4ryfdezipxwrzn7xzca" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaayh2t6irbplharxvcfcpzopxl5ojk3gm3jtthnonhvd4pupliie5a" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaa3gmh6j33rmb2z5vd52lb6dyvn6iy24kryhvhqe546rwtbbypzltq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_ARM64 - -if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_X86 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.us-chicago-1.aaaaaaaaxglgurk3cbsfgzrknz6bm4745br6sflp73pymuhu7nu3bg324goa" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaafigfhiva5nurwfo2yjp2mfvzcjdhqxbclxp2mvtm4kk44qnu5lra" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.phx.aaaaaaaanoh2ncjgaee7kxlkkeify2hux7nqcrfn4fjacruqupzlm6572zwa" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaanobby7pyz667w7mupftxwfa67sz5rpb3cm3eecgjq5sxpmxg5moq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaakdieboyxlwwrs5mbbshzl3or3xh4vgn7n2gve5pfdkvgtcwdiopq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaahagfoemyqlfb5mwp3umst7h7tbzetf3eoehz5lvm3mdtofkgeuta" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.iad.aaaaaaaafjz2wgkvdamf3epnseff5aybkefqpqmbx5ol6xklszeatspdwswa" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaaztvaby7stzck64mwfze6rosjs53dlg4umqxz3p4h3dqavo2zhirq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX_9_6_X86 - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX diff --git a/terraform/oci/kconfigs/images/Kconfig.Ubuntu b/terraform/oci/kconfigs/images/Kconfig.Ubuntu deleted file mode 100644 index 5a87cd4c3..000000000 --- a/terraform/oci/kconfigs/images/Kconfig.Ubuntu +++ /dev/null @@ -1,162 +0,0 @@ -if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU - -choice - prompt "OS release" - default TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_ARM64 if TARGET_ARCH_ARM64 - default TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_X86 if TARGET_ARCH_X86_64 - help - Select the release of Ubuntu to install on each instance. - -config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_ARM64 - bool "Ubuntu 20.04 (aarch64)" - depends on TARGET_ARCH_ARM64 - help - Canonical-Ubuntu-20.04-aarch64-2025.01.31-1 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/ubuntu-2004/canonical-ubuntu-20-04-aarch64-2025-01-31-1.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_X86 - bool "Ubuntu 20.04 (x86)" - depends on TARGET_ARCH_X86_64 - help - Canonical-Ubuntu-20.04-2025.01.31-1 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/ubuntu-2004/canonical-ubuntu-20-04-2025-01-31-1.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_ARM64 - bool "Ubuntu 22.04 (aarch64)" - depends on TARGET_ARCH_ARM64 - help - Canonical-Ubuntu-22.04-aarch64-2025.01.31-1 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/ubuntu-2204/canonical-ubuntu-22-04-aarch64-2025-01-31-1.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_X86 - bool "Ubuntu 22.04 (x86)" - depends on TARGET_ARCH_X86_64 - help - Canonical-Ubuntu-22.04-2025.01.31-1 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/ubuntu-2204/canonical-ubuntu-22-04-2025-01-31-1.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_ARM64 - bool "Ubuntu 24.04 (aarch64)" - depends on TARGET_ARCH_ARM64 - help - Canonical-Ubuntu-24.04-aarch64-2025.01.31-1 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/ubuntu-2404/canonical-ubuntu-24-04-aarch64-2025-01-31-1.htm - -config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_X86 - bool "Ubuntu 24.04 (x86)" - depends on TARGET_ARCH_X86_64 - help - Canonical-Ubuntu-24.04-2025.01.31-1 - - Image release notes: - https://docs.oracle.com/en-us/iaas/images/ubuntu-2404/canonical-ubuntu-24-04-2025-01-31-1.htm - -endchoice - -if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_ARM64 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaawnlatjgnpqmaercoleknle5nml47l23iwnxi7ba4xup5ajyarv6q" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaawkgecsy7fbxqeus5zpw5n7ykyeugzizcehrildz7pzavfjrcsswa" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaesuvbpyo4lpim5xxx3lwj4lcppfkzp6tsape336epukyndi2pora" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaoox5ewo5bq67sr2spakzdiw4rrxjlgbr25ucqwglb4aonastyhzq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.iad.aaaaaaaan5qjp6hcvi2ry24zp233wlotljj4llfghqbyn2yoon6wnc3se6pa" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-chicago-1.aaaaaaaa7habuxhtxdty52x47eq27lq7gjweoun4urafpv2s6ysggbp6nrxa" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.phx.aaaaaaaaji2v46qtemmx7bpuoomw2uvrsatvgxrlnp3orvdptbl6ppbal67q" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaa2dt3oqmhwwd3z2o3wynfltfa3rms6pc2uhvr2kmjmmyvqr2li7pq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_ARM64 - -if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_X86 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaa3uvxetf4g6beur4qn2ublcl6set7qtda2rcfcv5h7vul6aut2q7q" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaj276t4bm4hyqyu44mjcuzndgn6lku4th3nfaglwpiyzsp6lozqlq" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaaagkdbfci5rxx5yikkifi7culqosi7r623osdzqv25rkanxd66dbq" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaafbbzzsemfbol5vvyevlmqxhcv6avfo5z6larkuty4safdn3epoha" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.iad.aaaaaaaaw65jff6tnjbr7x2c2lr3qlf46l2sthpuidxaurmar2oxjmqry3qa" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-chicago-1.aaaaaaaagyn7e55mr27m7ttkp2exvdix4ugfl2jbl66xognsge44vuqat4ma" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.phx.aaaaaaaazjumsfmhi2tztgs7wuhesifaj2fw47xmyycltazjmr5xa6k7do7q" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaaka77df4vad27cm7oamg3zji6ir5zrvbwbkm7ks7rvucd3bwsbqnq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_20_04_X86 - -if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_ARM64 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaaca7s2s5pgnooszcjysi7pknrimayqjds6knvjascphe2r767m6vq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaamvlfwzlzk6jkyuhoylf6k3n5r7tz6m2lvf5fqjdpsrdwqk2dtcqa" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaai6c6hx7wvx5l3oikjcv7am3n23etmbuu3byic3grzhx5ylthigca" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaa7fy2cysnjwlpoghk5ax65jmvyteg4bjmji6xmm4gti6xg4kmgfia" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.iad.aaaaaaaaq3uhgye3ryjqjcnnmtk5u4ipa5ffhxawa6nvgelzccz5x3pfel4a" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-chicago-1.aaaaaaaar5u2rj2ahg2btnlmnxhzijozcuqb5lhjit327wesufuhjkytfwha" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.phx.aaaaaaaa7f6r242tdb2roknj3odb264g2tduvc2je2u4kbp3hqatiy4sngcq" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaax6vsn7c34viq7yfu3j3v554x6dulorapywrorheltorxoi5on4dq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_ARM64 - -if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_X86 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaalldybw6d43ihqwcqeeedsncrl4s7qfczeqwq2eb5cohxj2gyp72q" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaaooprivsfvvblwxhl2oww3djmz4mnjxjqczxunvahu5dvt3dwlfka" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaadstv5y7ovuhvg354zu4mocto6eyy4frnnfartpl34hmaupg6upka" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaf6wyj6ap2frgctd7xj7pkxwvj7gowxinvy6xbjzz3z4cv2d5ycfa" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.iad.aaaaaaaablkb5j2kdyqehb7qp2scdyuwslknidn4a53qzje2fxcbw3ji5gta" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-chicago-1.aaaaaaaa3dfmmuqlupm4gruk5weh5mncxbmfzn36uoj2relmdwvud44zc3ea" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.phx.aaaaaaaaccxuq5zox772ncsaggg52xngwcipzfqoqwu7x73owhvd7ula7xpa" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaappswsfuaodghkbps5kjh3bhjxxpaig56wiirxhjlo5tktsuypkha" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_22_04_X86 - -if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_ARM64 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaagkujhljfnogpc4zmmith4sbyh32ltdnxrjx7wksssyv3yv3xkasq" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaat27vwnwxtqovgbceettrrkmvlgwgyn3vj7rhyblih7omqhi4cioa" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaayojwvhljgwqgpdyqcqdjh4jgbcfd6hu2axdogi4c3si5stmdcjxa" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaaj4vzogabouc3ypajurmwx53juolg745la7mmi4qj3grijoaziwlq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.iad.aaaaaaaahga37ytba47p2msqzbh5erbqvniyybcvteuh646vgyw4tltustka" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-chicago-1.aaaaaaaasghgl3azcm2kjya2p7urk4nnpfjlrxlfeosn5jc6hm5epn7gkrra" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.phx.aaaaaaaag7js2gmz5yrqtnnjirri52hyqvsymn7gp5a7gwg5jtd2jowpi7tq" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaatsp47wenhtuubuusyi2pgohpnal5fz6jyz4ur5n4juwhj2n2egpq" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_ARM64 - -if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_X86 - -config TERRAFORM_OCI_OS_IMAGE_OCID - string - output yaml - default "ocid1.image.oc1.ap-hyderabad-1.aaaaaaaakzztav5leofa43dcc7uecenhjhazdxlaj7u3kgnfsu65fcw6c5wa" if TERRAFORM_OCI_REGION_HYD - default "ocid1.image.oc1.ap-mumbai-1.aaaaaaaayvok7wg6qwbf2nfeohcqroie2eyplrlxsuwjut7rdugg7jftk7pa" if TERRAFORM_OCI_REGION_BOM - default "ocid1.image.oc1.ca-montreal-1.aaaaaaaa33jzjdmexcf5zaiia2mhjou5xsgatzaqm4mwgqejp2f77bnjhwpa" if TERRAFORM_OCI_REGION_YUL - default "ocid1.image.oc1.ca-toronto-1.aaaaaaaadtwzeffczkghs325xbzeocp4i7ghpeims5insf6a65kxcpmk4bwq" if TERRAFORM_OCI_REGION_YYZ - default "ocid1.image.oc1.iad.aaaaaaaaaja5re7chpwbyrdk57xya7qoxdktskrn5lph7fsuai5zccaefawa" if TERRAFORM_OCI_REGION_IAD - default "ocid1.image.oc1.us-chicago-1.aaaaaaaaslqsnubarsgmpktkbewqedpf76vp6e5k7nafoxpx3aaryag2a6ba" if TERRAFORM_OCI_REGION_ORD - default "ocid1.image.oc1.phx.aaaaaaaapplpp6okoc73a23mdag6k6mwgscofpx2p7bcigeo3ztjktsd53pa" if TERRAFORM_OCI_REGION_PHX - default "ocid1.image.oc1.us-sanjose-1.aaaaaaaaebdhewufiuvsm6kh2eccurg5zdchwfr24heayt4h4bwenee3lwka" if TERRAFORM_OCI_REGION_SJC - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU_24_04_X86 - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU diff --git a/terraform/oci/kconfigs/images/Kconfig.custom b/terraform/oci/kconfigs/images/Kconfig.custom deleted file mode 100644 index 144b974fb..000000000 --- a/terraform/oci/kconfigs/images/Kconfig.custom +++ /dev/null @@ -1,20 +0,0 @@ -if TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM - -config TERRAFORM_OCI_OS_IMAGE_OCID - string "OS image OCID" - output yaml - help - An image is a template of a virtual hard drive. It - contains the operating system and other software for each - instance. Select an image by specifying the OCID of the - image to use. You can select: - - - An older release than the latest image release - - An older operating system release - - A custom-made image - - More detail is available: - - https://docs.oracle.com/en-us/iaas/Content/Compute/References/bringyourownimage.htm - -endif # TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM From 7066b47ba40a884e69d8b2706c85119f1910764a Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Sun, 19 Oct 2025 14:21:24 -0400 Subject: [PATCH 10/11] terraform/oci: Generate Kconfig.images dynamically Duplicate the same functionality as is already provided for AWS. The generated image menu includes platform images that are available in the region or regions that the user tenancy is subscribed to. Users can still manually select marketplace images by selecting the "Custom image OCID" option and pasting in the image's OCID directly. Generated-by: Claude AI Signed-off-by: Chuck Lever --- terraform/oci/scripts/gen_kconfig_image | 802 ++++++++++++++++++ terraform/oci/scripts/image_distributions.j2 | 90 ++ terraform/oci/scripts/image_publisher.j2 | 79 ++ .../oci/scripts/publisher_definitions.yml | 148 ++++ 4 files changed, 1119 insertions(+) create mode 100755 terraform/oci/scripts/gen_kconfig_image create mode 100644 terraform/oci/scripts/image_distributions.j2 create mode 100644 terraform/oci/scripts/image_publisher.j2 create mode 100644 terraform/oci/scripts/publisher_definitions.yml diff --git a/terraform/oci/scripts/gen_kconfig_image b/terraform/oci/scripts/gen_kconfig_image new file mode 100755 index 000000000..977446fd0 --- /dev/null +++ b/terraform/oci/scripts/gen_kconfig_image @@ -0,0 +1,802 @@ +#!/usr/bin/env python3 +# ex: set filetype=python: + +""" +Retrieve compute image information from OCI. Use it to construct the "images" +Kconfig menu. + +OCI images are OS templates that can be used to launch compute instances. +This script queries the OCI API to discover available images and generates +Kconfig menu entries for them. + +Publisher Definitions: + Publisher definitions (e.g., "Oracle Linux", "Ubuntu") are maintained + in the publisher_definitions.yml file in the same directory as this + script. This makes it easier to update publisher information when Oracle + adds new distributions or when you want to customize display names and + priorities. + + To update publisher definitions: + 1. Edit terraform/oci/scripts/publisher_definitions.yml + 2. Add or modify entries following the existing format + 3. Run this script to regenerate Kconfig.images + + The YAML file contains detailed instructions for how to add new + publisher definitions. If the YAML file is not found, the script + falls back to dynamic publisher discovery by analyzing image names. + +Image Discovery: + By default, this script aggregates images from all subscribed regions to + provide a comprehensive mapping of image OCIDs across regions. + + This script focuses exclusively on OCI platform images (official + Oracle-provided images). Marketplace and community images are not + included in the automated discovery, though users can still specify + marketplace image OCIDs manually via the "Custom image OCID" option. + + The script discovers Linux distribution platform images using: + - Known publishers defined in publisher_definitions.yml + - Dynamic discovery that detects new distributions automatically + +Usage: + # Generate images Kconfig from all subscribed regions (default) + ./gen_kconfig_image > ../kconfigs/Kconfig.images + + # List all available OS publishers + ./gen_kconfig_image --publishers + + # Get details for a specific publisher + ./gen_kconfig_image oracle +""" + +import sys +import os +import argparse +import re +from collections import defaultdict + +from oci_common import ( + get_default_region, + get_default_compartment, + get_subscribed_regions, + get_jinja2_environment, + load_yaml_config, + create_identity_client, + create_compute_client, + get_all_region_keys, + get_region_kconfig_name, +) + +# Cache for loaded publisher definitions (loaded once per script execution) +_cached_publishers = None +_publishers_load_attempted = False + + +def discover_publishers_from_images(images, quiet=False): + """ + Dynamically discover Linux publishers from image display names. + + This function analyzes image names to find publishers beyond the + hard-coded list, enabling automatic discovery of new Linux distributions. + + Args: + images (list): List of OCI image objects + quiet (bool): Suppress debug messages + + Returns: + dict: Dictionary of discovered publisher patterns + """ + discovered = {} + seen_patterns = defaultdict(set) + + # Patterns to check for potential new Linux distributions + # Format: (regex_pattern, key, publisher_name, description) + # Only match distributions with "Linux" in the name - this is self-filtering + # and doesn't require explicit exclusion of non-Linux systems + discovery_patterns = [ + (r"^([\w\-]+)-Linux-", None, None, "Linux"), + ] + + for image in images: + display_name = image.display_name + + # Check for Linux patterns + for pattern_regex, _, _, suffix in discovery_patterns: + match = re.match(pattern_regex, display_name, re.IGNORECASE) + if match: + publisher_prefix = match.group(1).lower() + + # Skip if we already know this publisher + known_publishers = get_known_publishers() + if publisher_prefix in known_publishers: + continue + + # Create a key for this publisher + if publisher_prefix not in discovered: + # Capitalize properly for display + display_name_parts = publisher_prefix.split("-") + publisher_display = " ".join( + part.capitalize() for part in display_name_parts + ) + + discovered[publisher_prefix] = { + "publisher_name": publisher_display, + "description": f"{publisher_display} {suffix}", + "display_name_patterns": [], + "priority": 100, # Lower priority for discovered + "discovered": True, # Mark as dynamically discovered + } + + # Add the pattern for this publisher + pattern_str = f"{match.group(1)}-.*" + seen_patterns[publisher_prefix].add(pattern_str) + + # Update discovered publishers with their patterns + for key, patterns in seen_patterns.items(): + if key in discovered: + discovered[key]["display_name_patterns"] = list(patterns) + + if not quiet and discovered: + print( + f"Dynamically discovered {len(discovered)} new Linux publisher(s):", + file=sys.stderr, + ) + for key, info in discovered.items(): + print( + f" - {info['publisher_name']}: {info['description']}", file=sys.stderr + ) + + return discovered + + +def get_known_publishers(): + """ + Get dictionary of known OS image publishers in OCI. + + Publisher definitions are loaded from publisher_definitions.yml to make + it easier to update when Oracle adds new Linux distributions or when you + want to customize publisher priorities and naming. + + The YAML file contains publisher information including: + - publisher_name: Display name for the publisher/company + - description: Full description used in Kconfig help text + - display_name_patterns: List of regex patterns to match image names + - priority: Display order (lower numbers appear first) + + If the YAML file is not found or fails to parse, an empty dictionary + is returned and the script relies on dynamic publisher discovery via + discover_publishers_from_images() to identify Linux distributions. + + The publishers are cached after first load to avoid repeated file I/O + and duplicate warnings. + + To update the publisher definitions: + 1. Edit terraform/oci/scripts/publisher_definitions.yml + 2. Add or modify entries following the existing format + 3. Regenerate Kconfig.images by running this script + + See publisher_definitions.yml for detailed update instructions. + + Returns: + dict: Dictionary mapping publisher keys to publisher information, + or empty dict if YAML is unavailable (dynamic discovery + will be used instead) + """ + global _cached_publishers, _publishers_load_attempted + + # Return cached result if already loaded + if _publishers_load_attempted: + return _cached_publishers if _cached_publishers else {} + + # Mark that we've attempted to load (even if it fails) + _publishers_load_attempted = True + + _cached_publishers = load_yaml_config("publisher_definitions.yml", quiet=True) + if not _cached_publishers: + print( + "Warning: publisher_definitions.yml not found or empty. " + "Relying on dynamic publisher discovery.", + file=sys.stderr, + ) + return _cached_publishers + + +def get_image_type_description(listing_type): + """ + Convert OCI listing_type to user-friendly description. + + Note: This script only processes platform images (listing_type "NONE" or None). + + Args: + listing_type (str): OCI image listing_type + + Returns: + str: User-friendly description + """ + if listing_type == "NONE" or listing_type is None: + return "Platform image" + else: + # Unexpected listing type - should not happen with platform-only images + return f"Image ({listing_type})" + + +def get_all_images(compartment_ocid, regions=None, quiet=False): + """ + Get all available platform images across specified regions with dynamic + publisher discovery. + + This enhanced version discovers new Linux publishers dynamically while + fetching images. + + Args: + compartment_ocid (str): OCI compartment OCID + regions (list): List of region names to query. If None, uses default region. + quiet (bool): Suppress debug messages + + Returns: + tuple: (images_dict, all_publishers) where: + - images_dict: Dictionary mapping (display_name, arch) to region->ocid mappings + - all_publishers: Combined dictionary of known and discovered publishers + """ + # Lazy import of OCI exceptions - only needed when actually using OCI API + from oci.exceptions import ServiceError, ConfigFileNotFound + + if regions is None: + regions = [get_default_region()] + + # Store images as: {(display_name, arch): {region: ocid, listing_type: type}} + all_images = defaultdict(lambda: {"regions": {}, "listing_type": None}) + all_image_objects = [] # Keep track of image objects for discovery + + for region in regions: + if not quiet: + print(f"Fetching images from {region}...", file=sys.stderr) + + try: + compute = create_compute_client(region) + + images_response = compute.list_images( + compartment_ocid, sort_by="DISPLAYNAME", sort_order="ASC" + ) + images = images_response.data + all_image_objects.extend(images) # Collect for publisher discovery + + # First pass: collect all images (we'll filter after discovery) + for image in images: + display_name = image.display_name + arch = get_image_architecture(display_name) + key = (display_name, arch) + all_images[key]["regions"][region] = image.id + # Capture listing_type (should be same across regions for same image) + if all_images[key]["listing_type"] is None: + all_images[key]["listing_type"] = getattr( + image, "listing_type", None + ) + + except ConfigFileNotFound: + print( + "Error: OCI config file not found. Please configure OCI CLI.", + file=sys.stderr, + ) + return {}, {} + except ServiceError as e: + print(f" Warning: Could not query {region}: {e.message}", file=sys.stderr) + continue + except Exception as e: + print(f" Warning: Error querying {region}: {e}", file=sys.stderr) + continue + + # Discover new publishers from the collected images + discovered_publishers = discover_publishers_from_images(all_image_objects, quiet) + + # Merge known and discovered publishers + all_publishers = get_known_publishers() + all_publishers.update(discovered_publishers) + + # Now filter images based on all publishers (known + discovered) + filtered_images = defaultdict(lambda: {"regions": {}, "listing_type": None}) + recognized_count = 0 + + for (display_name, arch), image_data in all_images.items(): + if is_recognized_image(display_name, all_publishers): + filtered_images[(display_name, arch)] = image_data + recognized_count += 1 + + if not quiet: + print( + f"\nTotal publishers: {len(all_publishers)} " + f"({len(discovered_publishers)} discovered)", + file=sys.stderr, + ) + print(f"Total recognized Linux images: {recognized_count}", file=sys.stderr) + + return filtered_images, all_publishers + + +def is_recognized_image(display_name, publishers): + """ + Check if an image display name matches any publisher patterns. + + All publisher patterns are Linux-specific, so no explicit exclusion + of non-Linux systems is needed. + + Args: + display_name (str): Image display name + publishers (dict): Dictionary of publisher information + + Returns: + bool: True if image is recognized + """ + for publisher_info in publishers.values(): + for pattern in publisher_info["display_name_patterns"]: + if re.match(pattern, display_name, re.IGNORECASE): + return True + return False + + +def get_image_architecture(display_name): + """ + Infer image architecture from display name. + + Args: + display_name (str): Image display name + + Returns: + str: 'x86_64' or 'arm64' + """ + display_lower = display_name.lower() + if "aarch64" in display_lower or "arm64" in display_lower: + return "arm64" + elif "gpu" in display_lower or "gen2-gpu" in display_lower: + return "x86_64" # GPU instances are x86_64 + else: + return "x86_64" # Default to x86_64 + + +def classify_image(display_name, publishers): + """ + Classify an image into publisher and version groups using dynamic publishers. + + Args: + display_name (str): Image display name + publishers (dict): Dictionary of publisher information + + Returns: + tuple: (publisher_key, version_key, friendly_name, full_display_name) + """ + display_lower = display_name.lower() + + # Check each publisher's patterns + for pub_key, pub_info in publishers.items(): + for pattern in pub_info["display_name_patterns"]: + if re.match(pattern, display_name, re.IGNORECASE): + # Found a matching publisher + # Extract version using the publisher's pattern as a guide + # Convert pattern like "Oracle-Linux-.*" to "Oracle-Linux-" + # Then look for version number immediately after this prefix + version_match = None + + # Try to extract the prefix from the pattern (remove wildcards) + prefix = pattern.replace(".*", "").replace("\\d+", "").replace("-$", "") + if prefix: + # Look for version after the prefix: prefix-X.Y or prefix X.Y + version_pattern = rf"{re.escape(prefix)}[-\s](\d+(?:\.\d+)?)" + version_match = re.search( + version_pattern, display_name, re.IGNORECASE + ) + + # Fallback: match version numbers followed by a hyphen + # This matches platform images (e.g., "Oracle-Linux-9.6-2025...") + if not version_match: + version_match = re.search(r"(\d+(?:\.\d+)?)-", display_name) + + if version_match: + version = version_match.group(1).replace(".", "_") + + # Determine architecture variant + variant = "" + if "gen2-gpu" in display_lower: + variant = "_GPU" + elif "aarch64" in display_lower or "arm64" in display_lower: + variant = "_ARM64" + else: + variant = "_X86" + + # Create version key + version_key = f"{pub_key.upper()}_{version}{variant}" + + # Create friendly name + friendly_name = ( + f"{pub_info['description']} {version_match.group(1)}" + ) + if variant == "_GPU": + friendly_name += " Gen2 GPU" + elif variant == "_ARM64": + friendly_name += " (aarch64)" + elif variant == "_X86": + friendly_name += " (x86)" + + # Add discovered marker if applicable + if pub_info.get("discovered"): + friendly_name += " [NEW]" + + return (pub_key, version_key, friendly_name, display_name) + + return (None, None, None, None) + + +def organize_images_by_publisher(images_dict, publishers, quiet=False): + """ + Organize images by publisher and version using dynamic publishers. + + Args: + images_dict (dict): Dictionary from get_all_images() + publishers (dict): Dictionary of publisher information + quiet (bool): Suppress debug messages + + Returns: + dict: Organized structure {publisher: {version_key: {regions, display_name, ...}}} + """ + organized = defaultdict(lambda: defaultdict(dict)) + + for (display_name, arch), image_data in images_dict.items(): + publisher_key, version_key, friendly_name, full_display_name = classify_image( + display_name, publishers + ) + + if not publisher_key or not version_key: + continue + + # Extract region OCIDs and listing type from the data structure + region_ocids = image_data["regions"] + listing_type = image_data.get("listing_type") + + # Multiple platform images may map to same version_key with different + # release dates (e.g., Oracle-Linux-9.5-2024.01.01 and 9.5-2024.02.01). + # Keep the newest image by comparing release dates in display names. + if version_key in organized[publisher_key]: + existing_display_name = organized[publisher_key][version_key][ + "display_name" + ] + # Extract dates from display names (format: YYYY.MM.DD) + # Dates are alphabetically sortable, so simple string comparison works + if display_name <= existing_display_name: + # Current image is older or same, keep existing + continue + # Current image is newer, replace existing (fall through to store) + + # Store image information + organized[publisher_key][version_key] = { + "friendly_name": friendly_name, + "display_name": full_display_name, + "architecture": arch, + "region_ocids": region_ocids, + "listing_type": listing_type, + "image_type": get_image_type_description(listing_type), + } + + if not quiet: + for publisher, versions in organized.items(): + pub_info = publishers.get(publisher, {}) + status = " (discovered)" if pub_info.get("discovered") else "" + print( + f"Publisher '{publisher}'{status}: {len(versions)} versions", + file=sys.stderr, + ) + + return organized + + +def get_release_notes_url(display_name): + """ + Generate the Oracle Cloud documentation URL for an image's release notes. + + Args: + display_name (str): Image display name + + Returns: + str: URL to release notes or empty string if not applicable + """ + # Convert display name to URL-friendly format + # Example: Oracle-Linux-9.6-2025.06.17-0 -> + # oracle-linux-9-6-2025-06-17-0 + url_slug = display_name.lower() + url_slug = url_slug.replace("canonical-ubuntu-", "ubuntu-") + url_slug = url_slug.replace(".", "-") + + # Determine the base path + if "oracle-linux" in display_name.lower(): + # Determine major version for URL path + version_match = re.search(r"(\d+)\.", display_name) + if version_match: + major_version = version_match.group(1) + return f"https://docs.oracle.com/en-us/iaas/images/oracle-linux-{major_version}x/{url_slug}.htm" + elif "ubuntu" in display_name.lower(): + # Determine version for URL path (2004, 2204, 2404) + version_match = re.search(r"(\d+)\.(\d+)", display_name) + if version_match: + major = version_match.group(1) + minor = version_match.group(2) + version_str = f"{major}{minor}" + return f"https://docs.oracle.com/en-us/iaas/images/ubuntu-{version_str}/{url_slug}.htm" + + return "" + + +def output_images_kconfig(organized_images, publishers, regions, region_key_map): + """ + Output images menu in Kconfig format with dynamic publishers. + + Args: + organized_images (dict): Organized images from organize_images_by_publisher() + publishers (dict): Dictionary of all publishers (known + discovered) + regions (list): List of region names that were queried + region_key_map (dict): Mapping from region_name to region_key + """ + # Output header comment showing which regions were queried + print("# This file was auto-generated by gen_kconfig_image") + print("# Queried OCI regions: " + ", ".join(sorted(regions))) + print("#") + print("# Note: Images may not be available in regions not listed above.") + print("# See individual image help text for specific region availability.") + print() + + environment = get_jinja2_environment() + + # Sort publishers by priority for consistent ordering + sorted_publishers = sorted( + [(k, v) for k, v in publishers.items() if k in organized_images], + key=lambda x: (x[1].get("priority", 100), x[0]), + ) + + # Output the top-level distribution choice menu + template = environment.get_template("image_distributions.j2") + print( + template.render( + publishers=[pub[0] for pub in sorted_publishers], + ) + ) + print() + + # Create a lambda that uses the region_key_map + def get_kconfig_name(region_name): + return get_region_kconfig_name(region_name, region_key_map) + + def version_sort_key(version_item): + """ + Extract numeric version from version_key for proper chronological sorting. + + Version keys are like: ORACLE_9_6_X86, UBUNTU_22_04_ARM64 + Sort by numeric version (oldest to newest), not alphabetic. + """ + version_key, version_data = version_item + parts = version_key.split("_") + + # Remove publisher prefix, leaving version numbers and architecture + # Could be: [major, minor, arch] or [major, arch] + version_parts = parts[1:] + + major = 0 + minor = 0 + + # The last part is usually the architecture (X86, ARM64, GPU) + # Everything before that is version numbers + if len(version_parts) >= 2: + try: + major = int(version_parts[0]) + # Try to parse second part as minor version + if len(version_parts) >= 3: + try: + minor = int(version_parts[1]) + except ValueError: + # Second part is arch, no minor version + minor = 0 + except ValueError: + pass + + # Architecture preference: X86, ARM64, GPU for consistent ordering + arch_order = {"X86": 0, "ARM64": 1, "GPU": 2} + arch = version_parts[-1] if version_parts else "X86" + arch_priority = arch_order.get(arch, 99) + + return (major, minor, arch_priority) + + # Output each publisher's images + template = environment.get_template("image_publisher.j2") + for publisher_key, publisher_info in sorted_publishers: + versions = organized_images.get(publisher_key, {}) + + # Sort versions numerically (oldest to newest) + sorted_versions = sorted(versions.items(), key=version_sort_key) + + # Add discovered marker to description if applicable + description = publisher_info.get("description", publisher_key) + if publisher_info.get("discovered"): + description += " (Discovered)" + + print( + template.render( + publisher_key=publisher_key, + publisher_name=publisher_info.get("publisher_name", publisher_key), + publisher_description=description, + versions=sorted_versions, + get_release_notes_url=get_release_notes_url, + get_region_kconfig_name=get_kconfig_name, + ) + ) + print() + + +def output_publishers_raw(quiet=False): + """Output available publishers in table format.""" + publishers = get_known_publishers() + + if not quiet: + print(f"Known OS image publishers ({len(publishers)}):\n") + + print(f"{'Publisher Key':<15} {'Publisher Name':<20} {'Description':<30}") + print("-" * 70) + + for key, info in publishers.items(): + print( + f"{key:<15} " f"{info['publisher_name']:<20} " f"{info['description']:<30}" + ) + + +def output_publisher_raw(publisher_key, organized_images, quiet=False): + """Output publisher image information in table format.""" + publishers = get_known_publishers() + publisher_info = publishers.get(publisher_key, {}) + + if not quiet: + print(f"Images for {publisher_info.get('publisher_name', publisher_key)}") + print(f"Description: {publisher_info.get('description', '')}\n") + + versions = organized_images.get(publisher_key, {}) + if not versions: + print(f"No images found for publisher '{publisher_key}'.") + return + + print(f"{'Version':<40} {'Architecture':<15} {'Regions':<10}") + print("-" * 70) + + for version_key, version_info in sorted(versions.items()): + region_count = len(version_info["region_ocids"]) + print( + f"{version_info['friendly_name']:<40} " + f"{version_info['architecture']:<15} " + f"{region_count:<10}" + ) + + +def parse_arguments(): + """Parse command line arguments.""" + parser = argparse.ArgumentParser( + description="Get OCI compute image information and generate Kconfig", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Generate Kconfig from all subscribed regions (default) + python %(prog)s > ../kconfigs/Kconfig.images + + # List available publishers + python %(prog)s --publishers + + # Get details for a specific publisher + python %(prog)s oracle --format raw + + # Query specific region only + python %(prog)s --region us-chicago-1 + """, + ) + parser.add_argument( + "publisher_key", nargs="?", help="Publisher key (e.g., oracle, ubuntu)" + ) + + parser.add_argument( + "--publishers", action="store_true", help="List all known publishers" + ) + parser.add_argument( + "--format", + "-f", + choices=["raw", "kconfig"], + default="kconfig", + help="Output format (default: kconfig)", + ) + parser.add_argument( + "--quiet", "-q", action="store_true", help="Suppress informational messages" + ) + parser.add_argument( + "--region", + "-r", + help="Query specific region only (default: aggregate from all subscribed regions)", + ) + return parser.parse_args() + + +def main(): + """Main function to run the program.""" + args = parse_arguments() + + if args.publishers: + # Show both known and discovered publishers + compartment_ocid = get_default_compartment() + if compartment_ocid: + # Get one region's images to discover publishers + region = get_default_region() + images_dict, all_publishers = get_all_images( + compartment_ocid, [region], True + ) # Quiet mode for discovery + + print("Known and Discovered Linux Publishers:") + print("-" * 70) + print( + f"{'Publisher Key':<15} {'Publisher Name':<20} {'Description':<25} {'Status':<10}" + ) + print("-" * 70) + + sorted_pubs = sorted( + all_publishers.items(), key=lambda x: (x[1].get("priority", 100), x[0]) + ) + for key, info in sorted_pubs: + status = "Discovered" if info.get("discovered") else "Built-in" + print( + f"{key:<15} " + f"{info['publisher_name']:<20} " + f"{info['description']:<25} " + f"{status:<10}" + ) + else: + output_publishers_raw(args.quiet) + return + + compartment_ocid = get_default_compartment() + if not compartment_ocid: + print("Error: Could not determine compartment OCID", file=sys.stderr) + sys.exit(1) + + # Get region key mappings from OCI API + region_key_map = get_all_region_keys(args.quiet) + + # Determine which regions to query + if args.region: + regions = [args.region] + else: + regions = get_subscribed_regions(args.quiet) + + # Get platform images from OCI API with dynamic publisher discovery + images_dict, all_publishers = get_all_images(compartment_ocid, regions, args.quiet) + + if not images_dict: + print("Error: No images found", file=sys.stderr) + sys.exit(1) + + # Organize images by publisher using discovered publishers + organized_images = organize_images_by_publisher( + images_dict, all_publishers, args.quiet + ) + + if args.publisher_key: + if args.publisher_key not in organized_images: + print(f"Error: Unknown publisher '{args.publisher_key}'", file=sys.stderr) + print( + f"Available publishers: {', '.join(organized_images.keys())}", + file=sys.stderr, + ) + sys.exit(1) + + if args.format == "raw": + output_publisher_raw(args.publisher_key, organized_images, args.quiet) + else: + # For Kconfig format of single publisher, output full menu + output_images_kconfig( + organized_images, all_publishers, regions, region_key_map + ) + return + + # Output full Kconfig menu with dynamic publishers + output_images_kconfig(organized_images, all_publishers, regions, region_key_map) + + +if __name__ == "__main__": + main() diff --git a/terraform/oci/scripts/image_distributions.j2 b/terraform/oci/scripts/image_distributions.j2 new file mode 100644 index 000000000..ecfa38eb6 --- /dev/null +++ b/terraform/oci/scripts/image_distributions.j2 @@ -0,0 +1,90 @@ +choice + prompt "Distribution" +{% if 'oracle' in publishers %} + default TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX +{% elif 'ubuntu' in publishers %} + default TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU +{% elif 'centos' in publishers %} + default TERRAFORM_OCI_OPERATING_SYSTEM_CENTOS +{% elif publishers %} + default TERRAFORM_OCI_OPERATING_SYSTEM_{{ publishers[0] | upper }} +{% endif %} + help + Select the Linux distribution to install on each instance. + + The distributions listed here are official OCI platform images + provided by Oracle. These images are well-tested, actively + maintained, and available across all subscribed regions. + + For marketplace or custom images, select "Custom image OCID" + below and enter the image OCID directly. + +{% for publisher_key in publishers %} +{% if publisher_key == 'oracle' %} +config TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX + bool "Oracle Linux" + help + Select this if you want to use a release of Oracle Linux + as the operating system in your instances. + +{% elif publisher_key == 'ubuntu' %} +config TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU + bool "Ubuntu" + help + Select this if you want to use a release of Ubuntu Linux + as the operating system in your instances. + +{% else %} +config TERRAFORM_OCI_OPERATING_SYSTEM_{{ publisher_key | upper }} + bool "{{ publisher_key | title }}" + help + Select this if you want to use a release of {{ publisher_key | title }} + as the operating system in your instances. + +{% endif %} +{% endfor %} + +config TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM + bool "Custom image OCID" + help + Select this if you want to enter a specific OCID for + an OS image. Use this option for: + + - Marketplace images (not included in automated menu) + - Community images + - Custom-built images + - Older platform image releases + + Note: The automated distribution menu above only includes + official OCI platform images. Marketplace images must be + specified manually using this custom OCID option. + + The image you specify must reside in the same region as + your instances. + + More image choices are available: + + https://docs.oracle.com/en-us/iaas/images/ + +endchoice + +if TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM + +config TERRAFORM_OCI_OS_IMAGE_OCID + string "OS image OCID" + output yaml + help + An image is a template of a virtual hard drive. It + contains the operating system and other software for each + instance. Select an image by specifying the OCID of the + image to use. You can select: + + - An older release than the latest image release + - An older operating system release + - A custom-made image + + More detail is available: + + https://docs.oracle.com/en-us/iaas/Content/Compute/References/bringyourownimage.htm + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_CUSTOM diff --git a/terraform/oci/scripts/image_publisher.j2 b/terraform/oci/scripts/image_publisher.j2 new file mode 100644 index 000000000..8772f7a5d --- /dev/null +++ b/terraform/oci/scripts/image_publisher.j2 @@ -0,0 +1,79 @@ +{# + This template is rendered by gen_kconfig_image script. + + Template variables: + - publisher_key: str (e.g., 'oracle', 'ubuntu') + - publisher_name: str (e.g., 'Oracle Linux') + - publisher_description: str (full description) + - versions: list of (version_key, version_info) tuples (pre-sorted) + - get_release_notes_url: function to generate doc URLs + - get_region_kconfig_name: function to convert region names +#} +{% if publisher_key == 'oracle' %} +if TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX +{% elif publisher_key == 'ubuntu' %} +if TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU +{% else %} +if TERRAFORM_OCI_OPERATING_SYSTEM_{{ publisher_key | upper }} +{% endif %} + +choice + prompt "OS release" +{# versions is a list of (version_key, version_info) tuples from sorted_versions in gen_kconfig_image #} +{% for version_key, version_info in versions | reverse %} +{% if "ARM64" in version_key %} + default TERRAFORM_OCI_OPERATING_SYSTEM_{{ version_key }} if TARGET_ARCH_ARM64 +{% elif "X86" in version_key %} + default TERRAFORM_OCI_OPERATING_SYSTEM_{{ version_key }} if TARGET_ARCH_X86_64 +{% endif %} +{% endfor %} + help + Select the release of {{ publisher_description }} to install on each + instance. + +{% for version_key, version_info in versions %} +config TERRAFORM_OCI_OPERATING_SYSTEM_{{ version_key }} + bool "{{ version_info['friendly_name'] }}" +{% if "ARM64" in version_key %} + depends on TARGET_ARCH_ARM64 +{% elif "GPU" in version_key %} + depends on TARGET_ARCH_X86_64 +{% elif "X86" in version_key %} + depends on TARGET_ARCH_X86_64 +{% endif %} + help + {{ version_info['display_name'] }} + + Image type: {{ version_info.get('image_type', 'Unknown') }} + + Available in regions: {% for region in version_info['region_ocids'].keys() | sort %}{{ region }}{% if not loop.last %}, {% endif %}{% endfor %} + +{% if get_release_notes_url(version_info['display_name']) %} + Image release notes: + {{ get_release_notes_url(version_info['display_name']) }} +{% endif %} + +{% endfor %} +endchoice + +{% for version_key, version_info in versions %} +if TERRAFORM_OCI_OPERATING_SYSTEM_{{ version_key }} + +config TERRAFORM_OCI_OS_IMAGE_OCID + string + output yaml +{# version_info['region_ocids'] is a dict, so .items() is required here #} +{% for region, ocid in version_info['region_ocids'].items() %} + default "{{ ocid }}" if TERRAFORM_OCI_REGION_{{ get_region_kconfig_name(region) }} +{% endfor %} + +endif # TERRAFORM_OCI_OPERATING_SYSTEM_{{ version_key }} + +{% endfor %} +{% if publisher_key == 'oracle' %} +endif # TERRAFORM_OCI_OPERATING_SYSTEM_ORACLE_LINUX +{% elif publisher_key == 'ubuntu' %} +endif # TERRAFORM_OCI_OPERATING_SYSTEM_UBUNTU +{% else %} +endif # TERRAFORM_OCI_OPERATING_SYSTEM_{{ publisher_key | upper }} +{% endif %} diff --git a/terraform/oci/scripts/publisher_definitions.yml b/terraform/oci/scripts/publisher_definitions.yml new file mode 100644 index 000000000..5d382163c --- /dev/null +++ b/terraform/oci/scripts/publisher_definitions.yml @@ -0,0 +1,148 @@ +# OCI Image Publisher Definitions +# +# This file defines known OS image publishers in Oracle Cloud Infrastructure +# and their image naming patterns for automatic image discovery. +# +# Purpose: +# When generating Kconfig.images, the gen_kconfig_image script uses these +# publisher definitions to: +# - Recognize and categorize OS images by their display names +# - Generate organized Kconfig menus grouped by Linux distribution +# - Provide friendly names and descriptions for each distribution +# +# Dynamic Discovery: +# In addition to these known publishers, the gen_kconfig_image script can +# dynamically discover new Linux distributions by analyzing image naming +# patterns. Discovered publishers are marked with [NEW] in the generated +# Kconfig output. +# +# Last Verified: 2025-10-21 +# Total Publishers: 10 +# +# Format: +# ------- +# publisher_key: +# publisher_name: "Display Name" +# description: "Full Description" +# display_name_patterns: +# - "regex-pattern-1" +# - "regex-pattern-2" +# priority: N +# +# Fields: +# publisher_key: Short identifier (lowercase, used in Kconfig symbols) +# publisher_name: Human-friendly publisher/company name +# description: Full description shown in Kconfig help text +# display_name_patterns: List of regex patterns to match image display names +# priority: Display order (lower numbers appear first) +# +# How to update this file: +# ------------------------ +# When Oracle adds new Linux distributions or you want to customize the list: +# +# 1. Find available images in your OCI tenancy: +# $ oci compute image list --compartment-id \ +# --sort-by DISPLAYNAME --all +# +# 2. Identify the image naming pattern from the display_name field. +# Examples: +# - "Oracle-Linux-9.6-2025.06.17-0" -> Pattern: "Oracle-Linux-.*" +# - "Canonical-Ubuntu-22.04-2024.10.14-0" -> Pattern: "Canonical-Ubuntu-.*" +# - "AlmaLinux-8-2024.10.11-0" -> Pattern: "AlmaLinux-.*" +# +# 3. Add a new publisher entry following the format above. Choose: +# - A unique publisher_key (lowercase, no spaces) +# - A descriptive publisher_name and description +# - Regex patterns that match all variants of that distribution +# - A priority number (higher numbers appear later in menus) +# +# 4. Update the "Last Verified" date and "Total Publishers" count above. +# +# 5. After updating this file, regenerate the Kconfig.images file: +# $ cd terraform/oci/scripts +# $ ./gen_kconfig_image > ../kconfigs/Kconfig.images +# +# 6. You can verify your patterns match correctly by running: +# $ ./gen_kconfig_image --publishers +# +# Notes: +# ------ +# - Patterns are evaluated as Python regex with re.IGNORECASE flag +# - The script processes images in priority order (lower priority first) +# - Only Linux distributions are included (no Windows, BSD, etc.) +# - Dynamic discovery can find new distributions not listed here +# +# Publisher Definitions: +# ---------------------- + +oracle: + publisher_name: "Oracle" + description: "Oracle Linux" + display_name_patterns: + - "Oracle-Linux-.*" + - "Oracle Linux .*" + - "Oracle-Autonomous-Linux-.*" + priority: 1 + +ubuntu: + publisher_name: "Canonical" + description: "Ubuntu" + display_name_patterns: + - "Canonical-Ubuntu-.*" + priority: 2 + +centos: + publisher_name: "CentOS" + description: "CentOS Linux" + display_name_patterns: + - "CentOS-\\d+-.*" + priority: 3 + +almalinux: + publisher_name: "AlmaLinux" + description: "AlmaLinux OS" + display_name_patterns: + - "AlmaLinux-.*" + priority: 4 + +rocky: + publisher_name: "Rocky Enterprise" + description: "Rocky Linux" + display_name_patterns: + - "Rocky-Linux-.*" + priority: 5 + +suse: + publisher_name: "SUSE" + description: "SUSE Linux Enterprise" + display_name_patterns: + - "SUSE-.*" + priority: 6 + +opensuse: + publisher_name: "openSUSE" + description: "openSUSE Linux" + display_name_patterns: + - "openSUSE-.*" + priority: 7 + +redhat: + publisher_name: "Red Hat" + description: "Red Hat Enterprise Linux" + display_name_patterns: + - "Red-Hat-.*" + priority: 8 + +debian: + publisher_name: "Debian" + description: "Debian Linux" + display_name_patterns: + - "Debian-.*" + priority: 9 + +fedora: + publisher_name: "Fedora" + description: "Fedora Linux" + display_name_patterns: + - "Fedora-.*" + priority: 10 From 68ce84ee283ad8aea69bfa7503ea3c01455e56d6 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 22 Oct 2025 16:30:31 -0400 Subject: [PATCH 11/11] Add Kconfig.image.generated to generate_cloud_configs.py Teach "make cloud-config" and "make cloud-config-oci" to update the Kconfig.image menu with dynamically discovered information. This information is based on what resources are available to the user's tenancy and region subscription. This support is intended to work like the reference implementation under terraform/lambdalabs/ Signed-off-by: Chuck Lever --- .gitignore | 1 + scripts/dynamic-cloud-kconfig.Makefile | 3 ++- scripts/generate_cloud_configs.py | 1 + terraform/oci/Kconfig | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 76c297edf..7472860ee 100644 --- a/.gitignore +++ b/.gitignore @@ -122,6 +122,7 @@ terraform/aws/kconfigs/Kconfig.instance.generated terraform/aws/kconfigs/Kconfig.location.generated terraform/aws/scripts/__pycache__/ +terraform/oci/kconfigs/Kconfig.image.generated terraform/oci/kconfigs/Kconfig.location.generated terraform/oci/kconfigs/Kconfig.shape.generated terraform/oci/scripts/__pycache__/ diff --git a/scripts/dynamic-cloud-kconfig.Makefile b/scripts/dynamic-cloud-kconfig.Makefile index 72ec94a54..d5015f5f2 100644 --- a/scripts/dynamic-cloud-kconfig.Makefile +++ b/scripts/dynamic-cloud-kconfig.Makefile @@ -22,10 +22,11 @@ AWS_KCONFIGS := $(AWS_KCONFIG_AMI) $(AWS_KCONFIG_INSTANCE) $(AWS_KCONFIG_LOCATIO # OCI dynamic configuration OCI_KCONFIG_DIR := terraform/oci/kconfigs +OCI_KCONFIG_IMAGE := $(OCI_KCONFIG_DIR)/Kconfig.image.generated OCI_KCONFIG_LOCATION := $(OCI_KCONFIG_DIR)/Kconfig.location.generated OCI_KCONFIG_SHAPE := $(OCI_KCONFIG_DIR)/Kconfig.shape.generated -OCI_KCONFIGS := $(OCI_KCONFIG_LOCATION) $(OCI_KCONFIG_SHAPE) +OCI_KCONFIGS := $(OCI_KCONFIG_IMAGE) $(OCI_KCONFIG_LOCATION) $(OCI_KCONFIG_SHAPE) # Add generated files to mrproper clean list KDEVOPS_MRPROPER += $(LAMBDALABS_KCONFIGS) $(AWS_KCONFIGS) $(OCI_KCONFIGS) diff --git a/scripts/generate_cloud_configs.py b/scripts/generate_cloud_configs.py index 20041d6b7..d14b56d20 100755 --- a/scripts/generate_cloud_configs.py +++ b/scripts/generate_cloud_configs.py @@ -159,6 +159,7 @@ def generate_oci_kconfig() -> bool: # Define the script-to-output mapping scripts_to_run = [ + ("gen_kconfig_image", "Kconfig.image.generated"), ("gen_kconfig_location", "Kconfig.location.generated"), ("gen_kconfig_shape", "Kconfig.shape.generated"), ] diff --git a/terraform/oci/Kconfig b/terraform/oci/Kconfig index aabb751b1..3369578b3 100644 --- a/terraform/oci/Kconfig +++ b/terraform/oci/Kconfig @@ -13,7 +13,7 @@ menu "Compute" comment "Shape selection" source "terraform/oci/kconfigs/Kconfig.shape.generated" comment "OS image selection" -source "terraform/oci/kconfigs/Kconfig.image" +source "terraform/oci/kconfigs/Kconfig.image.generated" endmenu menu "Storage" source "terraform/oci/kconfigs/Kconfig.storage"