Skip to content

Commit

Permalink
Add methods to upload and unmount a floppy image
Browse files Browse the repository at this point in the history
  • Loading branch information
joelrebel committed Sep 11, 2023
1 parent 7673e90 commit 76a049a
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 0 deletions.
136 changes: 136 additions & 0 deletions bmc/floppy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package bmc

import (
"context"
"fmt"
"io"

"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
)

// FloppyImageUploader defines methods to upload a floppy image
type FloppyImageUploader interface {
UploadFloppyImage(ctx context.Context, image io.Reader) (err error)
}

// floppyImageUploaderProvider is an internal struct to correlate an implementation/provider and its name
type floppyImageUploaderProvider struct {
name string
impl FloppyImageUploader
}

// uploadFloppyImage is a wrapper method to invoke methods for the FloppyImageUploader interface
func uploadFloppyImage(ctx context.Context, image io.Reader, p []floppyImageUploaderProvider) (metadata Metadata, err error) {
var metadataLocal Metadata

for _, elem := range p {
if elem.impl == nil {
continue
}

select {
case <-ctx.Done():
err = multierror.Append(err, ctx.Err())

return metadata, err
default:
metadataLocal.ProvidersAttempted = append(metadataLocal.ProvidersAttempted, elem.name)
uploadErr := elem.impl.UploadFloppyImage(ctx, image)
if uploadErr != nil {
err = multierror.Append(err, errors.WithMessagef(uploadErr, "provider: %v", elem.name))
continue
}

metadataLocal.SuccessfulProvider = elem.name
return metadataLocal, nil
}
}

return metadataLocal, multierror.Append(err, errors.New("failed to upload floppy image"))
}

// UploadFloppyImageFromInterfaces identifies implementations of the FloppyImageUploader interface and passes the found implementations to the uploadFloppyImage() wrapper
func UploadFloppyImageFromInterfaces(ctx context.Context, image io.Reader, p []interface{}) (metadata Metadata, err error) {
providers := make([]floppyImageUploaderProvider, 0)
for _, elem := range p {
temp := floppyImageUploaderProvider{name: getProviderName(elem)}
switch p := elem.(type) {
case FloppyImageUploader:
temp.impl = p
providers = append(providers, temp)
default:
e := fmt.Sprintf("not a FloppyImageUploader implementation: %T", p)
err = multierror.Append(err, errors.New(e))
}
}

if len(providers) == 0 {
return metadata, multierror.Append(err, errors.New("no FloppyImageUploader implementations found"))
}

return uploadFloppyImage(ctx, image, providers)
}

// FloppyImageUploader defines methods to unmount a floppy image
type FloppyImageUnmounter interface {
UnmountFloppyImage(ctx context.Context) (err error)
}

// floppyImageUnmounterProvider is an internal struct to correlate an implementation/provider and its name
type floppyImageUnmounterProvider struct {
name string
impl FloppyImageUnmounter
}

// unmountFloppyImage is a wrapper method to invoke methods for the FloppyImageUnmounter interface
func unmountFloppyImage(ctx context.Context, p []floppyImageUnmounterProvider) (metadata Metadata, err error) {
var metadataLocal Metadata

for _, elem := range p {
if elem.impl == nil {
continue
}

select {
case <-ctx.Done():
err = multierror.Append(err, ctx.Err())

return metadata, err
default:
metadataLocal.ProvidersAttempted = append(metadataLocal.ProvidersAttempted, elem.name)
uploadErr := elem.impl.UnmountFloppyImage(ctx)
if uploadErr != nil {
err = multierror.Append(err, errors.WithMessagef(uploadErr, "provider: %v", elem.name))
continue
}

metadataLocal.SuccessfulProvider = elem.name
return metadataLocal, nil
}
}

return metadataLocal, multierror.Append(err, errors.New("failed to unmount floppy image"))
}

// UploadFloppyImageFromInterfaces identifies implementations of the FloppyImageUnmounter interface and passes the found implementations to the unmountFloppyImage() wrapper
func UnmountFloppyImageFromInterfaces(ctx context.Context, p []interface{}) (metadata Metadata, err error) {
providers := make([]floppyImageUnmounterProvider, 0)
for _, elem := range p {
temp := floppyImageUnmounterProvider{name: getProviderName(elem)}
switch p := elem.(type) {
case FloppyImageUnmounter:
temp.impl = p
providers = append(providers, temp)
default:
e := fmt.Sprintf("not a FloppyImageUnmounter implementation: %T", p)
err = multierror.Append(err, errors.New(e))
}
}

if len(providers) == 0 {
return metadata, multierror.Append(err, errors.New("no FloppyImageUnmounter implementations found"))
}

return unmountFloppyImage(ctx, providers)
}
14 changes: 14 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,3 +378,17 @@ func (c *Client) Screenshot(ctx context.Context) (image []byte, fileType string,

return image, fileType, err
}

func (c *Client) UploadFloppyImage(ctx context.Context, image io.Reader) (err error) {
metadata, err := bmc.UploadFloppyImageFromInterfaces(ctx, image, c.registry().GetDriverInterfaces())
c.setMetadata(metadata)

return err
}

func (c *Client) UnmountFloppyImage(ctx context.Context) (err error) {
metadata, err := bmc.UnmountFloppyImageFromInterfaces(ctx, c.registry().GetDriverInterfaces())
c.setMetadata(metadata)

return err
}
6 changes: 6 additions & 0 deletions providers/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ const (
FeatureBootDeviceSet registrar.Feature = "bootdeviceset"
// FeaturesVirtualMedia means an implementation can manage virtual media devices
FeatureVirtualMedia registrar.Feature = "virtualmedia"
// FeatureUploadFloppyImage means an implementation uploads a floppy image for mounting as virtual media.
//
// note: This is differs from FeatureVirtualMedia which is limited to accepting a URL to download the image from.
FeatureUploadFloppyImage registrar.Feature = "uploadFloppyImage"
// FeatureUnmountFloppyImage means an implementation removes a floppy image that was previously uploaded.
FeatureUnmountFloppyImage registrar.Feature = "unmountFloppyImage"
// FeatureFirmwareInstall means an implementation that initiates the firmware install process
FeatureFirmwareInstall registrar.Feature = "firmwareinstall"
// FeatureFirmwareInstallSatus means an implementation that returns the firmware install status
Expand Down

0 comments on commit 76a049a

Please sign in to comment.