Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(oem/supermicro): Add Supermicro Manager OEM functions #213

Closed
wants to merge 4 commits into from

Conversation

feuerrot
Copy link
Contributor

This PR includes functions for:

  • IKVM (Java/HTML5)
  • NTP (Enabled/Servers/DST)
  • Syslog (Enabled/Server)

I'd appreciate any hints regarding the supermicro.Manager-structure and how custom manager extensions should be integrated - while it does work accessing the syslog configuration using smm.supermicroManager.Oem.Supermicro.Syslogs() seems to be rather awkward.

@feuerrot feuerrot marked this pull request as ready for review October 26, 2022 13:46
@stmcginnis
Copy link
Owner

Awesome!

while it does work accessing the syslog configuration using smm.supermicroManager.Oem.Supermicro.Syslogs() seems to be rather awkward.

The way it was invisioned for these OEM extensions it would be a matter of creating the OEM type from the standard type. So something roughly along these lines:

manager := c.GetManager()

smManager := supermicro.FromManager(manager)
for _, logs := range smManager.SysLogs() {
    // process
}

So rather than trying to mirror the whole structure, you just hydrate a new OEM object using the existing Redfish object. A decent example is probably here: https://github.com/stmcginnis/gofish/blob/main/oem/dell/eventservice.go

@feuerrot
Copy link
Contributor Author

@stmcginnis If I understand the Redfish Specification correctly, Supermicros Manager OEM extensions are separate resouces and not part of the manager itself, while Dells Eventservice contains the extensions directly. Does this make a difference in how the Supermicro extensions should be accessed from the manager?

@stmcginnis
Copy link
Owner

@stmcginnis If I understand the Redfish Specification correctly, Supermicros Manager OEM extensions are separate resouces and not part of the manager itself, while Dells Eventservice contains the extensions directly. Does this make a difference in how the Supermicro extensions should be accessed from the manager?

Thanks for the details. That may change a little of how the resulting structs are defined, but that wouldn't change how they are accessed. All OEM data should be accessed by using the standard Redfish objects, then using an OEM implementation to access the oem parts to handle vendor specific (i.e. non-standard) paths.

@feuerrot
Copy link
Contributor Author

I modified the manager accordingly.

Copy link
Owner

@stmcginnis stmcginnis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! I've added some suggestions, so I'll hold off on merging until you've had a chance to take a look and respond.

oem/supermicro/ikvm.go Show resolved Hide resolved

