diff --git a/pkg/backend/backend.go b/pkg/backend/backend.go index 2732282..be09636 100644 --- a/pkg/backend/backend.go +++ b/pkg/backend/backend.go @@ -11,6 +11,7 @@ type BackendOperations interface { CreateSession(context.Context, *ConfigurationSettings, *CreateSessionRequest) (*CreateSessionResponse, error) DeleteSession(context.Context, *ConfigurationSettings, *DeleteSessionRequest) (*DeleteSessionResponse, error) GetMemoryResourceBlocks(context.Context, *ConfigurationSettings, *MemoryResourceBlocksRequest) (*MemoryResourceBlocksResponse, error) + GetMemoryResourceBlocksCompositionStatus(context.Context, *ConfigurationSettings, *MemoryResourceBlocksCompositionRequest) (*MemoryResourceBlocksCompositionResponse, error) GetMemoryResourceBlockById(context.Context, *ConfigurationSettings, *MemoryResourceBlockByIdRequest) (*MemoryResourceBlockByIdResponse, error) GetPorts(context.Context, *ConfigurationSettings, *GetPortsRequest) (*GetPortsResponse, error) GetHostPortPcieDevices(ctx context.Context, settings *ConfigurationSettings, req *GetPortsRequest) (*GetPortsResponse, error) diff --git a/pkg/backend/httpfish.go b/pkg/backend/httpfish.go index 42c1541..9b1dace 100644 --- a/pkg/backend/httpfish.go +++ b/pkg/backend/httpfish.go @@ -1138,6 +1138,74 @@ func (service *httpfishService) GetMemoryResourceBlocks(ctx context.Context, set return &MemoryResourceBlocksResponse{MemoryResources: memoryResources, Status: "Success", ServiceError: nil}, nil } +// GetMemoryResourceBlocks: Request Memory Resource Block information from the backends +func (service *httpfishService) GetMemoryResourceBlocksCompositionStatus(ctx context.Context, settings *ConfigurationSettings, req *MemoryResourceBlocksCompositionRequest) (*MemoryResourceBlocksCompositionResponse, error) { + logger := klog.FromContext(ctx) + logger.V(4).Info("====== GetMemoryResourceBlocksCompositionStatus ======") + logger.V(4).Info("memory resource blocks", "request", req) + + memoryResourcesStatus := make([]MemoryResourceBlock, 0) + + session := service.service.session.(*Session) + + response := session.query(HTTPOperation.GET, session.redfishPaths[ResourceBlocksKey]) + + if response.err != nil { + return &MemoryResourceBlocksCompositionResponse{Status: "Failure", ServiceError: response.err}, response.err + } + + oemField, err := response.valueFromJSON("Oem") + + if err == nil { + compositionStatus := oemField.(map[string]interface{})["Seagate"].(map[string]interface{})["CompositionStatus"].([]map[string]interface{}) + for _, resourceBlock := range compositionStatus { + // Update CompositionState using the Reserved and CompositionState values from Redfish + + compositionState := resourceBlock["CompositionState"].(string) + reserved := resourceBlock["Reserved"].(bool) + + resourceState := findResourceState(&compositionState, reserved) + + blockInfo := MemoryResourceBlock{ + Id: getIdFromOdataId(resourceBlock["@odata.id"].(string)), + CompositionStatus: MemoryResourceBlockCompositionStatus{ + CompositionState: *resourceState, + }, + } + memoryResourcesStatus = append(memoryResourcesStatus, blockInfo) + } + + } else { + + resourceBlocks, _ := response.arrayFromJSON("Members") + for _, resourceBlock := range resourceBlocks { + blockDetails := session.query(HTTPOperation.GET, resourceBlock.(map[string]interface{})["@odata.id"].(string)) + + if !(blockDetails.err == nil && blockDetails.isMemoryResourceBlock()) { + continue + } + + uri, _ := blockDetails.stringFromJSON("@odata.id") + + compositionStatus, _ := blockDetails.valueFromJSON("CompositionStatus") + reserved := compositionStatus.(map[string]interface{})["Reserved"].(bool) + compositionState := compositionStatus.(map[string]interface{})["CompositionState"].(string) + + resourceState := findResourceState(&compositionState, reserved) + + blockInfo := MemoryResourceBlock{ + Id: getIdFromOdataId(uri), + CompositionStatus: MemoryResourceBlockCompositionStatus{ + CompositionState: *resourceState, + }, + } + memoryResourcesStatus = append(memoryResourcesStatus, blockInfo) + } + } + + return &MemoryResourceBlocksCompositionResponse{MemoryResourcesStatus: memoryResourcesStatus, Status: "Success", ServiceError: nil}, nil +} + // GetMemoryResourceBlockById: Request a particular Memory Resource Block information by ID from the backends func (service *httpfishService) GetMemoryResourceBlockById(ctx context.Context, settings *ConfigurationSettings, req *MemoryResourceBlockByIdRequest) (*MemoryResourceBlockByIdResponse, error) { logger := klog.FromContext(ctx) diff --git a/pkg/backend/ops.go b/pkg/backend/ops.go index aab9d6b..1e544e0 100644 --- a/pkg/backend/ops.go +++ b/pkg/backend/ops.go @@ -94,6 +94,15 @@ type MemoryResourceBlocksResponse struct { ServiceError error // Any error returned by the service } +type MemoryResourceBlocksCompositionRequest struct { +} + +type MemoryResourceBlocksCompositionResponse struct { + MemoryResourcesStatus []MemoryResourceBlock // Array to hold detail of memory resources + Status string // The status of the request + ServiceError error // Any error returned by the service +} + type GetPortsRequest struct { } diff --git a/pkg/manager/blade.go b/pkg/manager/blade.go index fbfb1ea..2011777 100644 --- a/pkg/manager/blade.go +++ b/pkg/manager/blade.go @@ -160,6 +160,26 @@ type RequestComposeMemory struct { Qos openapi.Qos } +// updateAllResourceStatus: Update the composition status on all resource blocks +func (b *Blade) updateAllResourceStatus(ctx context.Context) error { + logger := klog.FromContext(ctx) + logger.V(3).Info(">>>>>> updateAllResourceStatus: ") + + request := backend.MemoryResourceBlocksCompositionRequest{} + settings := backend.ConfigurationSettings{} + compositionResponse, err := b.backendOps.GetMemoryResourceBlocksCompositionStatus(ctx, &settings, &request) + + if err != nil { + return fmt.Errorf("unable to udpate resource block composition status") + } + + for _, blockInfo := range compositionResponse.MemoryResourcesStatus { + block, _ := b.GetResourceById(ctx, blockInfo.Id) + block.details.CompositionStatus.CompositionState = blockInfo.CompositionStatus.CompositionState.String() + } + return nil +} + // ComposeMemory: Create a new memory region of the requested size and, if a port is requested, assign it to a port. // In ComposeMemory, there are two steps in backend, one is AllocateMemory and the other one is AssignMemory // AllocateMemory creates memory region (memorychunk), AssignMemory connects the memory region to an port @@ -168,14 +188,12 @@ func (b *Blade) ComposeMemory(ctx context.Context, r *RequestComposeMemory) (*op logger.V(4).Info(">>>>>> ComposeMemory: ", "portId", r.PortId, "SizeMiB", r.SizeMib, "Qos", r.Qos, "bladeId", b.Id, "applianceId", b.ApplianceId) // Update all resource details - for _, resource := range b.Resources { - _, err := resource.GetDetails(ctx) - if err != nil { - newErr := fmt.Errorf("get details failure on blade [%s] resource [%s]: %w", b.Id, resource.Id, err) - logger.Error(newErr, "failure: compose memory") - return nil, &common.RequestError{StatusCode: err.(*common.RequestError).StatusCode, Err: newErr} - } + err := b.updateAllResourceStatus(ctx) + if err != nil { + logger.Error(err, "failure: compose memory") + return nil, &common.RequestError{StatusCode: common.StatusBladeGetMemoryResourceBlocksFailure, Err: err} } + resourceIds := b.findResourcesByQoS(r.SizeMib, r.Qos) if resourceIds == nil { newErr := fmt.Errorf("unable to find resources by qos during compose: appliance [%s] blade [%s] request [%v]", b.ApplianceId, b.Id, r) diff --git a/pkg/manager/port.go b/pkg/manager/port.go index c99bf65..1940110 100644 --- a/pkg/manager/port.go +++ b/pkg/manager/port.go @@ -35,7 +35,7 @@ type CxlBladePort struct { backendOps backend.BackendOperations } -func NewCxlBladePortById(ctx context.Context, applianceId, bladeId, portId string, ops backend.BackendOperations) (*CxlBladePort) { +func NewCxlBladePortById(ctx context.Context, applianceId, bladeId, portId string, ops backend.BackendOperations) *CxlBladePort { logger := klog.FromContext(ctx) logger.V(4).Info(">>>>>> NewCxlBladePortById: ", "portId", portId, "bladeId", bladeId, "applianceId", applianceId, "backend", ops.GetBackendInfo(ctx).BackendName)