Added CPU size selector & add tenant cleanup (#1326)
This commit is contained in:
165
models/allocatable_resources_response.go
Normal file
165
models/allocatable_resources_response.go
Normal file
@@ -0,0 +1,165 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// AllocatableResourcesResponse allocatable resources response
|
||||
//
|
||||
// swagger:model allocatableResourcesResponse
|
||||
type AllocatableResourcesResponse struct {
|
||||
|
||||
// cpu priority
|
||||
CPUPriority *NodeMaxAllocatableResources `json:"cpu_priority,omitempty"`
|
||||
|
||||
// mem priority
|
||||
MemPriority *NodeMaxAllocatableResources `json:"mem_priority,omitempty"`
|
||||
|
||||
// min allocatable cpu
|
||||
MinAllocatableCPU int64 `json:"min_allocatable_cpu,omitempty"`
|
||||
|
||||
// min allocatable mem
|
||||
MinAllocatableMem int64 `json:"min_allocatable_mem,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this allocatable resources response
|
||||
func (m *AllocatableResourcesResponse) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateCPUPriority(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateMemPriority(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AllocatableResourcesResponse) validateCPUPriority(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.CPUPriority) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.CPUPriority != nil {
|
||||
if err := m.CPUPriority.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("cpu_priority")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AllocatableResourcesResponse) validateMemPriority(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.MemPriority) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.MemPriority != nil {
|
||||
if err := m.MemPriority.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("mem_priority")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this allocatable resources response based on the context it is used
|
||||
func (m *AllocatableResourcesResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.contextValidateCPUPriority(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateMemPriority(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AllocatableResourcesResponse) contextValidateCPUPriority(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if m.CPUPriority != nil {
|
||||
if err := m.CPUPriority.ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("cpu_priority")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AllocatableResourcesResponse) contextValidateMemPriority(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if m.MemPriority != nil {
|
||||
if err := m.MemPriority.ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("mem_priority")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *AllocatableResourcesResponse) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *AllocatableResourcesResponse) UnmarshalBinary(b []byte) error {
|
||||
var res AllocatableResourcesResponse
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
70
models/node_max_allocatable_resources.go
Normal file
70
models/node_max_allocatable_resources.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// NodeMaxAllocatableResources node max allocatable resources
|
||||
//
|
||||
// swagger:model nodeMaxAllocatableResources
|
||||
type NodeMaxAllocatableResources struct {
|
||||
|
||||
// max allocatable cpu
|
||||
MaxAllocatableCPU int64 `json:"max_allocatable_cpu,omitempty"`
|
||||
|
||||
// max allocatable mem
|
||||
MaxAllocatableMem int64 `json:"max_allocatable_mem,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this node max allocatable resources
|
||||
func (m *NodeMaxAllocatableResources) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this node max allocatable resources based on context it is used
|
||||
func (m *NodeMaxAllocatableResources) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *NodeMaxAllocatableResources) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *NodeMaxAllocatableResources) UnmarshalBinary(b []byte) error {
|
||||
var res NodeMaxAllocatableResources
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -52,6 +52,39 @@ func init() {
|
||||
},
|
||||
"basePath": "/api/v1",
|
||||
"paths": {
|
||||
"/cluster/allocatable-resources": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"OperatorAPI"
|
||||
],
|
||||
"summary": "Get allocatable cpu and memory for given number of nodes",
|
||||
"operationId": "GetAllocatableResources",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"name": "num_nodes",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/allocatableResourcesResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cluster/max-allocatable-memory": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -1382,6 +1415,25 @@ func init() {
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"allocatableResourcesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu_priority": {
|
||||
"$ref": "#/definitions/nodeMaxAllocatableResources"
|
||||
},
|
||||
"mem_priority": {
|
||||
"$ref": "#/definitions/nodeMaxAllocatableResources"
|
||||
},
|
||||
"min_allocatable_cpu": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"min_allocatable_mem": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"awsConfiguration": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -2229,6 +2281,19 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeMaxAllocatableResources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"max_allocatable_cpu": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"max_allocatable_mem": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeSelectorTerm": {
|
||||
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.",
|
||||
"type": "object",
|
||||
@@ -3187,6 +3252,39 @@ func init() {
|
||||
},
|
||||
"basePath": "/api/v1",
|
||||
"paths": {
|
||||
"/cluster/allocatable-resources": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"OperatorAPI"
|
||||
],
|
||||
"summary": "Get allocatable cpu and memory for given number of nodes",
|
||||
"operationId": "GetAllocatableResources",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"name": "num_nodes",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/allocatableResourcesResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cluster/max-allocatable-memory": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -5242,6 +5340,25 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"allocatableResourcesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu_priority": {
|
||||
"$ref": "#/definitions/nodeMaxAllocatableResources"
|
||||
},
|
||||
"mem_priority": {
|
||||
"$ref": "#/definitions/nodeMaxAllocatableResources"
|
||||
},
|
||||
"min_allocatable_cpu": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"min_allocatable_mem": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"awsConfiguration": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -6077,6 +6194,19 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeMaxAllocatableResources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"max_allocatable_cpu": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"max_allocatable_mem": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeSelectorTerm": {
|
||||
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.",
|
||||
"type": "object",
|
||||
|
||||
@@ -78,6 +78,9 @@ func NewOperatorAPI(spec *loads.Document) *OperatorAPI {
|
||||
OperatorAPIDirectCSIFormatDriveHandler: operator_api.DirectCSIFormatDriveHandlerFunc(func(params operator_api.DirectCSIFormatDriveParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation operator_api.DirectCSIFormatDrive has not yet been implemented")
|
||||
}),
|
||||
OperatorAPIGetAllocatableResourcesHandler: operator_api.GetAllocatableResourcesHandlerFunc(func(params operator_api.GetAllocatableResourcesParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation operator_api.GetAllocatableResources has not yet been implemented")
|
||||
}),
|
||||
OperatorAPIGetDirectCSIDriveListHandler: operator_api.GetDirectCSIDriveListHandlerFunc(func(params operator_api.GetDirectCSIDriveListParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation operator_api.GetDirectCSIDriveList has not yet been implemented")
|
||||
}),
|
||||
@@ -236,6 +239,8 @@ type OperatorAPI struct {
|
||||
OperatorAPIDeleteTenantHandler operator_api.DeleteTenantHandler
|
||||
// OperatorAPIDirectCSIFormatDriveHandler sets the operation handler for the direct c s i format drive operation
|
||||
OperatorAPIDirectCSIFormatDriveHandler operator_api.DirectCSIFormatDriveHandler
|
||||
// OperatorAPIGetAllocatableResourcesHandler sets the operation handler for the get allocatable resources operation
|
||||
OperatorAPIGetAllocatableResourcesHandler operator_api.GetAllocatableResourcesHandler
|
||||
// OperatorAPIGetDirectCSIDriveListHandler sets the operation handler for the get direct c s i drive list operation
|
||||
OperatorAPIGetDirectCSIDriveListHandler operator_api.GetDirectCSIDriveListHandler
|
||||
// OperatorAPIGetDirectCSIVolumeListHandler sets the operation handler for the get direct c s i volume list operation
|
||||
@@ -398,6 +403,9 @@ func (o *OperatorAPI) Validate() error {
|
||||
if o.OperatorAPIDirectCSIFormatDriveHandler == nil {
|
||||
unregistered = append(unregistered, "operator_api.DirectCSIFormatDriveHandler")
|
||||
}
|
||||
if o.OperatorAPIGetAllocatableResourcesHandler == nil {
|
||||
unregistered = append(unregistered, "operator_api.GetAllocatableResourcesHandler")
|
||||
}
|
||||
if o.OperatorAPIGetDirectCSIDriveListHandler == nil {
|
||||
unregistered = append(unregistered, "operator_api.GetDirectCSIDriveListHandler")
|
||||
}
|
||||
@@ -618,6 +626,10 @@ func (o *OperatorAPI) initHandlerCache() {
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/cluster/allocatable-resources"] = operator_api.NewGetAllocatableResources(o.context, o.OperatorAPIGetAllocatableResourcesHandler)
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/direct-csi/drives"] = operator_api.NewGetDirectCSIDriveList(o.context, o.OperatorAPIGetDirectCSIDriveListHandler)
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package operator_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// GetAllocatableResourcesHandlerFunc turns a function with the right signature into a get allocatable resources handler
|
||||
type GetAllocatableResourcesHandlerFunc func(GetAllocatableResourcesParams, *models.Principal) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn GetAllocatableResourcesHandlerFunc) Handle(params GetAllocatableResourcesParams, principal *models.Principal) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// GetAllocatableResourcesHandler interface for that can handle valid get allocatable resources params
|
||||
type GetAllocatableResourcesHandler interface {
|
||||
Handle(GetAllocatableResourcesParams, *models.Principal) middleware.Responder
|
||||
}
|
||||
|
||||
// NewGetAllocatableResources creates a new http.Handler for the get allocatable resources operation
|
||||
func NewGetAllocatableResources(ctx *middleware.Context, handler GetAllocatableResourcesHandler) *GetAllocatableResources {
|
||||
return &GetAllocatableResources{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/* GetAllocatableResources swagger:route GET /cluster/allocatable-resources OperatorAPI getAllocatableResources
|
||||
|
||||
Get allocatable cpu and memory for given number of nodes
|
||||
|
||||
*/
|
||||
type GetAllocatableResources struct {
|
||||
Context *middleware.Context
|
||||
Handler GetAllocatableResourcesHandler
|
||||
}
|
||||
|
||||
func (o *GetAllocatableResources) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
*r = *rCtx
|
||||
}
|
||||
var Params = NewGetAllocatableResourcesParams()
|
||||
uprinc, aCtx, err := o.Context.Authorize(r, route)
|
||||
if err != nil {
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
if aCtx != nil {
|
||||
*r = *aCtx
|
||||
}
|
||||
var principal *models.Principal
|
||||
if uprinc != nil {
|
||||
principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
|
||||
}
|
||||
|
||||
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
res := o.Handler.Handle(Params, principal) // actually handle the request
|
||||
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package operator_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// NewGetAllocatableResourcesParams creates a new GetAllocatableResourcesParams object
|
||||
//
|
||||
// There are no default values defined in the spec.
|
||||
func NewGetAllocatableResourcesParams() GetAllocatableResourcesParams {
|
||||
|
||||
return GetAllocatableResourcesParams{}
|
||||
}
|
||||
|
||||
// GetAllocatableResourcesParams contains all the bound params for the get allocatable resources operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters GetAllocatableResources
|
||||
type GetAllocatableResourcesParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
Minimum: 1
|
||||
In: query
|
||||
*/
|
||||
NumNodes int32
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
// for simple values it will use straight method calls.
|
||||
//
|
||||
// To ensure default values, the struct must have been initialized with NewGetAllocatableResourcesParams() beforehand.
|
||||
func (o *GetAllocatableResourcesParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
qs := runtime.Values(r.URL.Query())
|
||||
|
||||
qNumNodes, qhkNumNodes, _ := qs.GetOK("num_nodes")
|
||||
if err := o.bindNumNodes(qNumNodes, qhkNumNodes, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindNumNodes binds and validates parameter NumNodes from query.
|
||||
func (o *GetAllocatableResourcesParams) bindNumNodes(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||
if !hasKey {
|
||||
return errors.Required("num_nodes", "query", rawData)
|
||||
}
|
||||
var raw string
|
||||
if len(rawData) > 0 {
|
||||
raw = rawData[len(rawData)-1]
|
||||
}
|
||||
|
||||
// Required: true
|
||||
// AllowEmptyValue: false
|
||||
|
||||
if err := validate.RequiredString("num_nodes", "query", raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value, err := swag.ConvertInt32(raw)
|
||||
if err != nil {
|
||||
return errors.InvalidType("num_nodes", "query", "int32", raw)
|
||||
}
|
||||
o.NumNodes = value
|
||||
|
||||
if err := o.validateNumNodes(formats); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateNumNodes carries on validations for parameter NumNodes
|
||||
func (o *GetAllocatableResourcesParams) validateNumNodes(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.MinimumInt("num_nodes", "query", int64(o.NumNodes), 1, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package operator_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// GetAllocatableResourcesOKCode is the HTTP code returned for type GetAllocatableResourcesOK
|
||||
const GetAllocatableResourcesOKCode int = 200
|
||||
|
||||
/*GetAllocatableResourcesOK A successful response.
|
||||
|
||||
swagger:response getAllocatableResourcesOK
|
||||
*/
|
||||
type GetAllocatableResourcesOK struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.AllocatableResourcesResponse `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetAllocatableResourcesOK creates GetAllocatableResourcesOK with default headers values
|
||||
func NewGetAllocatableResourcesOK() *GetAllocatableResourcesOK {
|
||||
|
||||
return &GetAllocatableResourcesOK{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get allocatable resources o k response
|
||||
func (o *GetAllocatableResourcesOK) WithPayload(payload *models.AllocatableResourcesResponse) *GetAllocatableResourcesOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get allocatable resources o k response
|
||||
func (o *GetAllocatableResourcesOK) SetPayload(payload *models.AllocatableResourcesResponse) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *GetAllocatableResourcesOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(200)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*GetAllocatableResourcesDefault Generic error response.
|
||||
|
||||
swagger:response getAllocatableResourcesDefault
|
||||
*/
|
||||
type GetAllocatableResourcesDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetAllocatableResourcesDefault creates GetAllocatableResourcesDefault with default headers values
|
||||
func NewGetAllocatableResourcesDefault(code int) *GetAllocatableResourcesDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &GetAllocatableResourcesDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the get allocatable resources default response
|
||||
func (o *GetAllocatableResourcesDefault) WithStatusCode(code int) *GetAllocatableResourcesDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the get allocatable resources default response
|
||||
func (o *GetAllocatableResourcesDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get allocatable resources default response
|
||||
func (o *GetAllocatableResourcesDefault) WithPayload(payload *models.Error) *GetAllocatableResourcesDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get allocatable resources default response
|
||||
func (o *GetAllocatableResourcesDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *GetAllocatableResourcesDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(o._statusCode)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package operator_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
golangswaggerpaths "path"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// GetAllocatableResourcesURL generates an URL for the get allocatable resources operation
|
||||
type GetAllocatableResourcesURL struct {
|
||||
NumNodes int32
|
||||
|
||||
_basePath string
|
||||
// avoid unkeyed usage
|
||||
_ struct{}
|
||||
}
|
||||
|
||||
// WithBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *GetAllocatableResourcesURL) WithBasePath(bp string) *GetAllocatableResourcesURL {
|
||||
o.SetBasePath(bp)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *GetAllocatableResourcesURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *GetAllocatableResourcesURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/cluster/allocatable-resources"
|
||||
|
||||
_basePath := o._basePath
|
||||
if _basePath == "" {
|
||||
_basePath = "/api/v1"
|
||||
}
|
||||
_result.Path = golangswaggerpaths.Join(_basePath, _path)
|
||||
|
||||
qs := make(url.Values)
|
||||
|
||||
numNodesQ := swag.FormatInt32(o.NumNodes)
|
||||
if numNodesQ != "" {
|
||||
qs.Set("num_nodes", numNodesQ)
|
||||
}
|
||||
|
||||
_result.RawQuery = qs.Encode()
|
||||
|
||||
return &_result, nil
|
||||
}
|
||||
|
||||
// Must is a helper function to panic when the url builder returns an error
|
||||
func (o *GetAllocatableResourcesURL) Must(u *url.URL, err error) *url.URL {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if u == nil {
|
||||
panic("url can't be nil")
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// String returns the string representation of the path with query string
|
||||
func (o *GetAllocatableResourcesURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *GetAllocatableResourcesURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on GetAllocatableResourcesURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on GetAllocatableResourcesURL")
|
||||
}
|
||||
|
||||
base, err := o.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.Scheme = scheme
|
||||
base.Host = host
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// StringFull returns the string representation of a complete url
|
||||
func (o *GetAllocatableResourcesURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package operatorapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sort"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
@@ -50,6 +51,20 @@ func registerNodesHandlers(api *operations.OperatorAPI) {
|
||||
}
|
||||
return operator_api.NewListNodeLabelsOK().WithPayload(*resp)
|
||||
})
|
||||
|
||||
api.OperatorAPIGetAllocatableResourcesHandler = operator_api.GetAllocatableResourcesHandlerFunc(func(params operator_api.GetAllocatableResourcesParams, principal *models.Principal) middleware.Responder {
|
||||
resp, err := getAllocatableResourcesResponse(params.NumNodes, principal)
|
||||
if err != nil {
|
||||
return operator_api.NewGetAllocatableResourcesDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewGetAllocatableResourcesOK().WithPayload(resp)
|
||||
})
|
||||
}
|
||||
|
||||
type NodeResourceInfo struct {
|
||||
Name string
|
||||
AllocatableMemory int64
|
||||
AllocatableCPU int64
|
||||
}
|
||||
|
||||
// getMaxAllocatableMemory get max allocatable memory given a desired number of nodes
|
||||
@@ -211,3 +226,147 @@ func getNodeLabelsResponse(ctx context.Context, session *models.Principal) (*mod
|
||||
}
|
||||
return clusterResources, nil
|
||||
}
|
||||
|
||||
func getClusterResourcesInfo(numNodes int32, inNodesResources []NodeResourceInfo) *models.AllocatableResourcesResponse {
|
||||
|
||||
// purge any nodes with 0 cpu
|
||||
var nodesResources []NodeResourceInfo
|
||||
for _, n := range inNodesResources {
|
||||
if n.AllocatableCPU > 0 {
|
||||
nodesResources = append(nodesResources, n)
|
||||
}
|
||||
}
|
||||
|
||||
if int32(len(nodesResources)) < numNodes || numNodes == 0 {
|
||||
return &models.AllocatableResourcesResponse{
|
||||
CPUPriority: &models.NodeMaxAllocatableResources{
|
||||
MaxAllocatableCPU: 0,
|
||||
MaxAllocatableMem: 0,
|
||||
},
|
||||
MemPriority: &models.NodeMaxAllocatableResources{
|
||||
MaxAllocatableCPU: 0,
|
||||
MaxAllocatableMem: 0,
|
||||
},
|
||||
MinAllocatableCPU: 0,
|
||||
MinAllocatableMem: 0,
|
||||
}
|
||||
}
|
||||
|
||||
allocatableResources := &models.AllocatableResourcesResponse{}
|
||||
|
||||
// sort nodesResources giving CPU priority
|
||||
sort.Slice(nodesResources, func(i, j int) bool { return nodesResources[i].AllocatableCPU < nodesResources[j].AllocatableCPU })
|
||||
maxCPUNodesNeeded := len(nodesResources) - int(numNodes)
|
||||
maxMemNodesNeeded := maxCPUNodesNeeded
|
||||
|
||||
maxAllocatableCPU := nodesResources[maxCPUNodesNeeded].AllocatableCPU
|
||||
minAllocatableCPU := nodesResources[maxCPUNodesNeeded].AllocatableCPU
|
||||
minAllocatableMem := nodesResources[maxMemNodesNeeded].AllocatableMemory
|
||||
|
||||
availableMemsForMaxCPU := []int64{}
|
||||
for _, info := range nodesResources {
|
||||
if info.AllocatableCPU >= maxAllocatableCPU {
|
||||
availableMemsForMaxCPU = append(availableMemsForMaxCPU, info.AllocatableMemory)
|
||||
}
|
||||
// min allocatable resources overall
|
||||
minAllocatableCPU = min(minAllocatableCPU, info.AllocatableCPU)
|
||||
minAllocatableMem = min(minAllocatableMem, info.AllocatableMemory)
|
||||
}
|
||||
|
||||
sort.Slice(availableMemsForMaxCPU, func(i, j int) bool { return availableMemsForMaxCPU[i] < availableMemsForMaxCPU[j] })
|
||||
maxAllocatableMem := availableMemsForMaxCPU[len(availableMemsForMaxCPU)-int(numNodes)]
|
||||
|
||||
allocatableResources.MinAllocatableCPU = minAllocatableCPU
|
||||
allocatableResources.MinAllocatableMem = minAllocatableMem
|
||||
allocatableResources.CPUPriority = &models.NodeMaxAllocatableResources{
|
||||
MaxAllocatableCPU: maxAllocatableCPU,
|
||||
MaxAllocatableMem: maxAllocatableMem,
|
||||
}
|
||||
|
||||
// sort nodesResources giving Mem priority
|
||||
sort.Slice(nodesResources, func(i, j int) bool { return nodesResources[i].AllocatableMemory < nodesResources[j].AllocatableMemory })
|
||||
maxMemNodesNeeded = len(nodesResources) - int(numNodes)
|
||||
maxAllocatableMem = nodesResources[maxMemNodesNeeded].AllocatableMemory
|
||||
|
||||
availableCPUsForMaxMem := []int64{}
|
||||
for _, info := range nodesResources {
|
||||
if info.AllocatableMemory >= maxAllocatableMem {
|
||||
availableCPUsForMaxMem = append(availableCPUsForMaxMem, info.AllocatableCPU)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(availableCPUsForMaxMem, func(i, j int) bool { return availableCPUsForMaxMem[i] < availableCPUsForMaxMem[j] })
|
||||
maxAllocatableCPU = availableCPUsForMaxMem[len(availableCPUsForMaxMem)-int(numNodes)]
|
||||
|
||||
allocatableResources.MemPriority = &models.NodeMaxAllocatableResources{
|
||||
MaxAllocatableCPU: maxAllocatableCPU,
|
||||
MaxAllocatableMem: maxAllocatableMem,
|
||||
}
|
||||
|
||||
return allocatableResources
|
||||
}
|
||||
|
||||
// getAllocatableResources get max allocatable memory given a desired number of nodes
|
||||
func getAllocatableResources(ctx context.Context, clientset v1.CoreV1Interface, numNodes int32) (*models.AllocatableResourcesResponse, error) {
|
||||
if numNodes == 0 {
|
||||
return nil, errors.New("error NumNodes must be greated than 0")
|
||||
}
|
||||
|
||||
// get all nodes from cluster
|
||||
nodes, err := clientset.Nodes().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodesInfo := []NodeResourceInfo{}
|
||||
OUTER:
|
||||
for _, n := range nodes.Items {
|
||||
// Don't consider node if it has a NoSchedule or NoExecute Taint
|
||||
for _, t := range n.Spec.Taints {
|
||||
switch t.Effect {
|
||||
case corev1.TaintEffectNoSchedule:
|
||||
continue OUTER
|
||||
case corev1.TaintEffectNoExecute:
|
||||
continue OUTER
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var nodeMemory int64
|
||||
var nodeCPU int64
|
||||
if quantity, ok := n.Status.Allocatable[corev1.ResourceMemory]; ok {
|
||||
// availableMemSizes = append(availableMemSizes, quantity.Value())
|
||||
nodeMemory = quantity.Value()
|
||||
}
|
||||
// we assume all nodes have allocatable cpu resource
|
||||
if quantity, ok := n.Status.Allocatable[corev1.ResourceCPU]; ok {
|
||||
// availableCPU = append(availableCPU, quantity.Value())
|
||||
nodeCPU = quantity.Value()
|
||||
}
|
||||
nodeInfo := NodeResourceInfo{
|
||||
Name: n.Name,
|
||||
AllocatableCPU: nodeCPU,
|
||||
AllocatableMemory: nodeMemory,
|
||||
}
|
||||
nodesInfo = append(nodesInfo, nodeInfo)
|
||||
}
|
||||
res := getClusterResourcesInfo(numNodes, nodesInfo)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Get allocatable resources response
|
||||
|
||||
func getAllocatableResourcesResponse(numNodes int32, session *models.Principal) (*models.AllocatableResourcesResponse, *models.Error) {
|
||||
ctx := context.Background()
|
||||
client, err := cluster.K8sClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
clusterResources, err := getAllocatableResources(ctx, client.CoreV1(), numNodes)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return clusterResources, nil
|
||||
}
|
||||
|
||||
@@ -153,10 +153,12 @@ export interface IResourceModel {
|
||||
|
||||
export interface IResourceRequests {
|
||||
memory: number;
|
||||
cpu: number;
|
||||
}
|
||||
|
||||
export interface IResourceLimits {
|
||||
memory: number;
|
||||
cpu: number;
|
||||
}
|
||||
|
||||
export interface ITLSTenantConfiguration {
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import storage from "local-storage-fallback";
|
||||
import get from "lodash/get";
|
||||
import { ICapacity, IErasureCodeCalc, IStorageFactors } from "./types";
|
||||
import { IPool } from "../screens/Console/Tenants/ListTenants/types";
|
||||
import { AllocableResourcesResponse } from "../screens/Console/Tenants/types";
|
||||
|
||||
const minStReq = 1073741824; // Minimal Space required for MinIO
|
||||
const minMemReq = 2147483648; // Minimal Memory required for MinIO in bytes
|
||||
@@ -594,3 +596,113 @@ export const decodeFileName = (text: string) => {
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
||||
export const setResourcesValidation = (
|
||||
memorySize: number,
|
||||
cpusSelected: number,
|
||||
maxAllocatableResources: AllocableResourcesResponse
|
||||
) => {
|
||||
const requestedSizeBytes = getBytes(memorySize.toString(10), "GB");
|
||||
const memReqSize = parseInt(requestedSizeBytes, 10);
|
||||
|
||||
const minimalRequiredMemory = 2147483648; // Minimal required memory, 2Gi
|
||||
|
||||
const memoryExists = get(
|
||||
maxAllocatableResources,
|
||||
"min_allocatable_mem",
|
||||
false
|
||||
);
|
||||
|
||||
const cpuExists = get(maxAllocatableResources, "min_allocatable_cpu", false);
|
||||
|
||||
if (memoryExists === false) {
|
||||
return {
|
||||
error:
|
||||
"No available memory for the selected number of nodes. Please try another combination.",
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (cpuExists === false) {
|
||||
return {
|
||||
error:
|
||||
"No available CPUs for the selected number of nodes. Please try another combination",
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (memReqSize < minimalRequiredMemory) {
|
||||
return {
|
||||
error: "Memory size is set bellow minimum required",
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (cpusSelected < 1) {
|
||||
return {
|
||||
error: "CPU amount is set bellow minimum available",
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
memReqSize <= maxAllocatableResources.mem_priority.max_allocatable_mem &&
|
||||
cpusSelected > maxAllocatableResources.mem_priority.max_allocatable_cpu
|
||||
) {
|
||||
return {
|
||||
error:
|
||||
"It is not possible to allocate this amount of memory in all the CPUs",
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
cpusSelected <= maxAllocatableResources.cpu_priority.max_allocatable_cpu &&
|
||||
memReqSize > maxAllocatableResources.cpu_priority.max_allocatable_mem
|
||||
) {
|
||||
return {
|
||||
error:
|
||||
"It is not possible to allocate this amount of CPUs with the available memory",
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
cpusSelected > maxAllocatableResources.cpu_priority.max_allocatable_cpu ||
|
||||
memReqSize > maxAllocatableResources.mem_priority.max_allocatable_mem
|
||||
) {
|
||||
return {
|
||||
error: "CPUs or Memory selected is beyond bounds",
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
error: "",
|
||||
memoryRequest: memReqSize,
|
||||
memoryLimit: maxAllocatableResources.mem_priority.max_allocatable_mem,
|
||||
cpuRequest: cpusSelected,
|
||||
cpuLimit: maxAllocatableResources.cpu_priority.max_allocatable_cpu,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -58,6 +58,7 @@ interface InputBoxProps {
|
||||
overlayObject?: any;
|
||||
extraInputProps?: StandardInputProps["inputProps"];
|
||||
noLabelMinWidth?: boolean;
|
||||
pattern?: string;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
@@ -121,6 +122,7 @@ const InputBoxWrapper = ({
|
||||
extraInputProps = {},
|
||||
overlayAction,
|
||||
noLabelMinWidth = false,
|
||||
pattern="",
|
||||
classes,
|
||||
}: InputBoxProps) => {
|
||||
let inputProps: any = { "data-index": index, ...extraInputProps };
|
||||
@@ -133,6 +135,10 @@ const InputBoxWrapper = ({
|
||||
inputProps["max"] = max;
|
||||
}
|
||||
|
||||
if(pattern !== "") {
|
||||
inputProps["pattern"] = pattern;
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Grid
|
||||
|
||||
@@ -174,7 +174,7 @@ const AddTenant = ({
|
||||
const enableTLS = fields.security.enableTLS;
|
||||
const ecParity = fields.tenantSize.ecParity;
|
||||
const distribution = fields.tenantSize.distribution;
|
||||
const memorySize = fields.tenantSize.memorySize;
|
||||
const resourcesSize = fields.tenantSize.resourcesSize;
|
||||
const tenantCustom = fields.configure.tenantCustom;
|
||||
const logSearchCustom = fields.configure.logSearchCustom;
|
||||
const prometheusCustom = fields.configure.prometheusCustom;
|
||||
@@ -255,10 +255,12 @@ const AddTenant = ({
|
||||
},
|
||||
resources: {
|
||||
requests: {
|
||||
memory: memorySize.request,
|
||||
memory: resourcesSize.memoryRequest,
|
||||
cpu: resourcesSize.cpuRequest,
|
||||
},
|
||||
limits: {
|
||||
memory: memorySize.limit,
|
||||
memory: resourcesSize.memoryRequest,
|
||||
cpu: resourcesSize.cpuRequest,
|
||||
},
|
||||
},
|
||||
securityContext: tenantCustom ? tenantSecurityContext : null,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import React, { Fragment } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
@@ -29,22 +29,11 @@ import Table from "@mui/material/Table";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import TableCell from "@mui/material/TableCell";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import {
|
||||
calculateDistribution,
|
||||
erasureCodeCalc,
|
||||
getBytes,
|
||||
niceBytes,
|
||||
setMemoryResource,
|
||||
} from "../../../../../common/utils";
|
||||
import { ecListTransform, Opts } from "../../ListTenants/utils";
|
||||
import { IMemorySize } from "../../ListTenants/types";
|
||||
import {
|
||||
ErrorResponseHandler,
|
||||
ICapacity,
|
||||
IErasureCodeCalc,
|
||||
} from "../../../../../common/types";
|
||||
import { commonFormValidation } from "../../../../../utils/validationFunctions";
|
||||
import api from "../../../../../common/api";
|
||||
import { niceBytes } from "../../../../../common/utils";
|
||||
import { Opts } from "../../ListTenants/utils";
|
||||
import { IResourcesSize } from "../../ListTenants/types";
|
||||
import { IErasureCodeCalc } from "../../../../../common/types";
|
||||
|
||||
import { Divider } from "@mui/material";
|
||||
|
||||
interface ISizePreviewProps {
|
||||
@@ -61,11 +50,12 @@ interface ISizePreviewProps {
|
||||
ecParityChoices: Opts[];
|
||||
cleanECChoices: string[];
|
||||
maxAllocableMemo: number;
|
||||
memorySize: IMemorySize;
|
||||
resourcesSize: IResourcesSize;
|
||||
distribution: any;
|
||||
ecParityCalc: IErasureCodeCalc;
|
||||
limitSize: any;
|
||||
selectedStorageClass: string;
|
||||
cpuToUse: string;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
@@ -96,201 +86,17 @@ const SizePreview = ({
|
||||
ecParityChoices,
|
||||
cleanECChoices,
|
||||
maxAllocableMemo,
|
||||
memorySize,
|
||||
resourcesSize,
|
||||
distribution,
|
||||
ecParityCalc,
|
||||
limitSize,
|
||||
selectedStorageClass,
|
||||
cpuToUse,
|
||||
}: ISizePreviewProps) => {
|
||||
const [errorFlag, setErrorFlag] = useState<boolean>(false);
|
||||
const [nodeError, setNodeError] = useState<string>("");
|
||||
const usableInformation = ecParityCalc.storageFactors.find(
|
||||
(element) => element.erasureCode === ecParity
|
||||
);
|
||||
|
||||
// Common
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
updateAddField("tenantSize", field, value);
|
||||
},
|
||||
[updateAddField]
|
||||
);
|
||||
|
||||
/*Debounce functions*/
|
||||
|
||||
// Storage Quotas
|
||||
|
||||
const validateMemorySize = useCallback(() => {
|
||||
const memSize = parseInt(memoryNode) || 0;
|
||||
const clusterSize = volumeSize || 0;
|
||||
const maxMemSize = maxAllocableMemo || 0;
|
||||
const clusterSizeFactor = sizeFactor;
|
||||
|
||||
const clusterSizeBytes = getBytes(
|
||||
clusterSize.toString(10),
|
||||
clusterSizeFactor
|
||||
);
|
||||
const memoSize = setMemoryResource(memSize, clusterSizeBytes, maxMemSize);
|
||||
updateField("memorySize", memoSize);
|
||||
}, [maxAllocableMemo, memoryNode, sizeFactor, updateField, volumeSize]);
|
||||
|
||||
const getMaxAllocableMemory = (nodes: string) => {
|
||||
if (nodes !== "" && !isNaN(parseInt(nodes))) {
|
||||
setNodeError("");
|
||||
api
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/cluster/max-allocatable-memory?num_nodes=${nodes}`
|
||||
)
|
||||
.then((res: { max_memory: number }) => {
|
||||
const maxMemory = res.max_memory ? res.max_memory : 0;
|
||||
updateField("maxAllocableMemo", maxMemory);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setErrorFlag(true);
|
||||
setNodeError(err.errorMessage);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
validateMemorySize();
|
||||
}, [memoryNode, validateMemorySize]);
|
||||
|
||||
useEffect(() => {
|
||||
validateMemorySize();
|
||||
}, [maxAllocableMemo, validateMemorySize]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ecParityChoices.length > 0 && distribution.error === "") {
|
||||
const ecCodeValidated = erasureCodeCalc(
|
||||
cleanECChoices,
|
||||
distribution.persistentVolumes,
|
||||
distribution.pvSize,
|
||||
distribution.nodes
|
||||
);
|
||||
|
||||
updateField("ecParityCalc", ecCodeValidated);
|
||||
updateField("ecParity", ecCodeValidated.defaultEC);
|
||||
}
|
||||
}, [ecParityChoices.length, distribution, cleanECChoices, updateField]);
|
||||
/*End debounce functions*/
|
||||
|
||||
/*Calculate Allocation*/
|
||||
useEffect(() => {
|
||||
validateClusterSize();
|
||||
getECValue();
|
||||
getMaxAllocableMemory(nodes);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [nodes, volumeSize, sizeFactor, drivesPerServer]);
|
||||
|
||||
const validateClusterSize = () => {
|
||||
const size = volumeSize;
|
||||
const factor = sizeFactor;
|
||||
const limitSize = getBytes("12", "Ti", true);
|
||||
|
||||
const clusterCapacity: ICapacity = {
|
||||
unit: factor,
|
||||
value: size.toString(),
|
||||
};
|
||||
|
||||
const distrCalculate = calculateDistribution(
|
||||
clusterCapacity,
|
||||
parseInt(nodes),
|
||||
parseInt(limitSize),
|
||||
parseInt(drivesPerServer)
|
||||
);
|
||||
|
||||
updateField("distribution", distrCalculate);
|
||||
};
|
||||
|
||||
const getECValue = () => {
|
||||
updateField("ecParity", "");
|
||||
|
||||
if (nodes.trim() !== "" && drivesPerServer.trim() !== "") {
|
||||
api
|
||||
.invoke("GET", `/api/v1/get-parity/${nodes}/${drivesPerServer}`)
|
||||
.then((ecList: string[]) => {
|
||||
updateField("ecParityChoices", ecListTransform(ecList));
|
||||
updateField("cleanECChoices", ecList);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
updateField("ecparityChoices", []);
|
||||
isPageValid("tenantSize", false);
|
||||
updateField("ecParity", "");
|
||||
});
|
||||
}
|
||||
};
|
||||
/*Calculate Allocation End*/
|
||||
|
||||
/* Validations of pages */
|
||||
|
||||
useEffect(() => {
|
||||
const parsedSize = getBytes(volumeSize, sizeFactor, true);
|
||||
const commonValidation = commonFormValidation([
|
||||
{
|
||||
fieldKey: "nodes",
|
||||
required: true,
|
||||
value: nodes,
|
||||
customValidation: errorFlag,
|
||||
customValidationMessage: nodeError,
|
||||
},
|
||||
{
|
||||
fieldKey: "volume_size",
|
||||
required: true,
|
||||
value: volumeSize,
|
||||
customValidation:
|
||||
parseInt(parsedSize) < 1073741824 ||
|
||||
parseInt(parsedSize) > limitSize[selectedStorageClass],
|
||||
customValidationMessage: `Volume size must be greater than 1Gi and less than ${niceBytes(
|
||||
limitSize[selectedStorageClass],
|
||||
true
|
||||
)}`,
|
||||
},
|
||||
{
|
||||
fieldKey: "memory_per_node",
|
||||
required: true,
|
||||
value: memoryNode,
|
||||
customValidation: parseInt(memoryNode) < 2,
|
||||
customValidationMessage: "Memory size must be greater than 2Gi",
|
||||
},
|
||||
{
|
||||
fieldKey: "drivesps",
|
||||
required: true,
|
||||
value: drivesPerServer,
|
||||
customValidation: parseInt(drivesPerServer) < 1,
|
||||
customValidationMessage: "There must be at least one drive",
|
||||
},
|
||||
]);
|
||||
|
||||
isPageValid(
|
||||
"tenantSize",
|
||||
!("nodes" in commonValidation) &&
|
||||
!("volume_size" in commonValidation) &&
|
||||
!("memory_per_node" in commonValidation) &&
|
||||
!("drivesps" in commonValidation) &&
|
||||
distribution.error === "" &&
|
||||
ecParityCalc.error === 0 &&
|
||||
memorySize.error === ""
|
||||
);
|
||||
}, [
|
||||
nodes,
|
||||
volumeSize,
|
||||
sizeFactor,
|
||||
memoryNode,
|
||||
distribution,
|
||||
drivesPerServer,
|
||||
ecParityCalc,
|
||||
memorySize,
|
||||
limitSize,
|
||||
selectedStorageClass,
|
||||
isPageValid,
|
||||
errorFlag,
|
||||
nodeError,
|
||||
]);
|
||||
|
||||
/* End Validation of pages */
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<h4>Resource Allocation</h4>
|
||||
@@ -327,6 +133,10 @@ const SizePreview = ({
|
||||
<TableCell align="right">{memoryNode} Gi</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
<TableRow>
|
||||
<TableCell scope="row">CPU Selection</TableCell>
|
||||
<TableCell align="right">{cpuToUse}</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
{ecParityCalc.error === 0 && usableInformation && (
|
||||
@@ -390,12 +200,13 @@ const mapState = (state: AppState) => ({
|
||||
cleanECChoices: state.tenants.createTenant.fields.tenantSize.cleanECChoices,
|
||||
maxAllocableMemo:
|
||||
state.tenants.createTenant.fields.tenantSize.maxAllocableMemo,
|
||||
memorySize: state.tenants.createTenant.fields.tenantSize.memorySize,
|
||||
resourcesSize: state.tenants.createTenant.fields.tenantSize.resourcesSize,
|
||||
distribution: state.tenants.createTenant.fields.tenantSize.distribution,
|
||||
ecParityCalc: state.tenants.createTenant.fields.tenantSize.ecParityCalc,
|
||||
limitSize: state.tenants.createTenant.fields.tenantSize.limitSize,
|
||||
selectedStorageClass:
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageClass,
|
||||
cpuToUse: state.tenants.createTenant.fields.tenantSize.cpuToUse,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, {
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
import React, { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import { SelectChangeEvent } from "@mui/material";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import get from "lodash/get";
|
||||
import { AppState } from "../../../../../store";
|
||||
import { isPageValid, updateAddField } from "../../actions";
|
||||
import {
|
||||
@@ -33,21 +35,17 @@ import {
|
||||
getBytes,
|
||||
k8sfactorForDropdown,
|
||||
niceBytes,
|
||||
setMemoryResource,
|
||||
setResourcesValidation,
|
||||
} from "../../../../../common/utils";
|
||||
import { clearValidationError } from "../../utils";
|
||||
import { ecListTransform, Opts } from "../../ListTenants/utils";
|
||||
import { IMemorySize } from "../../ListTenants/types";
|
||||
import {
|
||||
ErrorResponseHandler,
|
||||
ICapacity,
|
||||
IErasureCodeCalc,
|
||||
} from "../../../../../common/types";
|
||||
import { IResourcesSize } from "../../ListTenants/types";
|
||||
import { AllocableResourcesResponse } from "../../types";
|
||||
import { ICapacity, IErasureCodeCalc } from "../../../../../common/types";
|
||||
import { commonFormValidation } from "../../../../../utils/validationFunctions";
|
||||
import api from "../../../../../common/api";
|
||||
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import SelectWrapper from "../../../Common/FormComponents/SelectWrapper/SelectWrapper";
|
||||
import { SelectChangeEvent } from "@mui/material";
|
||||
|
||||
interface ITenantSizeProps {
|
||||
classes: any;
|
||||
@@ -63,11 +61,15 @@ interface ITenantSizeProps {
|
||||
ecParityChoices: Opts[];
|
||||
cleanECChoices: string[];
|
||||
maxAllocableMemo: number;
|
||||
memorySize: IMemorySize;
|
||||
resourcesSize: IResourcesSize;
|
||||
distribution: any;
|
||||
ecParityCalc: IErasureCodeCalc;
|
||||
limitSize: any;
|
||||
selectedStorageClass: string;
|
||||
cpuToUse: string;
|
||||
maxAllocatableResources: AllocableResourcesResponse;
|
||||
maxCPUsUse: string;
|
||||
maxMemorySize: string;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
@@ -106,11 +108,15 @@ const TenantSize = ({
|
||||
ecParityChoices,
|
||||
cleanECChoices,
|
||||
maxAllocableMemo,
|
||||
memorySize,
|
||||
resourcesSize,
|
||||
distribution,
|
||||
ecParityCalc,
|
||||
limitSize,
|
||||
cpuToUse,
|
||||
selectedStorageClass,
|
||||
maxAllocatableResources,
|
||||
maxCPUsUse,
|
||||
maxMemorySize,
|
||||
}: ITenantSizeProps) => {
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
const [errorFlag, setErrorFlag] = useState<boolean>(false);
|
||||
@@ -132,46 +138,22 @@ const TenantSize = ({
|
||||
|
||||
// Storage Quotas
|
||||
|
||||
const validateMemorySize = useCallback(() => {
|
||||
const memSize = parseInt(memoryNode) || 0;
|
||||
const clusterSize = volumeSize || 0;
|
||||
const maxMemSize = maxAllocableMemo || 0;
|
||||
const clusterSizeFactor = sizeFactor;
|
||||
const validateResourcesSize = useCallback(() => {
|
||||
const memSize = memoryNode || "0";
|
||||
const cpusSelected = cpuToUse;
|
||||
|
||||
const clusterSizeBytes = getBytes(
|
||||
clusterSize.toString(10),
|
||||
clusterSizeFactor
|
||||
const resourcesSize = setResourcesValidation(
|
||||
parseInt(memSize),
|
||||
parseInt(cpusSelected),
|
||||
maxAllocatableResources
|
||||
);
|
||||
const memoSize = setMemoryResource(memSize, clusterSizeBytes, maxMemSize);
|
||||
updateField("memorySize", memoSize);
|
||||
}, [maxAllocableMemo, memoryNode, sizeFactor, updateField, volumeSize]);
|
||||
|
||||
const getMaxAllocableMemory = (nodes: string) => {
|
||||
if (nodes !== "" && !isNaN(parseInt(nodes))) {
|
||||
setNodeError("");
|
||||
api
|
||||
.invoke(
|
||||
"GET",
|
||||
`/api/v1/cluster/max-allocatable-memory?num_nodes=${nodes}`
|
||||
)
|
||||
.then((res: { max_memory: number }) => {
|
||||
const maxMemory = res.max_memory ? res.max_memory : 0;
|
||||
updateField("maxAllocableMemo", maxMemory);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setErrorFlag(true);
|
||||
setNodeError(err.errorMessage);
|
||||
});
|
||||
}
|
||||
};
|
||||
updateField("resourcesSize", resourcesSize);
|
||||
}, [memoryNode, cpuToUse, maxAllocatableResources, updateField]);
|
||||
|
||||
useEffect(() => {
|
||||
validateMemorySize();
|
||||
}, [memoryNode, validateMemorySize]);
|
||||
|
||||
useEffect(() => {
|
||||
validateMemorySize();
|
||||
}, [maxAllocableMemo, validateMemorySize]);
|
||||
validateResourcesSize();
|
||||
}, [memoryNode, cpuToUse, validateResourcesSize]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ecParityChoices.length > 0 && distribution.error === "") {
|
||||
@@ -190,13 +172,7 @@ const TenantSize = ({
|
||||
|
||||
/*Calculate Allocation*/
|
||||
useEffect(() => {
|
||||
validateClusterSize();
|
||||
getECValue();
|
||||
getMaxAllocableMemory(nodes);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [nodes, volumeSize, sizeFactor, drivesPerServer]);
|
||||
|
||||
const validateClusterSize = () => {
|
||||
//Validate Cluster Size
|
||||
const size = volumeSize;
|
||||
const factor = sizeFactor;
|
||||
const limitSize = getBytes("12", "Ti", true);
|
||||
@@ -214,31 +190,84 @@ const TenantSize = ({
|
||||
);
|
||||
|
||||
updateField("distribution", distrCalculate);
|
||||
};
|
||||
setErrorFlag(false);
|
||||
setNodeError("");
|
||||
|
||||
const getECValue = () => {
|
||||
updateField("ecParity", "");
|
||||
// Get allocatable Resources
|
||||
api
|
||||
.invoke("GET", `api/v1/cluster/allocatable-resources?num_nodes=${nodes}`)
|
||||
.then((res: AllocableResourcesResponse) => {
|
||||
updateField("maxAllocatableResources", res);
|
||||
|
||||
const maxAllocatableResources = res;
|
||||
|
||||
const memoryExists = get(
|
||||
maxAllocatableResources,
|
||||
"min_allocatable_mem",
|
||||
false
|
||||
);
|
||||
|
||||
const cpuExists = get(
|
||||
maxAllocatableResources,
|
||||
"min_allocatable_cpu",
|
||||
false
|
||||
);
|
||||
|
||||
if (memoryExists === false || cpuExists === false) {
|
||||
updateField("cpuToUse", 0);
|
||||
|
||||
updateField("maxMemorySize", "0");
|
||||
updateField("maxCPUsUse", "0");
|
||||
|
||||
validateResourcesSize();
|
||||
return;
|
||||
}
|
||||
|
||||
// We default to Best CPU Configuration
|
||||
updateField(
|
||||
"maxMemorySize",
|
||||
res.mem_priority.max_allocatable_mem.toString()
|
||||
);
|
||||
updateField(
|
||||
"maxCPUsUse",
|
||||
res.cpu_priority.max_allocatable_cpu.toString()
|
||||
);
|
||||
|
||||
updateField("maxAllocableMemo", res.mem_priority.max_allocatable_mem);
|
||||
|
||||
const cpuInt = parseInt(cpuToUse);
|
||||
const maxAlocatableCPU = get(
|
||||
maxAllocatableResources,
|
||||
"cpu_priority.max_allocatable_cpu",
|
||||
0
|
||||
);
|
||||
|
||||
if (cpuInt === 0 && cpuInt !== maxAlocatableCPU) {
|
||||
updateField("cpuToUse", maxAlocatableCPU);
|
||||
} else if (cpuInt > maxAlocatableCPU) {
|
||||
updateField("cpuToUse", maxAlocatableCPU);
|
||||
}
|
||||
|
||||
// We reset error states
|
||||
validateResourcesSize();
|
||||
})
|
||||
.catch((err: any) => {
|
||||
updateField("maxAllocableMemo", 0);
|
||||
updateField("cpuToUse", "0");
|
||||
setErrorFlag(true);
|
||||
setNodeError(err.errorMessage);
|
||||
console.error(err);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [nodes, volumeSize, sizeFactor, updateField]);
|
||||
|
||||
if (nodes.trim() !== "" && drivesPerServer.trim() !== "") {
|
||||
api
|
||||
.invoke("GET", `/api/v1/get-parity/${nodes}/${drivesPerServer}`)
|
||||
.then((ecList: string[]) => {
|
||||
updateField("ecParityChoices", ecListTransform(ecList));
|
||||
updateField("cleanECChoices", ecList);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
updateField("ecparityChoices", []);
|
||||
isPageValid("tenantSize", false);
|
||||
updateField("ecParity", "");
|
||||
});
|
||||
}
|
||||
};
|
||||
/*Calculate Allocation End*/
|
||||
|
||||
/* Validations of pages */
|
||||
|
||||
useEffect(() => {
|
||||
const parsedSize = getBytes(volumeSize, sizeFactor, true);
|
||||
|
||||
const commonValidation = commonFormValidation([
|
||||
{
|
||||
fieldKey: "nodes",
|
||||
@@ -283,7 +312,10 @@ const TenantSize = ({
|
||||
!("drivesps" in commonValidation) &&
|
||||
distribution.error === "" &&
|
||||
ecParityCalc.error === 0 &&
|
||||
memorySize.error === ""
|
||||
resourcesSize.error === "" &&
|
||||
parseInt(cpuToUse) <= parseInt(maxCPUsUse) &&
|
||||
parseInt(cpuToUse) > 0 &&
|
||||
ecParity !== ""
|
||||
);
|
||||
|
||||
setValidationErrors(commonValidation);
|
||||
@@ -293,16 +325,40 @@ const TenantSize = ({
|
||||
sizeFactor,
|
||||
memoryNode,
|
||||
distribution,
|
||||
drivesPerServer,
|
||||
ecParityCalc,
|
||||
memorySize,
|
||||
resourcesSize,
|
||||
limitSize,
|
||||
selectedStorageClass,
|
||||
cpuToUse,
|
||||
maxCPUsUse,
|
||||
isPageValid,
|
||||
errorFlag,
|
||||
nodeError,
|
||||
drivesPerServer,
|
||||
ecParity,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (distribution.error === "") {
|
||||
// Get EC Value
|
||||
updateField("ecParity", "");
|
||||
|
||||
if (nodes.trim() !== "" && distribution.disks !== 0) {
|
||||
api
|
||||
.invoke("GET", `api/v1/get-parity/${nodes}/${distribution.disks}`)
|
||||
.then((ecList: string[]) => {
|
||||
updateField("ecParityChoices", ecListTransform(ecList));
|
||||
updateField("cleanECChoices", ecList);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
updateField("ecparityChoices", []);
|
||||
isPageValid("tenantSize", false);
|
||||
updateField("ecParity", "");
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [distribution, isPageValid, updateField, nodes]);
|
||||
|
||||
/* End Validation of pages */
|
||||
|
||||
return (
|
||||
@@ -320,19 +376,20 @@ const TenantSize = ({
|
||||
<div className={classes.error}>{distribution.error}</div>
|
||||
</Grid>
|
||||
)}
|
||||
{memorySize.error !== "" && (
|
||||
{resourcesSize.error !== "" && (
|
||||
<Grid item xs={12}>
|
||||
<div className={classes.error}>{memorySize.error}</div>
|
||||
<div className={classes.error}>{resourcesSize.error}</div>
|
||||
</Grid>
|
||||
)}
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="nodes"
|
||||
name="nodes"
|
||||
type="number"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("nodes", e.target.value);
|
||||
cleanValidation("nodes");
|
||||
if (e.target.validity.valid) {
|
||||
updateField("nodes", e.target.value);
|
||||
cleanValidation("nodes");
|
||||
}
|
||||
}}
|
||||
label="Number of Servers"
|
||||
disabled={selectedStorageClass === ""}
|
||||
@@ -340,16 +397,18 @@ const TenantSize = ({
|
||||
min="4"
|
||||
required
|
||||
error={validationErrors["nodes"] || ""}
|
||||
pattern={"[0-9]*"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="drivesps"
|
||||
name="drivesps"
|
||||
type="number"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("drivesPerServer", e.target.value);
|
||||
cleanValidation("drivesps");
|
||||
if (e.target.validity.valid) {
|
||||
updateField("drivesPerServer", e.target.value);
|
||||
cleanValidation("drivesps");
|
||||
}
|
||||
}}
|
||||
label="Number of Drives per Server"
|
||||
value={drivesPerServer}
|
||||
@@ -357,6 +416,7 @@ const TenantSize = ({
|
||||
min="1"
|
||||
required
|
||||
error={validationErrors["drivesps"] || ""}
|
||||
pattern={"[0-9]*"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
@@ -396,42 +456,66 @@ const TenantSize = ({
|
||||
</div>
|
||||
</Grid>
|
||||
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
id="memory_per_node"
|
||||
name="memory_per_node"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("memoryNode", e.target.value);
|
||||
cleanValidation("memory_per_node");
|
||||
}}
|
||||
label="Memory per Node [Gi]"
|
||||
value={memoryNode}
|
||||
disabled={selectedStorageClass === ""}
|
||||
required
|
||||
error={validationErrors["memory_per_node"] || ""}
|
||||
min="2"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<SelectWrapper
|
||||
id="ec_parity"
|
||||
name="ec_parity"
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
updateField("ecParity", e.target.value as string);
|
||||
}}
|
||||
label="Erasure Code Parity"
|
||||
disabled={selectedStorageClass === ""}
|
||||
value={ecParity}
|
||||
options={ecParityChoices}
|
||||
/>
|
||||
<span className={classes.descriptionText}>
|
||||
Please select the desired parity. This setting will change the max
|
||||
usable capacity in the cluster
|
||||
</span>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
label={"CPU Selection"}
|
||||
id={"cpuToUse"}
|
||||
name={"cpuToUse"}
|
||||
onChange={(e) => {
|
||||
if (e.target.validity.valid) {
|
||||
updateField("cpuToUse", e.target.value);
|
||||
}
|
||||
}}
|
||||
value={cpuToUse}
|
||||
disabled={selectedStorageClass === ""}
|
||||
min="1"
|
||||
max={maxCPUsUse}
|
||||
error={
|
||||
parseInt(cpuToUse) > parseInt(maxCPUsUse) ||
|
||||
parseInt(cpuToUse) <= 0 ||
|
||||
isNaN(parseInt(cpuToUse))
|
||||
? "Invalid CPU Configuration"
|
||||
: ""
|
||||
}
|
||||
pattern={"[0-9]*"}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
id="memory_per_node"
|
||||
name="memory_per_node"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("memoryNode", e.target.value);
|
||||
cleanValidation("memory_per_node");
|
||||
}}
|
||||
label="Memory per Node [Gi]"
|
||||
value={memoryNode}
|
||||
disabled={selectedStorageClass === ""}
|
||||
required
|
||||
error={validationErrors["memory_per_node"] || ""}
|
||||
min="2"
|
||||
max={maxMemorySize}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<SelectWrapper
|
||||
id="ec_parity"
|
||||
name="ec_parity"
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
updateField("ecParity", e.target.value as string);
|
||||
}}
|
||||
label="Erasure Code Parity"
|
||||
disabled={selectedStorageClass === ""}
|
||||
value={ecParity}
|
||||
options={ecParityChoices}
|
||||
/>
|
||||
<span className={classes.descriptionText}>
|
||||
Please select the desired parity. This setting will change the max
|
||||
usable capacity in the cluster
|
||||
</span>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
@@ -448,12 +532,17 @@ const mapState = (state: AppState) => ({
|
||||
cleanECChoices: state.tenants.createTenant.fields.tenantSize.cleanECChoices,
|
||||
maxAllocableMemo:
|
||||
state.tenants.createTenant.fields.tenantSize.maxAllocableMemo,
|
||||
memorySize: state.tenants.createTenant.fields.tenantSize.memorySize,
|
||||
resourcesSize: state.tenants.createTenant.fields.tenantSize.resourcesSize,
|
||||
distribution: state.tenants.createTenant.fields.tenantSize.distribution,
|
||||
ecParityCalc: state.tenants.createTenant.fields.tenantSize.ecParityCalc,
|
||||
limitSize: state.tenants.createTenant.fields.tenantSize.limitSize,
|
||||
limitSize: state.tenants.createTenant.limitSize,
|
||||
selectedStorageClass:
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageClass,
|
||||
cpuToUse: state.tenants.createTenant.fields.tenantSize.cpuToUse,
|
||||
maxAllocatableResources:
|
||||
state.tenants.createTenant.fields.tenantSize.maxAllocatableResources,
|
||||
maxCPUsUse: state.tenants.createTenant.fields.tenantSize.maxCPUsUse,
|
||||
maxMemorySize: state.tenants.createTenant.fields.tenantSize.maxMemorySize,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, {
|
||||
|
||||
@@ -122,8 +122,10 @@ export interface ITenantsResponse {
|
||||
tenants: ITenant[];
|
||||
}
|
||||
|
||||
export interface IMemorySize {
|
||||
export interface IResourcesSize {
|
||||
error: string;
|
||||
limit: number;
|
||||
request: number;
|
||||
memoryRequest: number;
|
||||
memoryLimit: number;
|
||||
cpuRequest: number;
|
||||
cpuLimit: number;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import {
|
||||
ADD_TENANT_ENCRYPTION_VAULT_CA,
|
||||
ADD_TENANT_ENCRYPTION_GEMALTO_CA,
|
||||
ADD_TENANT_RESET_FORM,
|
||||
ADD_TENANT_SET_LIMIT_SIZE,
|
||||
TENANT_DETAILS_SET_LOADING,
|
||||
TENANT_DETAILS_SET_CURRENT_TENANT,
|
||||
TENANT_DETAILS_SET_TENANT,
|
||||
@@ -200,10 +201,13 @@ const initialState: ITenantState = {
|
||||
ecParityChoices: [],
|
||||
cleanECChoices: [],
|
||||
maxAllocableMemo: 0,
|
||||
memorySize: {
|
||||
cpuToUse: "0",
|
||||
resourcesSize: {
|
||||
error: "",
|
||||
limit: 0,
|
||||
request: 0,
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
},
|
||||
distribution: {
|
||||
error: "",
|
||||
@@ -221,6 +225,20 @@ const initialState: ITenantState = {
|
||||
storageFactors: [],
|
||||
},
|
||||
limitSize: {},
|
||||
maxAllocatableResources: {
|
||||
min_allocatable_mem: 0,
|
||||
min_allocatable_cpu: 0,
|
||||
cpu_priority: {
|
||||
max_allocatable_cpu: 0,
|
||||
max_allocatable_mem: 0,
|
||||
},
|
||||
mem_priority: {
|
||||
max_allocatable_cpu: 0,
|
||||
max_allocatable_mem: 0,
|
||||
},
|
||||
},
|
||||
maxCPUsUse: "0",
|
||||
maxMemorySize: "0"
|
||||
},
|
||||
affinity: {
|
||||
nodeSelectorLabels: "",
|
||||
@@ -371,6 +389,13 @@ export function tenantsReducer(
|
||||
},
|
||||
};
|
||||
return { ...changeCL };
|
||||
case ADD_TENANT_SET_LIMIT_SIZE:
|
||||
const changeSizeLimit = {
|
||||
...state,
|
||||
createTenant: { ...state.createTenant, limitSize: action.limitSize },
|
||||
};
|
||||
|
||||
return { ...changeSizeLimit };
|
||||
case ADD_TENANT_ADD_MINIO_KEYPAIR:
|
||||
const minioCerts = [
|
||||
...state.createTenant.certificates.minioCertificates,
|
||||
@@ -714,11 +739,6 @@ export function tenantsReducer(
|
||||
ecParityChoices: [],
|
||||
cleanECChoices: [],
|
||||
maxAllocableMemo: 0,
|
||||
memorySize: {
|
||||
error: "",
|
||||
limit: 0,
|
||||
request: 0,
|
||||
},
|
||||
distribution: {
|
||||
error: "",
|
||||
nodes: 0,
|
||||
@@ -735,6 +755,28 @@ export function tenantsReducer(
|
||||
storageFactors: [],
|
||||
},
|
||||
limitSize: {},
|
||||
cpuToUse: "0",
|
||||
resourcesSize: {
|
||||
error: "",
|
||||
memoryRequest: 0,
|
||||
memoryLimit: 0,
|
||||
cpuRequest: 0,
|
||||
cpuLimit: 0,
|
||||
},
|
||||
maxAllocatableResources: {
|
||||
min_allocatable_mem: 0,
|
||||
min_allocatable_cpu: 0,
|
||||
cpu_priority: {
|
||||
max_allocatable_cpu: 0,
|
||||
max_allocatable_mem: 0,
|
||||
},
|
||||
mem_priority: {
|
||||
max_allocatable_cpu: 0,
|
||||
max_allocatable_mem: 0,
|
||||
},
|
||||
},
|
||||
maxCPUsUse: "0",
|
||||
maxMemorySize: "0"
|
||||
},
|
||||
affinity: {
|
||||
nodeSelectorLabels: "",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { IErasureCodeCalc } from "../../../common/types";
|
||||
import { IMemorySize, ITenant } from "./ListTenants/types";
|
||||
import { ITenant, IResourcesSize } from "./ListTenants/types";
|
||||
import { KeyPair, Opts } from "./ListTenants/utils";
|
||||
|
||||
export const ADD_TENANT_SET_CURRENT_PAGE = "ADD_TENANT/SET_CURRENT_PAGE";
|
||||
@@ -238,10 +238,14 @@ export interface ITenantSizeFields {
|
||||
ecParityChoices: Opts[];
|
||||
cleanECChoices: string[];
|
||||
maxAllocableMemo: number;
|
||||
memorySize: IMemorySize;
|
||||
resourcesSize: IResourcesSize;
|
||||
distribution: any;
|
||||
ecParityCalc: IErasureCodeCalc;
|
||||
cpuToUse: string;
|
||||
limitSize: any;
|
||||
maxAllocatableResources: AllocableResourcesResponse;
|
||||
maxCPUsUse: string;
|
||||
maxMemorySize: string;
|
||||
}
|
||||
|
||||
export interface ITenantAffinity {
|
||||
@@ -268,6 +272,18 @@ export interface ILabelKeyPair {
|
||||
labelValue: string;
|
||||
}
|
||||
|
||||
export interface AllocableResourcesResponse {
|
||||
min_allocatable_mem?: number;
|
||||
min_allocatable_cpu?: number;
|
||||
cpu_priority: NodeMaxAllocatableResources;
|
||||
mem_priority: NodeMaxAllocatableResources;
|
||||
}
|
||||
|
||||
export interface NodeMaxAllocatableResources {
|
||||
max_allocatable_cpu: number;
|
||||
max_allocatable_mem: number;
|
||||
}
|
||||
|
||||
interface SetTenantWizardPage {
|
||||
type: typeof ADD_TENANT_SET_CURRENT_PAGE;
|
||||
page: number;
|
||||
|
||||
@@ -19,7 +19,7 @@ securityDefinitions:
|
||||
tokenUrl: http://min.io
|
||||
# Apply the key security definition to all APIs
|
||||
security:
|
||||
- key: [ ]
|
||||
- key: []
|
||||
paths:
|
||||
/login:
|
||||
get:
|
||||
@@ -35,7 +35,7 @@ paths:
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
# Exclude this API from the authentication requirement
|
||||
security: [ ]
|
||||
security: []
|
||||
tags:
|
||||
- UserAPI
|
||||
/login/operator:
|
||||
@@ -55,7 +55,7 @@ paths:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
security: [ ]
|
||||
security: []
|
||||
tags:
|
||||
- UserAPI
|
||||
|
||||
@@ -76,7 +76,7 @@ paths:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
security: [ ]
|
||||
security: []
|
||||
tags:
|
||||
- UserAPI
|
||||
|
||||
@@ -110,7 +110,6 @@ paths:
|
||||
tags:
|
||||
- UserAPI
|
||||
|
||||
|
||||
/subscription/info:
|
||||
get:
|
||||
summary: Subscription info
|
||||
@@ -188,7 +187,6 @@ paths:
|
||||
tags:
|
||||
- OperatorAPI
|
||||
|
||||
|
||||
/tenants:
|
||||
get:
|
||||
summary: List Tenant of All Namespaces
|
||||
@@ -794,6 +792,29 @@ paths:
|
||||
tags:
|
||||
- OperatorAPI
|
||||
|
||||
/cluster/allocatable-resources:
|
||||
get:
|
||||
summary: Get allocatable cpu and memory for given number of nodes
|
||||
operationId: GetAllocatableResources
|
||||
parameters:
|
||||
- name: num_nodes
|
||||
in: query
|
||||
required: true
|
||||
type: integer
|
||||
format: int32
|
||||
minimum: 1
|
||||
responses:
|
||||
200:
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: "#/definitions/allocatableResourcesResponse"
|
||||
default:
|
||||
description: Generic error response.
|
||||
schema:
|
||||
$ref: "#/definitions/error"
|
||||
tags:
|
||||
- OperatorAPI
|
||||
|
||||
/get-parity/{nodes}/{disksPerNode}:
|
||||
get:
|
||||
summary: Gets parity by sending number of nodes & number of disks
|
||||
@@ -926,7 +947,6 @@ paths:
|
||||
- OperatorAPI
|
||||
|
||||
definitions:
|
||||
|
||||
error:
|
||||
type: object
|
||||
required:
|
||||
@@ -945,7 +965,7 @@ definitions:
|
||||
properties:
|
||||
loginStrategy:
|
||||
type: string
|
||||
enum: [ form, redirect, service-account ]
|
||||
enum: [form, redirect, service-account]
|
||||
redirect:
|
||||
type: string
|
||||
loginRequest:
|
||||
@@ -980,7 +1000,7 @@ definitions:
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [ ok ]
|
||||
enum: [ok]
|
||||
operator:
|
||||
type: boolean
|
||||
permissions:
|
||||
@@ -1325,10 +1345,10 @@ definitions:
|
||||
type: string
|
||||
securityContext:
|
||||
type: object
|
||||
$ref: '#/definitions/securityContext'
|
||||
$ref: "#/definitions/securityContext"
|
||||
postgres_securityContext:
|
||||
type: object
|
||||
$ref: '#/definitions/securityContext'
|
||||
$ref: "#/definitions/securityContext"
|
||||
postgres_image:
|
||||
type: string
|
||||
postgres_init_image:
|
||||
@@ -1350,7 +1370,7 @@ definitions:
|
||||
type: string
|
||||
securityContext:
|
||||
type: object
|
||||
$ref: '#/definitions/securityContext'
|
||||
$ref: "#/definitions/securityContext"
|
||||
idpConfiguration:
|
||||
type: object
|
||||
properties:
|
||||
@@ -1454,7 +1474,7 @@ definitions:
|
||||
$ref: "#/definitions/azureConfiguration"
|
||||
securityContext:
|
||||
type: object
|
||||
$ref: '#/definitions/securityContext'
|
||||
$ref: "#/definitions/securityContext"
|
||||
|
||||
vaultConfiguration:
|
||||
type: object
|
||||
@@ -1701,7 +1721,7 @@ definitions:
|
||||
$ref: "#/definitions/poolTolerations"
|
||||
securityContext:
|
||||
type: object
|
||||
$ref: '#/definitions/securityContext'
|
||||
$ref: "#/definitions/securityContext"
|
||||
|
||||
poolTolerations:
|
||||
description: Tolerations allows users to set entries like effect,
|
||||
@@ -2150,7 +2170,6 @@ definitions:
|
||||
items:
|
||||
type: string
|
||||
|
||||
|
||||
subscriptionValidateRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -2226,7 +2245,6 @@ definitions:
|
||||
drive:
|
||||
type: string
|
||||
|
||||
|
||||
csiFormatErrorResponse:
|
||||
type: object
|
||||
properties:
|
||||
@@ -2330,19 +2348,42 @@ definitions:
|
||||
force:
|
||||
type: boolean
|
||||
securityContext:
|
||||
type: object
|
||||
required:
|
||||
- runAsUser
|
||||
- runAsGroup
|
||||
- runAsNonRoot
|
||||
- fsGroup
|
||||
properties:
|
||||
runAsUser:
|
||||
type: string
|
||||
runAsGroup:
|
||||
type: string
|
||||
runAsNonRoot:
|
||||
type: boolean
|
||||
fsGroup:
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- runAsUser
|
||||
- runAsGroup
|
||||
- runAsNonRoot
|
||||
- fsGroup
|
||||
properties:
|
||||
runAsUser:
|
||||
type: string
|
||||
runAsGroup:
|
||||
type: string
|
||||
runAsNonRoot:
|
||||
type: boolean
|
||||
fsGroup:
|
||||
type: string
|
||||
|
||||
allocatableResourcesResponse:
|
||||
type: object
|
||||
properties:
|
||||
min_allocatable_mem:
|
||||
type: integer
|
||||
format: int64
|
||||
min_allocatable_cpu:
|
||||
type: integer
|
||||
format: int64
|
||||
cpu_priority:
|
||||
$ref: "#/definitions/nodeMaxAllocatableResources"
|
||||
mem_priority:
|
||||
$ref: "#/definitions/nodeMaxAllocatableResources"
|
||||
|
||||
nodeMaxAllocatableResources:
|
||||
type: object
|
||||
properties:
|
||||
max_allocatable_cpu:
|
||||
type: integer
|
||||
format: int64
|
||||
max_allocatable_mem:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
Reference in New Issue
Block a user