type Manager struct {
redfish.Manager
Oem ManagerOem
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a simple interface to just get rid of this Oem field and move the fields of ManagerOem up a level into Manager.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT, this is just matching the JSON structure

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it's an unnecessary detail for consumers. In the JSON unmarhalling it can pull out the fields and set them as direct properties of the manager struct.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think I know what you mean now. Unexport the whole Oem field?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. You're already using an OEM object, so it feels a little awkward to have to have OEMObject.OEM.Foo instead of OEMObject.Foo.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stmcginnis what do you think?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Close, but I think this would be best:

type Manager struct {
	redfish.Manager
	fanMode         string
	iKVM            string
	ipAccessControl string
	kcsInterface    string
	licenseManager  string
	mouseMode       string
	ntp             string
	radius          string
	smcrakp         string
	snmp            string
	smtp            string
	snooping        string
	sysLockdown     string
	syslog          string
}

type managerOem struct {
	Supermicro struct {
		ODataType       string `json:"@odata.type"`
		FanMode         common.Link
		IKVM            common.Link
		IPAccessControl common.Link
		KCSInterface    common.Link
		LicenseManager  common.Link
		MouseMode       common.Link
		NTP             common.Link
		RADIUS          common.Link
		SMCRAKP         common.Link
		SNMP            common.Link
		SMTP            common.Link
		Snooping        common.Link
		SysLockdown     common.Link
		Syslog          common.Link
	} `json:"Supermicro"`
}

func FromManager(manager *redfish.Manager) (Manager, error) {
	var oem managerOem
	err := json.Unmarshal(manager.Oem, &oem)
	if err != nil {
		return Manager{}, fmt.Errorf("can't unmarshal OEM Manager: %v", err)
	}

	return Manager{
		Manager:         *manager,
		fanMode:         oem.Supermicro.FanMode.String(),
		iKVM:            oem.Supermicro.IKVM.String(),
		ipAccessControl: oem.Supermicro.IPAccessControl.String(),
		kcsInterface:    oem.Supermicro.KCSInterface.String(),
		licenseManager:  oem.Supermicro.LicenseManager.String(),
		mouseMode:       oem.Supermicro.MouseMode.String(),
		ntp:             oem.Supermicro.NTP.String(),
		radius:          oem.Supermicro.RADIUS.String(),
		smcrakp:         oem.Supermicro.SMCRAKP.String(),
		snmp:            oem.Supermicro.SNMP.String(),
		smtp:            oem.Supermicro.SMTP.String(),
		snooping:        oem.Supermicro.Snooping.String(),
		sysLockdown:     oem.Supermicro.SysLockdown.String(),
		syslog:          oem.Supermicro.Syslog.String(),
	}, nil
}

func (manager *Manager) NTP() (*NTP, error) {
	return GetNTP(manager.GetClient(), manager.ntp)
}

func (manager *Manager) Syslog() (*Syslog, error) {
	return GetSyslog(manager.GetClient(), manager.syslog)
}

func (manager *Manager) IKVM() (*IKVM, error) {
	return GetIKVM(manager.GetClient(), manager.iKVM)
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do it like that, but it feels very repetitive to me. Why is the type of, for example Manager.fanMode important, when it's not exported anyway?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can omit the extra ones that you are not adding accessor methods for. I just put them in for completeness.

This is more repetitive for the implementation side so it's cleaner for the library consumer.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words, we implement it once here so others never need to think about it.

type ManagerOem struct {
Supermicro struct {
OdataType string `json:"@odata.type"`
NTP common.Link
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then make these fields lower case. The links aren't needed by the user of the library, just the methods being added below to access the objects that those links point to.

So combined with the above, it would just be something like:

smManager, err := supermicro.FromManager(redfishManager)
if err != nil {
    // Handle it
}

ntp, err := smManager.NTP()

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fields have to be exported to load them with encoding/json

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need them when unmarshalling, but not after that. See elsewhere in the library where the unmarshalling takes care of accessing internal details, then stores them as non-public fields that are used in a more user-friendly interface.

feuerrot and others added 3 commits May 24, 2023 15:29
This commit includes functions for:
* IKVM (Java/HTML5)
* NTP (Enabled/Servers/DST)
* Syslog (Enabled/Server)
Copy link
Owner

@stmcginnis stmcginnis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for taking ridiculously long to get back to this. There are a couple comments still not addressed. If you can make a few updates, this looks really good and we can get it merged.

Thanks for working on this!

type IKVM struct {
common.Entity

OdataType string `json:"@odata.type"`
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've standardized on OData (versus Odata) elsewhere. Mind changing these to be consistent?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it.

@feuerrot
Copy link
Contributor Author

feuerrot commented Jul 3, 2024

Hi,
sorry for my late reply: I don't have access to the Supermicro hardware or the fork anymore, as I switched jobs last year. Maybe @mxey could add the missing changes to this PR?

@mxey
Copy link

mxey commented Jul 4, 2024

Maybe @mxey could add the missing changes to this PR?

Yes, I'll look into this.

@mxey
Copy link

mxey commented Jul 8, 2024

@stmcginnis I responded to all the open review comments. I decided to add another commit to the pull request, since previous review changes also appeared to be extra commits. I would suggest squashing it all together at the end.

Copy link
Owner

@stmcginnis stmcginnis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll take a closer look soon!


type Manager struct {
redfish.Manager
Oem ManagerOem
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it's an unnecessary detail for consumers. In the JSON unmarhalling it can pull out the fields and set them as direct properties of the manager struct.

@stmcginnis
Copy link
Owner

Sorry, we've had a push to add more Supermicro support, so unfortunately this is now superceded by other work. There's some great stuff here, so feel free to add to or improve the current code in the repo. Thanks a ton for your effort on this!

@stmcginnis stmcginnis closed this Oct 16, 2024
@mxey
Copy link

mxey commented Oct 18, 2024

@stmcginnis No worries, looks like you added everything we needed :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants