Skip to content

Commit

Permalink
feat: no longer depend on RedfishEndpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
synackd committed Oct 21, 2024
1 parent 0abcb2a commit 44d4488
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 98 deletions.
24 changes: 1 addition & 23 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ type Cache struct {
LastUpdated time.Time
Mutex sync.RWMutex

RedfishEndpoints map[string]RedfishEndpoint
EthernetInterfaces map[string]EthernetInterface
Components map[string]Component
}
Expand Down Expand Up @@ -56,12 +55,6 @@ func (c *Cache) Refresh() error {
return fmt.Errorf("failed to fetch Components from SMD: %w", err)
}
log.Debug("Components: " + string(compsData))
log.Debug("fetching RedfishEndpoints")
rfeData, err := c.Client.APIGetToken("/hsm/v2/Inventory/RedfishEndpoints")
if err != nil {
return fmt.Errorf("failed to fetch RedfishEndpoints from SMD: %w", err)
}
log.Debug("RedfishEndpoints: " + string(rfeData))

// Unmarshal it
log.Debug("unmarshaling EthernetInterfaces")
Expand All @@ -78,14 +71,6 @@ func (c *Cache) Refresh() error {
if err != nil {
return fmt.Errorf("failed to unmarshal Components data: %w", err)
}
log.Debug("unmarshaling RedfishEndpoints")
var rfeStruct struct {
RedfishEndpoints []RedfishEndpoint `json:"RedfishEndpoints"`
}
err = json.Unmarshal(rfeData, &rfeStruct)
if err != nil {
return fmt.Errorf("failed to unmarshal RedfishEndpoints data: %w", err)
}

// Organize it to be referenced via map
log.Debug("organizing EthernetInterfaces into map")
Expand All @@ -98,22 +83,15 @@ func (c *Cache) Refresh() error {
for _, comp := range compsStruct.Components {
compMap[comp.ID] = comp
}
log.Debug("organizing RedfishEndpoints into map")
rfeMap := make(map[string]RedfishEndpoint)
for _, rfe := range rfeStruct.RedfishEndpoints {
rfeMap[rfe.MACAddr] = rfe
}

// Update cache with info
log.Debug("updating cache with map data")
c.Mutex.Lock()
c.EthernetInterfaces = eiMap
c.Components = compMap
c.RedfishEndpoints = rfeMap
c.LastUpdated = time.Now()
c.Mutex.Unlock()
log.Infof("Cache updated with %d RedfishEndpoints, %d EthernetInterfaces, and %d Components", len(rfeMap), len(eiMap), len(compMap))
log.Debugf("RedfishEndpoints: %v", rfeMap)
log.Infof("Cache updated with %d EthernetInterfaces and %d Components", len(eiMap), len(compMap))
log.Debugf("EthernetInterfaces: %v", eiMap)
log.Debugf("Components: %v", compMap)

Expand Down
70 changes: 31 additions & 39 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ func setup6(args ...string) (handler.Handler6, error) {

func setup4(args ...string) (handler.Handler4, error) {
// Ensure all required args were passed
if len(args) != 5 {
return nil, errors.New("expected 2 arguments: base URL, CA certificate path, cache duration, access token")
if len(args) != 4 {
return nil, errors.New("expected 4 arguments: base URL, boot script base URL, CA certificate path, cache duration")
}

// Create new SmdClient using first argument (base URL)
Expand Down Expand Up @@ -74,9 +74,6 @@ func setup4(args ...string) (handler.Handler4, error) {
return nil, fmt.Errorf("failed to create new cache: %w", err)
}

// Set access token using fifth argument
accessToken = args[4]

cache.RefreshLoop()

log.Infof("coresmd plugin initialized with base URL %s and validity duration %s", smdClient.BaseURL, cache.Duration.String())
Expand All @@ -93,42 +90,37 @@ func Handler4(req, resp *dhcpv4.DHCPv4) (*dhcpv4.DHCPv4, bool) {

// STEP 1: Assign IP address
hwAddr := req.ClientHWAddr.String()
if ei, ok := cache.EthernetInterfaces[hwAddr]; ok {
// First, check EthernetInterfaces, which are mapped to Components
compId := ei.ComponentID
log.Debugf("EthernetInterface found in cache for hardware address %s with ID %s", hwAddr, compId)
comp, ok := cache.Components[compId]
if !ok {
log.Errorf("no Component %s found in cache for EthernetInterface hardware address %s", compId, hwAddr)
return resp, true
}
compNid := comp.NID
log.Debugf("Component found in cache with matching ID %s (NID %d)", compId, compNid)
if len(ei.IPAddresses) == 0 {
log.Errorf("no IP addresses found for component %s with hardware address %s", compId, hwAddr)
return resp, true
}
log.Debugf("IP addresses available for hardware address %s (component %s): %v", hwAddr, compId, ei.IPAddresses)
ip := ei.IPAddresses[0].IPAddress
log.Infof("setting IP for %s to %s", hwAddr, ip)

// Set client IP address
resp.YourIPAddr = net.ParseIP(ip)

// Set client hostname
resp.Options.Update(dhcpv4.OptHostName(fmt.Sprintf("nid%03d", compNid)))
} else if rfe, ok := cache.RedfishEndpoints[hwAddr]; ok {
// If not an EthernetInterface, check RedfishEndpoints which are attached to BMCs
log.Debug("RedfishEndpoint found in cache for hardware address %s", hwAddr)
ip := rfe.IPAddr
log.Infof("setting IP for %s to %s", hwAddr, ip)

// Set client IP address
resp.YourIPAddr = net.ParseIP(ip)
} else {
log.Infof("no EthernetInterfaces or RedfishEndpoints were found in cache for hardware address %s", hwAddr)
ei, ok := cache.EthernetInterfaces[hwAddr]
if !ok {
log.Infof("no EthernetInterfaces were found in cache for hardware address %s", hwAddr)
return resp, true
}

// First, check EthernetInterfaces, which are mapped to Components
compId := ei.ComponentID
log.Debugf("EthernetInterface found in cache for hardware address %s with ID %s", hwAddr, compId)
comp, ok := cache.Components[compId]
if !ok {
log.Errorf("no Component %s found in cache for EthernetInterface hardware address %s", compId, hwAddr)
return resp, true
}
compType := comp.Type
log.Debugf("Component of type %s found in cache with matching ID %s", compType, compId)
if len(ei.IPAddresses) == 0 {
log.Errorf("no IP addresses found for component %s of type %s with hardware address %s", compId, compType, hwAddr)
return resp, true
}
log.Debugf("IP addresses available for hardware address %s (component %s of type %s): %v", hwAddr, compId, compType, ei.IPAddresses)
ip := ei.IPAddresses[0].IPAddress
log.Infof("setting IP for %s (%s) to %s", hwAddr, compType, ip)

// Set client IP address
resp.YourIPAddr = net.ParseIP(ip)

// Set client hostname
if compType == "Node" {
resp.Options.Update(dhcpv4.OptHostName(fmt.Sprintf("nid%03d", comp.NID)))
}

// STEP 2: Send boot config
if cinfo := req.Options.Get(dhcpv4.OptionUserClassInformation); string(cinfo) != "iPXE" {
Expand Down
36 changes: 0 additions & 36 deletions smd.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,11 @@ var (
defaultResponseHeaderTimeout = 120 * time.Second
)

var accessToken string

type SmdClient struct {
*http.Client
BaseURL *url.URL
}

type RedfishEndpoint struct {
IPAddr string `json:IPAddr`
MACAddr string `json:"MACAddr"`
}

type EthernetInterface struct {
MACAddress string `json:"MACAddress"`
ComponentID string `json:"ComponentID"`
Expand Down Expand Up @@ -109,32 +102,3 @@ func (sc *SmdClient) APIGet(path string) ([]byte, error) {

return data, nil
}

func (sc *SmdClient) APIGetToken(path string) ([]byte, error) {
endpoint := sc.BaseURL.JoinPath(path)
req, err := http.NewRequest("GET", endpoint.String(), nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))

if sc == nil {
return nil, fmt.Errorf("SmdClient is nil")
}
if sc.Client == nil {
return nil, fmt.Errorf("SmdClient's HTTP client is nil")
}

resp, err := sc.Client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to execute HTTP request: %w", err)
}
defer resp.Body.Close()

data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}

return data, nil
}

0 comments on commit 44d4488

Please sign in to comment.