commitments

package
v0.0.0-...-0e8ba2f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2026 License: Apache-2.0 Imports: 48 Imported by: 0

Documentation

Index

Constants

View Source
const (

	// Resource type suffixes
	ResourceSuffixRAM       = "_ram"
	ResourceSuffixCores     = "_cores"
	ResourceSuffixInstances = "_instances"
)

Limes LIQUID resource naming convention: hw_version_<flavorgroup>_<resourcetype> Supported resource types: _ram, _cores, _instances

View Source
const (
	SkipReasonUnitMismatch       = "unit_mismatch"
	SkipReasonUnknownFlavorGroup = "unknown_flavor_group"
	SkipReasonInvalidResource    = "invalid_resource_name"
	SkipReasonEmptyUUID          = "empty_uuid"
	SkipReasonNonCompute         = "non_compute"
)

Skip reason labels for commitment processing

Variables

View Source
var (
	// CreatorValue identifies reservations created by this syncer.
	CreatorValue = "commitments-syncer"
)

Functions

func CheckCommitmentsInfoEndpoint

func CheckCommitmentsInfoEndpoint(ctx context.Context, config E2EChecksConfig)

CheckCommitmentsInfoEndpoint sends a GET request to the /commitments/v1/info endpoint and verifies that it returns HTTP 200 with a valid ServiceInfo response.

func FlavorGroupAcceptsCommitments

func FlavorGroupAcceptsCommitments(fg *compute.FlavorGroupFeature) bool

FlavorGroupAcceptsCommitments returns true if the given flavor group can accept committed resources. Currently, only groups with a fixed RAM/core ratio (all flavors have the same ratio) accept CRs. This is the single source of truth for CR eligibility and should be used across all CR APIs.

func FlavorGroupCommitmentRejectionReason

func FlavorGroupCommitmentRejectionReason(fg *compute.FlavorGroupFeature) string

FlavorGroupCommitmentRejectionReason returns the reason why the given flavor group does not accept CRs. Returns empty string if the group accepts commitments.

func GetMaxSlotIndex

func GetMaxSlotIndex(reservations []v1alpha1.Reservation) int

func GetNextSlotIndex

func GetNextSlotIndex(reservations []v1alpha1.Reservation) int

Always continue counting slots from max, instead of filling gaps.

func LoggerFromContext

func LoggerFromContext(ctx context.Context) logr.Logger

LoggerFromContext returns a logger with greq and req values from the context. This creates a child logger with the request tracking values pre-attached, so you don't need to repeat them in every log call.

func ResourceNameCores

func ResourceNameCores(flavorGroup string) string

ResourceNameCores creates a LIQUID resource name for CPU cores from a flavor group name. Format: hw_version_<flavorgroup>_cores

func ResourceNameInstances

func ResourceNameInstances(flavorGroup string) string

ResourceNameInstances creates a LIQUID resource name for instance count from a flavor group name. Format: hw_version_<flavorgroup>_instances

func ResourceNameRAM

func ResourceNameRAM(flavorGroup string) string

ResourceNameRAM creates a LIQUID resource name for RAM from a flavor group name. Format: hw_version_<flavorgroup>_ram

func RunCommitmentsE2EChecks

func RunCommitmentsE2EChecks(ctx context.Context, config E2EChecksConfig)

RunCommitmentsE2EChecks runs all e2e checks for the commitments API.

func WithGlobalRequestID

func WithGlobalRequestID(ctx context.Context, greq string) context.Context

WithGlobalRequestID creates a new context with the specified global request ID. This is used to propagate existing request IDs (e.g., from the creator annotation).

func WithNewGlobalRequestID

func WithNewGlobalRequestID(ctx context.Context) context.Context

WithNewGlobalRequestID creates a new context with a committed-resource-prefixed global request ID.

Types

type ApplyResult

type ApplyResult struct {
	// Created is the number of reservations created
	Created int
	// Deleted is the number of reservations deleted
	Deleted int
	// Repaired is the number of reservations repaired (metadata sync or recreated due to wrong config)
	Repaired int
	// TouchedReservations are reservations that were created or updated
	TouchedReservations []v1alpha1.Reservation
	// RemovedReservations are reservations that were deleted
	RemovedReservations []v1alpha1.Reservation
}

