Skip to content

Commit

Permalink
Add some AMI OEM objects (#377)
Browse files Browse the repository at this point in the history
This is far from complete, but adds some basic OEM objects for AMI-based
Redfish implementations.

Signed-off-by: Sean McGinnis <[email protected]>
  • Loading branch information
stmcginnis authored Oct 20, 2024
1 parent aa597ec commit 58a9e90
Show file tree
Hide file tree
Showing 10 changed files with 959 additions and 2 deletions.
86 changes: 86 additions & 0 deletions oem/ami/accountservice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// SPDX-License-Identifier: BSD-3-Clause
//

package ami

import (
"encoding/json"

"github.com/stmcginnis/gofish/common"
"github.com/stmcginnis/gofish/redfish"
)

// PAMOrder is the PAM modules used for authentication.
type PAMOrder string

const (
// IPMIPAMOrder specifies IPMI authentication.
IPMIPAMOrder PAMOrder = "IPMI"
// LDAPPAMOrder specifies LDAP authentication.
LDAPPAMOrder PAMOrder = "LDAP"
// ACTIVEDIRECTORYPAMOrder specifies ACTIVE DIRECTORY authentication.
ACTIVEDIRECTORYPAMOrder PAMOrder = "ACTIVE DIRECTORY"
// RADIUSPAMOrder specifies RADIUS authentication.
RADIUSPAMOrder PAMOrder = "RADIUS"
)

// AccountServiceConfigurations allows additional configuring of the AMI AccountService.
type AccountServiceConfigurations struct {
common.Entity
// ODataContext is the odata context.
ODataContext string `json:"@odata.context"`
// ODataEtag is the odata etag.
ODataEtag string `json:"@odata.etag"`
// ODataType is the odata type.
ODataType string `json:"@odata.type"`
// Description provides a description of this resource.
Description string
// PAMEnabled indicates whether or not PAM authentication should be used when authenticating Redfish requests.
PAMEnabled bool
// PAMOrder is an array that represents the order the PAM modules will be checked for authentication.
PAMOrder []PAMOrder
}

// GetAccountServiceConfigurations will get an AccountServiceConfigurations instance from the Redfish
// service.
func GetAccountServiceConfigurations(c common.Client, uri string) (*AccountServiceConfigurations, error) {
return common.GetObject[AccountServiceConfigurations](c, uri)
}

// AccountService is an AMI OEM instance of an AccountService.
type AccountService struct {
redfish.AccountService

configuration string
}

// FromAccountService converts a standard AccountService object to the OEM implementation.
func FromAccountService(accountService *redfish.AccountService) (*AccountService, error) {
as := AccountService{
AccountService: *accountService,
}

var t struct {
Oem struct {
AMI struct {
Configurtion common.Link `json:"Configuration"`
} `json:"AMI"`
} `json:"Oem"`
}

err := json.Unmarshal(accountService.RawData, &t)
if err != nil {
return nil, err
}

as.configuration = t.Oem.AMI.Configurtion.String()
as.SetClient(accountService.GetClient())

return &as, nil
}

// Configuration will get the AccountServiceConfigurations for this AccountService.
func (as *AccountService) Configuration() (*AccountServiceConfigurations, error) {
return GetAccountServiceConfigurations(as.GetClient(), as.configuration)
}
102 changes: 102 additions & 0 deletions oem/ami/accountservice_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// SPDX-License-Identifier: BSD-3-Clause
//

package ami

import (
"encoding/json"
"strings"
"testing"

"github.com/stmcginnis/gofish/redfish"
)

var accountServiceBody = `{
"@odata.type": "#AccountService.v1_7_2.AccountService",
"@odata.id": "/redfish/v1/AccountService",
"Id": "AccountService",
"Name": "Account Service",
"Oem": {
"Ami": {
"@odata.type": "#AMIAccountService.v1_0_0.AMIAccountService",
"Configuration": {
"@odata.id": "/redfish/v1/AccountService/Oem/Ami/Configurations"
}
}
},
"PrivilegeMap": {
"@odata.id": "/redfish/v1/Registries/Redfish_1.4.0_PrivilegeRegistry.json"
},
"Roles": {
"@odata.id": "/redfish/v1/AccountService/Roles"
},
"ServiceEnabled": true,
"Status": {
"Health": "OK",
"State": "Enabled"
}
}`

// TestAMIAccountService tests the parsing of the AccountService.
func TestAMIAccountService(t *testing.T) {
as := &redfish.AccountService{}
if err := json.Unmarshal([]byte(accountServiceBody), as); err != nil {
t.Fatalf("error decoding json: %v", err)
}

accountService, err := FromAccountService(as)
if err != nil {
t.Fatalf("error getting oem info: %v", err)
}

if accountService.ID != "AccountService" {
t.Errorf("unexpected ID: %s", accountService.ID)
}

if accountService.configuration != "/redfish/v1/AccountService/Oem/Ami/Configurations" {
t.Errorf("unexpected configuration link: %s", accountService.configuration)
}
}

var accountServiceConfigurationsBody = `{
"@odata.context": "/redfish/v1/$metadata#AMIAccountServiceConfigurations.AMIAccountServiceConfigurations",
"@odata.etag": "\"1729105654\"",
"@odata.id": "/redfish/v1/AccountService/Oem/Ami/Configurations",
"@odata.type": "#AMIAccountServiceConfigurations.v1_0_0.AMIAccountServiceConfigurations",
"Id": "Configurations",
"Name": "AccountService Configurations",
"PAMEnabled": true,
"PAMOrder": [
"IPMI",
"LDAP",
"ACTIVE DIRECTORY",
"RADIUS"
]
}`

// TestAMIAccountServiceConfigurations tests the parsing of the AccountServiceConfigurations.
func TestAMIAccountServiceConfigurations(t *testing.T) {
var result AccountServiceConfigurations
err := json.NewDecoder(strings.NewReader(accountServiceConfigurationsBody)).Decode(&result)

if err != nil {
t.Errorf("Error decoding JSON: %s", err)
}

if result.ID != "Configurations" {
t.Errorf("unexpected ID: %s", result.ID)
}

if !result.PAMEnabled {
t.Errorf("unexpected PAMEnabled: %t", result.PAMEnabled)
}

if len(result.PAMOrder) != 4 {
t.Errorf("unexpected PAMOrder length: %d", len(result.PAMOrder))
}

if result.PAMOrder[0] != "IPMI" {
t.Errorf("unexpected PAMOrder[0]: %s", result.PAMOrder[0])
}
}
141 changes: 141 additions & 0 deletions oem/ami/computersystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//
// SPDX-License-Identifier: BSD-3-Clause
//

package ami

import (
"encoding/json"

"github.com/stmcginnis/gofish/common"
"github.com/stmcginnis/gofish/redfish"
)

// ManagerBootMode is is the boot mode of the manager.
type ManagerBootMode string

const (
// NoneManagerBootMode Added None in Boot Option
NoneManagerBootMode ManagerBootMode = "None"
// SoftResetManagerBootMode Added SoftReset in Boot Option
SoftResetManagerBootMode ManagerBootMode = "SoftReset"
// ResetTimeoutManagerBootMode ResetTimeout support is Boot Option
ResetTimeoutManagerBootMode ManagerBootMode = "ResetTimeout"
)

// AMIBIOSInventoryCRC provides the information related to inventory data/
//
//nolint:revive
type AMIBIOSInventoryCRC struct {
// Bios provides the information related to inventory data.
Bios Bios
// ManagerBootConfiguration indicates the properties related to ManagerBoot
ManagerBootConfiguration ManagerBootConfiguration
}

// BiosTableis the root for BiosTable information.
type BiosTable struct {
common.Entity
// ODataContext is the odata context.
ODataContext string `json:"@odata.context"`
// ODataType is the odata type.
ODataType string `json:"@odata.type"`
// Description provides a description of this resource.
Description string
// FilesContent contains the contents of the BiosTable file.
FilesContent string
}

// TableTag contains the TableTag informations.
type TableTag struct {
// TableType shall contain a string representing the TableTag.
TableType string
// Value shall contains the value for the corresponding TableTag.
Value string
}

// BiosTableTags is the root for TableTags information.
type BiosTableTags struct {
common.Entity
// ODataContext is the odata context.
ODataContext string `json:"@odata.context"`
// ODataType is the odata type.
ODataType string `json:"@odata.type"`
// Description provides a description of this resource.
Description string
// NumberofTables contains the number of TableTags present.
NumberofTables string
// TableTags contains the TableTags informations.
TableTags []TableTag
}

// Bios
type Bios struct {
// BiosTable provides the information related to BiosTable
BiosTable BiosTable
// BiosTableTags provides the information related to BiosTableTags.
BiosTableTags BiosTableTags
// Inventory provides the information related to inventory data Crc value.
Inventory Inventory
// RedfishVersion shall represent the version of the Redfish service. The format of this string shall be of the
// format majorversion.minorversion.errata in compliance with Protocol Version section of the Redfish
// specification.
RedfishVersion string
// RTPVersion shall represent the version of the RTP Version.
RTPVersion string
}

// Crc
type Crc struct {
// GroupCrcList provides the information related to inventory data of GroupCrcList value.
GroupCrcList []map[string]uint64
}

// Inventory
type Inventory struct {
// Crc provides the information related to inventory data of Crc value.
Crc Crc
}

// ManagerBootConfiguration
type ManagerBootConfiguration struct {
// ManagerBootMode shall specify the enum supported by ManagerBootMode.
ManagerBootMode ManagerBootMode
}

// ComputerSystem is the update service instance associated with the system.
type ComputerSystem struct {
redfish.ComputerSystem

BIOS Bios
ManagerBootConfiguration ManagerBootConfiguration
SSIFMode string
}

// FromComputerSystem gets the OEM instance of the ComputerSystemSystem.
func FromComputerSystem(computerSystem *redfish.ComputerSystem) (*ComputerSystem, error) {
us := ComputerSystem{
ComputerSystem: *computerSystem,
}

var t struct {
Oem struct {
Ami struct {
BIOS Bios `json:"BIOS"`
ManagerBootConfiguration ManagerBootConfiguration `json:"ManagerBootConfiguration"`
SSIFMode string `json:"SSIFMode"`
}
}
}

err := json.Unmarshal(computerSystem.RawData, &t)
if err != nil {
return nil, err
}

us.BIOS = t.Oem.Ami.BIOS
us.ManagerBootConfiguration = t.Oem.Ami.ManagerBootConfiguration
us.SSIFMode = t.Oem.Ami.SSIFMode

return &us, nil
}
Loading

0 comments on commit 58a9e90

Please sign in to comment.