Skip to content

Commit

Permalink
Add Quota Management Support (Part 1) (#55)
Browse files Browse the repository at this point in the history
Without this, you'll not get very far with Openstack's defaults!  This
adds in an endpoint that can read and update quotas.  These are
explciitly scoped to the identity (as that maps to an OpenStack project
where quotas reside), and implicitly to the client e.g.
unikorn-kubernetes/unikorn-baremetal, so they can independently affect
quotas in a shared identity without having to know about one another.

This first part adds in the necessary APIs that allow quotas to be
created by a client, trigger an identity reconcile and are implicitly
deleted on identity deletion.
  • Loading branch information
spjmurray committed Sep 3, 2024
1 parent f0675b6 commit 61180cc
Show file tree
Hide file tree
Showing 14 changed files with 1,137 additions and 100 deletions.
4 changes: 2 additions & 2 deletions charts/region/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ description: A Helm chart for deploying Unikorn's Region Controller

type: application

version: v0.1.37
appVersion: v0.1.37
version: v0.1.38
appVersion: v0.1.38

icon: https://raw.githubusercontent.com/unikorn-cloud/assets/main/images/logos/dark-on-light/icon.png

Expand Down
85 changes: 85 additions & 0 deletions charts/region/crds/region.unikorn-cloud.org_quotas.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.1
name: quotas.region.unikorn-cloud.org
spec:
group: region.unikorn-cloud.org
names:
categories:
- unikorn
kind: Quota
listKind: QuotaList
plural: quotas
singular: quota
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: age
type: date
name: v1alpha1
schema:
openAPIV3Schema:
description: |-
Quota defines resource limits for identities.
We don't want to be concerned with Hertz and bytes, instead we want to
expose higher level primitives like flavors and how many they are. This
removes a lot of the burden from clients. Where we have to be careful is
with overheads, e.g. a machine implicitly defines CPUs, memory and storage,
but this will also need networks, NICs and other supporting resources.
Quotas are scoped to identities, and also to a specific client, as this avoids
having to worry about IPC and split brain concerns.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
properties:
flavors:
description: Flavors is a list of flavors and their count.
items:
properties:
count:
description: |-
Count is the number of instances that are required.
For certain services that can do rolling upgrades, be aware that this
may need a little overhead to cater for that. For example the Kubernetes
service will do a one-in-one-out upgrade of the control plane.
type: integer
id:
description: ID is the flavor ID.
type: string
required:
- count
- id
type: object
type: array
x-kubernetes-list-map-keys:
- id
x-kubernetes-list-type: map
type: object
status:
type: object
required:
- spec
type: object
served: true
storage: true
subresources: {}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ rules:
- apiGroups:
- region.unikorn-cloud.org
resources:
- quotas
- physicalnetworks
verbs:
- list
Expand Down
3 changes: 3 additions & 0 deletions charts/region/templates/region-controller/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ rules:
resources:
- identities
- physicalnetworks
- quotas
verbs:
- list
- watch
- create
- delete
- patch
- update
- apiGroups:
- region.unikorn-cloud.org
resources:
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/unikorn/v1alpha1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ var (
func init() {
SchemeBuilder.Register(&Region{}, &RegionList{})
SchemeBuilder.Register(&Identity{}, &IdentityList{})
SchemeBuilder.Register(&Quota{}, &QuotaList{})
SchemeBuilder.Register(&PhysicalNetwork{}, &PhysicalNetworkList{})
SchemeBuilder.Register(&OpenstackIdentity{}, &OpenstackIdentityList{})
SchemeBuilder.Register(&OpenstackPhysicalNetwork{}, &OpenstackPhysicalNetworkList{})
Expand Down
47 changes: 47 additions & 0 deletions pkg/apis/unikorn/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,50 @@ type VLANAllocationEntry struct {

type VLANAllocationStatus struct {
}

// QuotaList is a typed list of quotas.
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type QuotaList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Quota `json:"items"`
}

// Quota defines resource limits for identities.
// We don't want to be concerned with Hertz and bytes, instead we want to
// expose higher level primitives like flavors and how many they are. This
// removes a lot of the burden from clients. Where we have to be careful is
// with overheads, e.g. a machine implicitly defines CPUs, memory and storage,
// but this will also need networks, NICs and other supporting resources.
// Quotas are scoped to identities, and also to a specific client, as this avoids
// having to worry about IPC and split brain concerns.
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:scope=Namespaced,categories=unikorn
// +kubebuilder:printcolumn:name="age",type="date",JSONPath=".metadata.creationTimestamp"
type Quota struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec QuotaSpec `json:"spec"`
Status QuotaStatus `json:"status,omitempty"`
}

type QuotaSpec struct {
// Flavors is a list of flavors and their count.
// +listType=map
// +listMapKey=id
Flavors []FlavorQuota `json:"flavors,omitempty"`
}

type FlavorQuota struct {
// ID is the flavor ID.
ID string `json:"id"`
// Count is the number of instances that are required.
// For certain services that can do rolling upgrades, be aware that this
// may need a little overhead to cater for that. For example the Kubernetes
// service will do a one-in-one-out upgrade of the control plane.
Count int `json:"count"`
}

type QuotaStatus struct {
}
114 changes: 114 additions & 0 deletions pkg/apis/unikorn/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 61180cc

Please sign in to comment.