ApplyResult contains the result of applying a commitment state.

type CapacityCalculator

type CapacityCalculator struct {
	// contains filtered or unexported fields
}

CapacityCalculator computes capacity reports for Limes LIQUID API.

func NewCapacityCalculator

func NewCapacityCalculator(client client.Client) *CapacityCalculator

func (*CapacityCalculator) CalculateCapacity

CalculateCapacity computes per-AZ capacity for all flavor groups. For each flavor group, three resources are reported: _ram, _cores, _instances. All flavor groups are included, not just those with fixed RAM/core ratio. The request provides the list of all AZs from Limes that must be included in the report.

type ChangeCommitmentsAPIMonitor

type ChangeCommitmentsAPIMonitor struct {
	// contains filtered or unexported fields
}

ChangeCommitmentsAPIMonitor provides metrics for the CR change API.

func NewChangeCommitmentsAPIMonitor

func NewChangeCommitmentsAPIMonitor() ChangeCommitmentsAPIMonitor

NewChangeCommitmentsAPIMonitor creates a new monitor with Prometheus metrics. Metrics are pre-initialized with zero values for common HTTP status codes to ensure they appear in Prometheus before the first request.

func (*ChangeCommitmentsAPIMonitor) Collect

func (m *ChangeCommitmentsAPIMonitor) Collect(ch chan<- prometheus.Metric)

Collect implements prometheus.Collector.

func (*ChangeCommitmentsAPIMonitor) Describe

func (m *ChangeCommitmentsAPIMonitor) Describe(ch chan<- *prometheus.Desc)

Describe implements prometheus.Collector.

type Commitment

type Commitment struct {
	// A unique numerical identifier for this commitment. This API uses this
	// numerical ID to refer to the commitment in other API calls.
	ID int `json:"id"`
	// A unique string identifier for this commitment. The next major version of
	// this API will use this UUID instead of the numerical ID to refer to
	// commitments in API calls.
	UUID string `json:"uuid"`
	// The resource for which usage is committed.
	ServiceType  string `json:"service_type"`
	ResourceName string `json:"resource_name"`
	// The availability zone in which usage is committed.
	AvailabilityZone string `json:"availability_zone"`
	// The amount of usage that was committed to.
	Amount uint64 `json:"amount"`
	// For measured resources, the unit for this resource. The value from the
	// amount field is measured in this unit.
	Unit string `json:"unit"`
	// The requested duration of this commitment, expressed as a comma-separated
	// sequence of positive integer multiples of time units like "1 year,
	// 3 months". Acceptable time units include "second", "minute", "hour",
	// "day", "month" and "year".
	Duration string `json:"duration"`
	// UNIX timestamp when this commitment was created.
	CreatedAt uint64 `json:"created_at"`
	// UNIX timestamp when this commitment should be confirmed. Only shown if
	// this was given when creating the commitment, to delay confirmation into
	// the future.
	ConfirmBy *uint64 `json:"confirm_by,omitempty"`
	// UNIX timestamp when this commitment was confirmed. Only shown after
	// confirmation.
	ConfirmedAt *uint64 `json:"confirmed_at,omitempty"`
	// UNIX timestamp when this commitment is set to expire. Note that the
	// duration counts from confirmBy (or from createdAt for immediately-
	// confirmed commitments) and is calculated at creation time, so this is
	// also shown on unconfirmed commitments.
	ExpiresAt uint64 `json:"expires_at"`
	// Whether the commitment is marked for transfer to a different project.
	// Transferable commitments do not count towards quota calculation in their
	// project, but still block capacity and still count towards billing. Not
	// shown if false.
	Transferable bool `json:"transferable"`
	// The current status of this commitment. If provided, one of "planned",
	// "pending", "guaranteed", "confirmed", "superseded", or "expired".
	Status string `json:"status,omitempty"`
	// Whether a mail notification should be sent if a created commitment is
	// confirmed. Can only be set if the commitment contains a confirmBy value.
	NotifyOnConfirm bool `json:"notify_on_confirm"`

	// The openstack project ID this commitment is for.
	ProjectID string `json:"project_id"`
	// The openstack domain ID this commitment is for.
	DomainID string `json:"domain_id"`
}

