Skip to content

Commit

Permalink
Add some AMI OEM objects
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 committed Oct 20, 2024
1 parent aa597ec commit 73b8a2d
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 73b8a2d

Please sign in to comment.