Skip to content

Commit

Permalink
Merge pull request #490 from elezar/add-mps-support
Browse files Browse the repository at this point in the history
Add initial MPS support
  • Loading branch information
elezar authored Feb 6, 2024
2 parents 531e9e2 + 6ea5fa8 commit 5bd74ed
Show file tree
Hide file tree
Showing 68 changed files with 5,518 additions and 110 deletions.
29 changes: 4 additions & 25 deletions api/config/v1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func NewConfig(c *cli.Context, flags []cli.Flag) (*Config, error) {
// logger is used to issue warning in API functions without requiring an explicit implementation.
type logger interface {
Warning(...interface{})
Warningf(string, ...interface{})
}

// DisableResourceNamingInConfig temporarily disable the resource renaming feature of the plugin.
Expand All @@ -72,31 +73,9 @@ func DisableResourceNamingInConfig(logger logger, config *Config) {
config.Resources.MIGs = nil

// Disable renaming / device selection in Sharing.TimeSlicing.Resources
renameByDefault := config.Sharing.TimeSlicing.RenameByDefault
setsNonDefaultRename := false
setsDevices := false
for i, r := range config.Sharing.TimeSlicing.Resources {
if !renameByDefault && r.Rename != "" {
setsNonDefaultRename = true
config.Sharing.TimeSlicing.Resources[i].Rename = ""
}
if renameByDefault && r.Rename != r.Name.DefaultSharedRename() {
setsNonDefaultRename = true
config.Sharing.TimeSlicing.Resources[i].Rename = r.Name.DefaultSharedRename()
}
if !r.Devices.All {
setsDevices = true
config.Sharing.TimeSlicing.Resources[i].Devices.All = true
config.Sharing.TimeSlicing.Resources[i].Devices.Count = 0
config.Sharing.TimeSlicing.Resources[i].Devices.List = nil
}
}
if setsNonDefaultRename {
logger.Warning("Setting the 'rename' field in sharing.timeSlicing.resources is not yet supported in the config. Ignoring...")
}
if setsDevices {
logger.Warning("Customizing the 'devices' field in sharing.timeSlicing.resources is not yet supported in the config. Ignoring...")
}
config.Sharing.TimeSlicing.disableResoureRenaming(logger, "timeSlicing")
// Disable renaming / device selection in Sharing.MPS.Resources
config.Sharing.MPS.disableResoureRenaming(logger, "mps")
}

// parseConfig parses a config file as either YAML of JSON and unmarshals it into a Config struct.
Expand Down
52 changes: 48 additions & 4 deletions api/config/v1/replicas.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,57 @@ import (
"github.com/google/uuid"
)

// TimeSlicing defines the set of replicas to be made for timeSlicing available resources.
type TimeSlicing struct {
// ReplicatedResources defines generic options for replicating devices.
type ReplicatedResources struct {
RenameByDefault bool `json:"renameByDefault,omitempty" yaml:"renameByDefault,omitempty"`
FailRequestsGreaterThanOne bool `json:"failRequestsGreaterThanOne,omitempty" yaml:"failRequestsGreaterThanOne,omitempty"`
Resources []ReplicatedResource `json:"resources,omitempty" yaml:"resources,omitempty"`
}

func (rrs *ReplicatedResources) disableResoureRenaming(logger logger, id string) {
if rrs == nil {
return
}
renameByDefault := rrs.RenameByDefault
setsNonDefaultRename := false
setsDevices := false
for i, r := range rrs.Resources {
if !renameByDefault && r.Rename != "" {
setsNonDefaultRename = true
rrs.Resources[i].Rename = ""
}
if renameByDefault && r.Rename != r.Name.DefaultSharedRename() {
setsNonDefaultRename = true
rrs.Resources[i].Rename = r.Name.DefaultSharedRename()
}
if !r.Devices.All {
setsDevices = true
rrs.Resources[i].Devices.All = true
rrs.Resources[i].Devices.Count = 0
rrs.Resources[i].Devices.List = nil
}
}
if setsNonDefaultRename {
logger.Warningf("Setting the 'rename' field in sharing.%s.resources is not yet supported in the config. Ignoring...", id)
}
if setsDevices {
logger.Warningf("Customizing the 'devices' field in sharing.%s.resources is not yet supported in the config. Ignoring...", id)
}

}

func (rrs *ReplicatedResources) isReplicated() bool {
if rrs == nil {
return false
}
for _, rr := range rrs.Resources {
if rr.Replicas > 1 {
return true
}
}
return false
}

// ReplicatedResource represents a resource to be replicated.
type ReplicatedResource struct {
Name ResourceName `json:"name" yaml:"name"`
Expand Down Expand Up @@ -117,8 +161,8 @@ func (d ReplicatedDeviceRef) IsMigUUID() bool {
return true
}

// UnmarshalJSON unmarshals raw bytes into a 'TimeSlicing' struct.
func (s *TimeSlicing) UnmarshalJSON(b []byte) error {
// UnmarshalJSON unmarshals raw bytes into a 'ReplicatedResources' struct.
func (s *ReplicatedResources) UnmarshalJSON(b []byte) error {
ts := make(map[string]json.RawMessage)
err := json.Unmarshal(b, &ts)
if err != nil {
Expand Down
10 changes: 5 additions & 5 deletions api/config/v1/replicas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,10 +371,10 @@ func TestUnmarshalReplicatedResource(t *testing.T) {
}
}

func TestUnmarshalTimeSlicing(t *testing.T) {
func TestUnmarshalReplicatedResources(t *testing.T) {
testCases := []struct {
input string
output TimeSlicing
output ReplicatedResources
err bool
}{
{
Expand All @@ -400,7 +400,7 @@ func TestUnmarshalTimeSlicing(t *testing.T) {
}
]
}`,
output: TimeSlicing{
output: ReplicatedResources{
Resources: []ReplicatedResource{
{
Name: NoErrorNewResourceName("valid"),
Expand All @@ -423,7 +423,7 @@ func TestUnmarshalTimeSlicing(t *testing.T) {
}
]
}`,
output: TimeSlicing{
output: ReplicatedResources{
Resources: []ReplicatedResource{
{
Name: NoErrorNewResourceName("valid1"),
Expand Down Expand Up @@ -453,7 +453,7 @@ func TestUnmarshalTimeSlicing(t *testing.T) {

for i, tc := range testCases {
t.Run(fmt.Sprintf("test case %d", i), func(t *testing.T) {
var output TimeSlicing
var output ReplicatedResources
err := output.UnmarshalJSON([]byte(tc.input))
if tc.err {
require.Error(t, err)
Expand Down
33 changes: 32 additions & 1 deletion api/config/v1/sharing.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,36 @@ package v1

// Sharing encapsulates the set of sharing strategies that are supported.
type Sharing struct {
TimeSlicing TimeSlicing `json:"timeSlicing,omitempty" yaml:"timeSlicing,omitempty"`
// TimeSlicing defines the set of replicas to be made for timeSlicing available resources.
TimeSlicing ReplicatedResources `json:"timeSlicing,omitempty" yaml:"timeSlicing,omitempty"`
// MPS defines the set of replicas to be shared using MPS
MPS *ReplicatedResources `json:"mps,omitempty" yaml:"mps,omitempty"`
}

type SharingStrategy string

const (
SharingStrategyMPS = SharingStrategy("mps")
SharingStrategyNone = SharingStrategy("none")
SharingStrategyTimeSlicing = SharingStrategy("time-slicing")
)

// SharingStrategy returns the active sharing strategy.
func (s *Sharing) SharingStrategy() SharingStrategy {
if s.MPS != nil && s.MPS.isReplicated() {
return SharingStrategyMPS
}

if s.TimeSlicing.isReplicated() {
return SharingStrategyTimeSlicing
}
return SharingStrategyNone
}

// ReplicatedResources returns the resources associated with the active sharing strategy.
func (s *Sharing) ReplicatedResources() *ReplicatedResources {
if s.MPS != nil {
return s.MPS
}
return &s.TimeSlicing
}
Loading

0 comments on commit 5bd74ed

Please sign in to comment.