Commitment model from the limes API. See: https://github.com/sapcc/limes/blob/5ea068b/docs/users/api-spec-resources.md?plain=1#L493 See: https://github.com/sapcc/go-api-declarations/blob/94ee3e5/limes/resources/commitment.go#L19

type CommitmentReservationController

type CommitmentReservationController struct {
	// Client for the kubernetes API.
	client.Client
	// Kubernetes scheme to use for the reservations.
	Scheme *runtime.Scheme
	// Configuration for the controller.
	Conf Config
	// Database connection for querying VM state from Knowledge cache.
	DB *db.DB
	// SchedulerClient for making scheduler API calls.
	SchedulerClient *reservations.SchedulerClient
}

CommitmentReservationController reconciles commitment Reservation objects

func (*CommitmentReservationController) Init

Init initializes the reconciler with required clients and DB connection.

func (*CommitmentReservationController) Reconcile

Reconcile is part of the main kubernetes reconciliation loop which aims to move the current state of the cluster closer to the desired state. Note: This controller only handles commitment reservations, as filtered by the predicate.

func (*CommitmentReservationController) SetupWithManager

func (r *CommitmentReservationController) SetupWithManager(mgr ctrl.Manager, mcl *multicluster.Client) error

SetupWithManager sets up the controller with the Manager.

type CommitmentState

type CommitmentState struct {
	// CommitmentUUID is the UUID of the commitment this state corresponds to.
	CommitmentUUID string
	// ProjectID is the OpenStack project this commitment belongs to
	ProjectID string
	// DomainID is the OpenStack domain this commitment belongs to
	DomainID string
	// FlavorGroupName identifies the flavor group (e.g., "hana_medium_v2")
	FlavorGroupName string
	// the total memory in bytes across all reservation slots
	TotalMemoryBytes int64
	// AvailabilityZone specifies the availability zone for this commitment
	AvailabilityZone string
	// StartTime is when the commitment becomes active
	StartTime *time.Time
	// EndTime is when the commitment expires
	EndTime *time.Time
	// CreatorRequestID is the request ID that triggered this state change (for traceability)
	CreatorRequestID string
}

CommitmentState represents desired or current commitment resource allocation.

func FromChangeCommitmentTargetState

func FromChangeCommitmentTargetState(
	commitment liquid.Commitment,
	projectID string,
	flavorGroupName string,
	flavorGroup compute.FlavorGroupFeature,
	az string,
) (*CommitmentState, error)

FromChangeCommitmentTargetState converts LIQUID API request to CommitmentState.

func FromCommitment

func FromCommitment(
	commitment Commitment,
	flavorGroup compute.FlavorGroupFeature,
) (*CommitmentState, error)

FromCommitment converts Limes commitment to CommitmentState.

func FromReservations

func FromReservations(reservations []v1alpha1.Reservation) (*CommitmentState, error)

FromReservations reconstructs CommitmentState from existing Reservation CRDs.

type CommitmentStateWithUsage

type CommitmentStateWithUsage struct {
	CommitmentState
	// RemainingMemoryBytes is the uncommitted capacity left for VM assignment
	RemainingMemoryBytes int64
	// AssignedVMs tracks which VMs have been assigned to this commitment
	AssignedVMs []string
}

CommitmentStateWithUsage extends CommitmentState with usage tracking for billing calculations. Used by the report-usage API to track remaining capacity during VM-to-commitment assignment.

func NewCommitmentStateWithUsage

func NewCommitmentStateWithUsage(state *CommitmentState) *CommitmentStateWithUsage

NewCommitmentStateWithUsage creates a CommitmentStateWithUsage from a CommitmentState.

func (*CommitmentStateWithUsage) AssignVM

