Skip to content
This repository has been archived by the owner on Jul 18, 2024. It is now read-only.

Update BIOSConfig and server metadata when receiving request #10

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions internal/fleetdb/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@ package internalfleetdb

import (
"encoding/json"
"fmt"
"os"

"github.com/metal-toolbox/component-inventory/pkg/api/constants"
"github.com/metal-toolbox/component-inventory/pkg/api/types"
fleetdb "github.com/metal-toolbox/fleetdb/pkg/api/v1"
)

const (
uefiVariablesKey = "uefi-variables"
ssMetadataAttributeFound = "__ss_found"
)

func deviceVendorAttributes(cid *types.ComponentInventoryDevice) (map[string]string, *fleetdb.Attributes, error) {
deviceVendorData := map[string]string{
constants.ServerSerialAttributeKey: "unknown",
Expand Down Expand Up @@ -50,3 +57,35 @@ func attributeByNamespace(ns string, attributes []fleetdb.Attributes) *fleetdb.A

return nil
}

// mustFilterAssetMetadata processes the asset inventory metadata to filter out fields we'll turn into versioned attributes (e.g. UEFIVariables)
func mustFilterAssetMetadata(inventory map[string]string) json.RawMessage {
excludedKeys := map[string]struct{}{
uefiVariablesKey: {},
}

filtered := make(map[string]string)

for k, v := range inventory {
if _, ok := excludedKeys[k]; ok {
continue
}
filtered[k] = v
}

byt, err := json.Marshal(filtered)
if err != nil {
panic("serializing metadata string map")
}

return byt
}

// serverBIOSConfigNS returns the namespace server bios configuration are stored in.
func serverBIOSConfigNS(appKind types.AppKind) string {
if biosConfigNS := os.Getenv("CIS_FLEETDB_BIOS_CONFIG_NS"); biosConfigNS != "" {
return biosConfigNS
}

return fmt.Sprintf("%s.%s.bios_configuration", constants.FleetDBNSPrefix, appKind)
}
70 changes: 58 additions & 12 deletions internal/fleetdb/fleetdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package internalfleetdb
import (
"context"
"encoding/json"
"fmt"

"github.com/google/uuid"
"github.com/metal-toolbox/component-inventory/internal/app"
Expand All @@ -17,7 +16,8 @@ type Client interface {
GetServer(context.Context, uuid.UUID) (*fleetdb.Server, *fleetdb.ServerResponse, error)
GetComponents(context.Context, uuid.UUID, *fleetdb.PaginationParams) (fleetdb.ServerComponentSlice, *fleetdb.ServerResponse, error)
UpdateAttributes(context.Context, *fleetdb.Server, *types.ComponentInventoryDevice, *zap.Logger) error
UpdateServerBIOSConfig() error
UpdateServerBIOSConfig(context.Context, *fleetdb.Server, *types.ComponentInventoryDevice, *zap.Logger) error
UpdateServerMetadataAttributes(context.Context, uuid.UUID, *types.ComponentInventoryDevice, *zap.Logger) error
}

// Creates a new Client, with reasonable defaults
Expand All @@ -37,7 +37,8 @@ func NewFleetDBClient(cfg *app.Configuration) (Client, error) {
}

type fleetDBClient struct {
client *fleetdb.Client
client *fleetdb.Client
appKind types.AppKind
}

func (fc fleetDBClient) GetServer(ctx context.Context, id uuid.UUID) (*fleetdb.Server, *fleetdb.ServerResponse, error) {
Expand Down Expand Up @@ -78,13 +79,12 @@ func createUpdateServerAttributes(ctx context.Context, c *fleetdb.Client, server
return err
}

updatedVendorData := existingVendorData
var changes bool
for key := range newVendorData {
if updatedVendorData[key] == "" || updatedVendorData[key] == "unknown" {
if existingVendorData[key] == "" || existingVendorData[key] == "unknown" {
if newVendorData[key] != "unknown" {
changes = true
updatedVendorData[key] = newVendorData[key]
existingVendorData[key] = newVendorData[key]
}
}
}
Expand All @@ -93,8 +93,8 @@ func createUpdateServerAttributes(ctx context.Context, c *fleetdb.Client, server
return nil
}

if len(updatedVendorData) > 0 {
updateBytes, err := json.Marshal(updatedVendorData)
if len(existingVendorData) > 0 {
updateBytes, err := json.Marshal(existingVendorData)
if err != nil {
return err
}
Expand All @@ -107,10 +107,56 @@ func createUpdateServerAttributes(ctx context.Context, c *fleetdb.Client, server
return nil
}

func (fc fleetDBClient) UpdateServerBIOSConfig() error {
return createUpdateServerBIOSConfig()
func (fc fleetDBClient) UpdateServerBIOSConfig(ctx context.Context, server *fleetdb.Server, dev *types.ComponentInventoryDevice, log *zap.Logger) error {
// Nothing to publish
if len(*dev.BiosCfg) == 0 {
log.Info("no bios configuration collected")
return nil
}

// marshal metadata from device
bc, err := json.Marshal(dev.BiosCfg)
if err != nil {
log.Error("invalid biosConfig")
return err
}

va := fleetdb.VersionedAttributes{
Namespace: serverBIOSConfigNS(fc.appKind),
Data: bc,
}

_, err = fc.client.CreateVersionedAttributes(ctx, server.UUID, va)

return err
}

func createUpdateServerBIOSConfig() error {
return fmt.Errorf("unimplemented")
func (fc fleetDBClient) UpdateServerMetadataAttributes(ctx context.Context, serverID uuid.UUID, dev *types.ComponentInventoryDevice, log *zap.Logger) error {
// no metadata reported in inventory from device
if dev.Inv == nil || len(dev.Inv.Metadata) == 0 {
// XXX: should delete the metadata on the server-service record!
return nil
}

// marshal metadata from device
metadata := mustFilterAssetMetadata(dev.Inv.Metadata)

attribute := fleetdb.Attributes{
Namespace: constants.ServerMetadataAttributeNS,
Data: metadata,
}

// XXX: This would be much easier if serverservice/fleetdb supported upsert
// current asset metadata has no attributes set and no metadata attribute, create one
if _, ok := dev.Inv.Metadata[ssMetadataAttributeFound]; !ok {
_, err := fc.client.CreateAttributes(ctx, serverID, attribute)
log.Info("creating server attributes")
return err
}

// update vendor, model attributes
_, err := fc.client.UpdateAttributes(ctx, serverID, constants.ServerMetadataAttributeNS, metadata)

return err

}
10 changes: 5 additions & 5 deletions pkg/api/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ const (
// server server service BMC address attribute key found under the bmcAttributeNamespace
BmcIPAddressAttributeKey = "address"

// serverservice namespace prefix the data is stored in.
ServerServiceNSPrefix = "sh.hollow.alloy"
// fleetdb namespace prefix the data is stored in.
FleetDBNSPrefix = "sh.hollow.alloy"

// server vendor, model attributes are stored in this namespace.
ServerVendorAttributeNS = ServerServiceNSPrefix + ".server_vendor_attributes"
ServerVendorAttributeNS = FleetDBNSPrefix + ".server_vendor_attributes"

// additional server metadata are stored in this namespace.
ServerMetadataAttributeNS = ServerServiceNSPrefix + ".server_metadata_attributes"
ServerMetadataAttributeNS = FleetDBNSPrefix + ".server_metadata_attributes"

// errors that occurred when connecting/collecting inventory from the bmc are stored here.
ServerBMCErrorsAttributeNS = ServerServiceNSPrefix + ".server_bmc_errors"
ServerBMCErrorsAttributeNS = FleetDBNSPrefix + ".server_bmc_errors"

// server service server serial attribute key
ServerSerialAttributeKey = "serial"
Expand Down
12 changes: 12 additions & 0 deletions pkg/api/routes/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,21 @@ import (

func processInband(ctx context.Context, c internalfleetdb.Client, server *fleetdb.Server, dev *types.ComponentInventoryDevice, log *zap.Logger) error { //nolint
log.Info("processing", zap.String("server", server.Name), zap.String("device", dev.Inv.Serial))
// update bisconfig
if err := c.UpdateServerBIOSConfig(ctx, server, dev, log); err != nil {
return err
}

// create/update server serial, vendor, model attributes
if err := c.UpdateAttributes(ctx, server, dev, log); err != nil {
return err
}

// create update server metadata attributes
if err := c.UpdateServerMetadataAttributes(ctx, server.UUID, dev, log); err != nil {
return err
}

return errors.New("not implemented")
}

Expand Down
5 changes: 4 additions & 1 deletion pkg/api/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import (
"github.com/bmc-toolbox/common"
)

type BiosConfig map[string]string
type (
BiosConfig map[string]string
AppKind string
)

type ComponentInventoryDevice struct {
ID string `json:"id,omitempty"`
Expand Down
Loading