func (c *CommitmentStateWithUsage) AssignVM(vmUUID string, vmMemoryBytes int64) bool

AssignVM attempts to assign a VM to this commitment if there's enough capacity. Returns true if the VM was assigned, false if not enough capacity.

func (*CommitmentStateWithUsage) HasRemainingCapacity

func (c *CommitmentStateWithUsage) HasRemainingCapacity() bool

HasRemainingCapacity returns true if the commitment has any remaining capacity.

type CommitmentsClient

type CommitmentsClient interface {
	// Init the client.
	Init(ctx context.Context, client client.Client, conf SyncerConfig) error
	// List all projects to resolve commitments.
	ListProjects(ctx context.Context) ([]Project, error)
	// List all commitments with resolved metadata (e.g. project, flavor, ...).
	ListCommitmentsByID(ctx context.Context, projects ...Project) (map[string]Commitment, error)
}

Client to fetch commitments.

func NewCommitmentsClient

func NewCommitmentsClient() CommitmentsClient

type Config

type Config struct {

	// RequeueIntervalActive is the interval for requeueing active reservations for verification.
	RequeueIntervalActive time.Duration `json:"committedResourceRequeueIntervalActive"`
	// RequeueIntervalRetry is the interval for requeueing when retrying after knowledge is not ready.
	RequeueIntervalRetry time.Duration `json:"committedResourceRequeueIntervalRetry"`
	// PipelineDefault is the default pipeline used for scheduling committed resource reservations.
	PipelineDefault string `json:"committedResourcePipelineDefault"`

	// SchedulerURL is the endpoint of the nova external scheduler
	SchedulerURL string `json:"schedulerURL"`

	// Secret ref to SSO credentials stored in a k8s secret, if applicable.
	SSOSecretRef *corev1.SecretReference `json:"ssoSecretRef"`

	// Secret ref to keystone credentials stored in a k8s secret.
	KeystoneSecretRef corev1.SecretReference `json:"keystoneSecretRef"`

	// Secret ref to the database credentials for querying VM state.
	DatabaseSecretRef *corev1.SecretReference `json:"databaseSecretRef,omitempty"`

	// FlavorGroupPipelines maps flavor group names to pipeline names.
	// Example: {"2152": "kvm-hana-bin-packing", "2101": "kvm-general-purpose-load-balancing", "*": "kvm-general-purpose-load-balancing"}
	// Used to select different scheduling pipelines based on flavor group characteristics.
	FlavorGroupPipelines map[string]string `json:"committedResourceFlavorGroupPipelines,omitempty"`

	// ChangeAPIWatchReservationsTimeout defines how long to wait for reservations to become ready before timing out and rolling back.
	ChangeAPIWatchReservationsTimeout time.Duration `json:"committedResourceChangeAPIWatchReservationsTimeout"`

	// ChangeAPIWatchReservationsPollInterval defines how frequently to poll reservation status during watch.
	ChangeAPIWatchReservationsPollInterval time.Duration `json:"committedResourceChangeAPIWatchReservationsPollInterval"`

	// EnableChangeCommitmentsAPI controls whether the change-commitments API endpoint is active.
	// When false, the endpoint will return HTTP 503 Service Unavailable.
	// The info endpoint remains available for health checks.
	EnableChangeCommitmentsAPI bool `json:"committedResourceEnableChangeCommitmentsAPI"`

	// EnableReportUsageAPI controls whether the report-usage API endpoint is active.
	// When false, the endpoint will return HTTP 503 Service Unavailable.
	// This can be used as an emergency switch if the usage reporting is causing issues.
	EnableReportUsageAPI bool `json:"committedResourceEnableReportUsageAPI"`

	// EnableReportCapacityAPI controls whether the report-capacity API endpoint is active.
	// When false, the endpoint will return HTTP 503 Service Unavailable.
	// This can be used as an emergency switch if the capacity reporting is causing issues.
	EnableReportCapacityAPI bool `json:"committedResourceEnableReportCapacityAPI"`
}

func DefaultConfig

func DefaultConfig() Config

func (*Config) ApplyDefaults

func (c *Config) ApplyDefaults()

ApplyDefaults fills in any unset values with defaults.

type E2EChecksConfig

type E2EChecksConfig struct {
	// Base URL for the commitments API. If empty, defaults to defaultCommitmentsAPIURL.
	BaseURL string `json:"baseURL"`
}

E2EChecksConfig holds the configuration for CR e2e checks.

type Flavor

type Flavor struct {
	ID          string  `json:"id"`
	Disk        int     `json:"disk"` // in GB.
	RAM         int     `json:"ram"`  // in MB.
	Name        string  `json:"name"`
	RxTxFactor  float64 `json:"rxtx_factor"`
	VCPUs       int     `json:"vcpus"`
	IsPublic    bool    `json:"os-flavor-access:is_public"`
	Ephemeral   int     `json:"OS-FLV-EXT-DATA:ephemeral"`
	Description string  `json:"description"`

	// JSON string of extra specifications used when scheduling the flavor.
	ExtraSpecs map[string]string `json:"extra_specs" db:"extra_specs"`
}

OpenStack flavor model as returned by the Nova API under /flavors/detail. See: https://docs.openstack.org/api-ref/compute/#list-flavors

type HTTPAPI

type HTTPAPI struct {
	// contains filtered or unexported fields
}

HTTPAPI implements Limes LIQUID commitment validation endpoints.

func NewAPI

func NewAPI(client client.Client) *HTTPAPI

func NewAPIWithConfig

func NewAPIWithConfig(client client.Client, config Config, novaClient UsageNovaClient) *HTTPAPI

func (*HTTPAPI) HandleChangeCommitments

func (api *HTTPAPI) HandleChangeCommitments(w http.ResponseWriter, r *http.Request)

implements POST /commitments/v1/change-commitments from Limes LIQUID API: See: https://github.com/sapcc/go-api-declarations/blob/main/liquid/commitment.go See: https://pkg.go.dev/github.com/sapcc/go-api-declarations/liquid

This endpoint handles commitment changes by creating/updating/deleting Reservation CRDs based on the commitment lifecycle. A request may contain multiple commitment changes which are processed in a single transaction. If any change fails, all changes are rolled back.

func (*HTTPAPI) HandleQuota

func (api *HTTPAPI) HandleQuota(w http.ResponseWriter, r *http.Request)

HandleQuota implements PUT /commitments/v1/projects/:project_id/quota from Limes LIQUID API. See: https://pkg.go.dev/github.com/sapcc/go-api-declarations/liquid

This is a no-op endpoint that accepts quota requests but doesn't store them. Cortex does not enforce quotas for committed resources - quota enforcement happens through commitment validation at change-commitments time. The endpoint exists for API compatibility with the LIQUID specification.

func (*HTTPAPI) HandleReportCapacity

func (api *HTTPAPI) HandleReportCapacity(w http.ResponseWriter, r *http.Request)

handles POST /commitments/v1/report-capacity requests from Limes: See: https://github.com/sapcc/go-api-declarations/blob/main/liquid/commitment.go See: https://pkg.go.dev/github.com/sapcc/go-api-declarations/liquid Reports available capacity across all flavor group resources. Note, unit is specified in the Info API response with multiple of the smallest memory resource unit within a flavor group.

func (*HTTPAPI) HandleReportUsage

func (api *HTTPAPI) HandleReportUsage(w http.ResponseWriter, r *http.Request)

HandleReportUsage implements POST /commitments/v1/projects/:project_id/report-usage from Limes LIQUID API. See: https://github.com/sapcc/go-api-declarations/blob/main/liquid/report_usage.go See: https://pkg.go.dev/github.com/sapcc/go-api-declarations/liquid

This endpoint reports usage information for a specific project's committed resources, including per-AZ usage, physical usage, and detailed VM subresources.

func (*HTTPAPI) Init

func (api *HTTPAPI) Init(mux *http.ServeMux, registry prometheus.Registerer, log logr.Logger)

type InfoAPIMonitor

type InfoAPIMonitor struct {
	// contains filtered or unexported fields
}

InfoAPIMonitor provides metrics for the CR info API.

func NewInfoAPIMonitor

func NewInfoAPIMonitor() InfoAPIMonitor

NewInfoAPIMonitor creates a new monitor with Prometheus metrics. Metrics are pre-initialized with zero values for common HTTP status codes to ensure they appear in Prometheus before the first request.

func (*InfoAPIMonitor) Collect

func (m *InfoAPIMonitor) Collect(ch chan<- prometheus.Metric)

Collect implements prometheus.Collector.

func (*InfoAPIMonitor) Describe

func (m *InfoAPIMonitor) Describe(ch chan<- *prometheus.Desc)

Describe implements prometheus.Collector.

type Project

type Project struct {
	// DomainID is the domain ID the project belongs to.
	DomainID string `json:"domain_id"`
	// ID is the unique ID of the project.
	ID string `json:"id"`
	// Name is the name of the project.
	Name string `json:"name"`
	// ParentID is the parent_id of the project.
	ParentID string `json:"parent_id"`
}

OpenStack project model as returned by the Keystone API under /projects. See: https://docs.openstack.org/api-ref/identity/v3/#projects

type ReportCapacityAPIMonitor

type ReportCapacityAPIMonitor struct {
	// contains filtered or unexported fields
}

ReportCapacityAPIMonitor provides metrics for the CR report-capacity API.

func NewReportCapacityAPIMonitor

func NewReportCapacityAPIMonitor() ReportCapacityAPIMonitor

NewReportCapacityAPIMonitor creates a new monitor with Prometheus metrics. Metrics are pre-initialized with zero values for common HTTP status codes to ensure they appear in Prometheus before the first request.

func (*ReportCapacityAPIMonitor) Collect

func (m *ReportCapacityAPIMonitor) Collect(ch chan<- prometheus.Metric)

Collect implements prometheus.Collector.

func (*ReportCapacityAPIMonitor) Describe

func (m *ReportCapacityAPIMonitor) Describe(ch chan<- *prometheus.Desc)

Describe implements prometheus.Collector.

type ReportUsageAPIMonitor

type ReportUsageAPIMonitor struct {
	// contains filtered or unexported fields
}

ReportUsageAPIMonitor provides metrics for the CR report-usage API.

func NewReportUsageAPIMonitor

func NewReportUsageAPIMonitor() ReportUsageAPIMonitor

NewReportUsageAPIMonitor creates a new monitor with Prometheus metrics. Metrics are pre-initialized with zero values for common HTTP status codes to ensure they appear in Prometheus before the first request.

func (*ReportUsageAPIMonitor) Collect

func (m *ReportUsageAPIMonitor) Collect(ch chan<- prometheus.Metric)

Collect implements prometheus.Collector.

func (*ReportUsageAPIMonitor) Describe

func (m *ReportUsageAPIMonitor) Describe(ch chan<- *prometheus.Desc)

Describe implements prometheus.Collector.

type ReservationManager

type ReservationManager struct {
	client.Client
}

ReservationManager handles CRUD operations for Reservation CRDs.

func NewReservationManager

func NewReservationManager(k8sClient client.Client) *ReservationManager

func (*ReservationManager) ApplyCommitmentState

func (m *ReservationManager) ApplyCommitmentState(
	ctx context.Context,
	log logr.Logger,
	desiredState *CommitmentState,
	flavorGroups map[string]compute.FlavorGroupFeature,
	creator string,
) (*ApplyResult, error)

ApplyCommitmentState synchronizes Reservation CRDs to match the desired commitment state. This function performs CRUD operations (create/update/delete) on reservation slots to align with the capacity specified in desiredState.

Entry points:

  • from Syncer - periodic sync with Limes state
  • from API ChangeCommitmentsHandler - batch processing of commitment changes

The function is idempotent and handles:

  • Repairing inconsistent slots (wrong flavor group/project)
  • Creating new reservation slots when capacity increases
  • Deleting unused/excess slots when capacity decreases
  • Syncing reservation metadata for all remaining slots

Returns ApplyResult containing touched/removed reservations and counts for metrics.

type Server

type Server struct {
	ID                             string  `json:"id" db:"id,primarykey"`
	Name                           string  `json:"name" db:"name"`
	Status                         string  `json:"status" db:"status"`
	TenantID                       string  `json:"tenant_id" db:"tenant_id"`
	UserID                         string  `json:"user_id" db:"user_id"`
	HostID                         string  `json:"hostId" db:"host_id"`
	Created                        string  `json:"created" db:"created"`
	Updated                        string  `json:"updated" db:"updated"`
	AccessIPv4                     string  `json:"accessIPv4" db:"access_ipv4"`
	AccessIPv6                     string  `json:"accessIPv6" db:"access_ipv6"`
	OSDCFdiskConfig                string  `json:"OS-DCF:diskConfig" db:"os_dcf_disk_config"`
	Progress                       int     `json:"progress" db:"progress"`
	OSEXTAvailabilityZone          string  `json:"OS-EXT-AZ:availability_zone" db:"os_ext_az_availability_zone"`
	ConfigDrive                    string  `json:"config_drive" db:"config_drive"`
	KeyName                        string  `json:"key_name" db:"key_name"`
	OSSRVUSGLaunchedAt             string  `json:"OS-SRV-USG:launched_at" db:"os_srv_usg_launched_at"`
	OSSRVUSGTerminatedAt           *string `json:"OS-SRV-USG:terminated_at" db:"os_srv_usg_terminated_at"`
	OSEXTSRVATTRHost               string  `json:"OS-EXT-SRV-ATTR:host" db:"os_ext_srv_attr_host"`
	OSEXTSRVATTRInstanceName       string  `json:"OS-EXT-SRV-ATTR:instance_name" db:"os_ext_srv_attr_instance_name"`
	OSEXTSRVATTRHypervisorHostname string  `json:"OS-EXT-SRV-ATTR:hypervisor_hostname" db:"os_ext_srv_attr_hypervisor_hostname"`
	OSEXTSTSTaskState              *string `json:"OS-EXT-STS:task_state" db:"os_ext_sts_task_state"`
	OSEXTSTSVmState                string  `json:"OS-EXT-STS:vm_state" db:"os_ext_sts_vm_state"`
	OSEXTSTSPowerState             int     `json:"OS-EXT-STS:power_state" db:"os_ext_sts_power_state"`

	// From nested JSON
	FlavorName string `json:"-" db:"flavor_name"`
}

OpenStack server model as returned by the Nova API under /servers/detail. See: https://docs.openstack.org/api-ref/compute/#list-servers-detailed

func (*Server) MarshalJSON

func (s *Server) MarshalJSON() ([]byte, error)

Custom marshaler for OpenStackServer to handle nested JSON.

func (*Server) UnmarshalJSON

func (s *Server) UnmarshalJSON(data []byte) error

Custom unmarshaler for OpenStackServer to handle nested JSON.

type Syncer

type Syncer struct {
	// Client to fetch commitments from Limes
	CommitmentsClient
	// Kubernetes client for CRD operations
	client.Client
	// contains filtered or unexported fields
}

func NewSyncer

func NewSyncer(k8sClient client.Client, monitor *SyncerMonitor) *Syncer

func (*Syncer) Init

func (s *Syncer) Init(ctx context.Context, config SyncerConfig) error

func (*Syncer) SyncReservations

func (s *Syncer) SyncReservations(ctx context.Context) error

SyncReservations fetches commitments from Limes and synchronizes Reservation CRDs.

type SyncerConfig

type SyncerConfig struct {
	// Secret ref to keystone credentials stored in a k8s secret.
	KeystoneSecretRef corev1.SecretReference `json:"keystoneSecretRef"`
	// Secret ref to SSO credentials stored in a k8s secret, if applicable.
	SSOSecretRef *corev1.SecretReference `json:"ssoSecretRef"`
	// SyncInterval defines how often the syncer reconciles Limes commitments to Reservation CRDs.
	SyncInterval time.Duration `json:"committedResourceSyncInterval"`
}

func DefaultSyncerConfig

func DefaultSyncerConfig() SyncerConfig

func (*SyncerConfig) ApplyDefaults

func (c *SyncerConfig) ApplyDefaults()

ApplyDefaults fills in any unset values with defaults.

type SyncerMonitor

type SyncerMonitor struct {
	// contains filtered or unexported fields
}

SyncerMonitor provides metrics for the commitment syncer.

func NewSyncerMonitor

func NewSyncerMonitor() *SyncerMonitor

NewSyncerMonitor creates a new monitor with Prometheus metrics.

func (*SyncerMonitor) Collect

func (m *SyncerMonitor) Collect(ch chan<- prometheus.Metric)

Collect implements prometheus.Collector.

func (*SyncerMonitor) Describe

func (m *SyncerMonitor) Describe(ch chan<- *prometheus.Desc)

Describe implements prometheus.Collector.

func (*SyncerMonitor) RecordCommitmentProcessed

func (m *SyncerMonitor) RecordCommitmentProcessed()

RecordCommitmentProcessed records a commitment successfully processed.

func (*SyncerMonitor) RecordCommitmentSeen

func (m *SyncerMonitor) RecordCommitmentSeen()

RecordCommitmentSeen records a commitment seen from Limes.

func (*SyncerMonitor) RecordCommitmentSkipped

func (m *SyncerMonitor) RecordCommitmentSkipped(reason string)

RecordCommitmentSkipped records a commitment skipped with a reason.

func (*SyncerMonitor) RecordReservationsCreated

func (m *SyncerMonitor) RecordReservationsCreated(count int)

RecordReservationsCreated records reservations created.

func (*SyncerMonitor) RecordReservationsDeleted

func (m *SyncerMonitor) RecordReservationsDeleted(count int)

RecordReservationsDeleted records reservations deleted.

func (*SyncerMonitor) RecordReservationsRepaired

func (m *SyncerMonitor) RecordReservationsRepaired(count int)

RecordReservationsRepaired records reservations repaired.

func (*SyncerMonitor) RecordSyncError

func (m *SyncerMonitor) RecordSyncError()

RecordSyncError records a syncer error.

func (*SyncerMonitor) RecordSyncRun

func (m *SyncerMonitor) RecordSyncRun()

RecordSyncRun records a syncer run.

func (*SyncerMonitor) RecordUnitMismatch

func (m *SyncerMonitor) RecordUnitMismatch(_ string)

RecordUnitMismatch records a unit mismatch skip (convenience method).

type UsageCalculator

type UsageCalculator struct {
	// contains filtered or unexported fields
}

UsageCalculator computes usage reports for Limes LIQUID API.

func NewUsageCalculator

func NewUsageCalculator(client client.Client, novaClient UsageNovaClient) *UsageCalculator

NewUsageCalculator creates a new UsageCalculator instance.

func (*UsageCalculator) CalculateUsage

func (c *UsageCalculator) CalculateUsage(
	ctx context.Context,
	log logr.Logger,
	projectID string,
	allAZs []liquid.AvailabilityZone,
) (liquid.ServiceUsageReport, error)

CalculateUsage computes the usage report for a specific project.

type UsageNovaClient

type UsageNovaClient interface {
	ListProjectServers(ctx context.Context, projectID string) ([]nova.ServerDetail, error)
}

UsageNovaClient is a minimal interface for the Nova client needed by the usage API. This allows for easy mocking in tests without implementing the full NovaClient interface.

type VMUsageInfo

type VMUsageInfo struct {
	UUID          string
	Name          string
	FlavorName    string
	FlavorGroup   string
	Status        string
	MemoryMB      uint64
	VCPUs         uint64
	DiskGB        uint64
	AZ            string
	Hypervisor    string
	CreatedAt     time.Time
	UsageMultiple uint64            // Memory in multiples of smallest flavor in the group
	Metadata      map[string]string // Server metadata from Nova
	Tags          []string          // Server tags from Nova
	OSType        string            // OS type from OSTypeProber (for billing)
}

VMUsageInfo contains VM information needed for usage calculation. This is a local view of the VM enriched with flavor group information.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL