github.com/vmware/govmomi@v0.51.0/simulator/option_manager.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package simulator
     6  
     7  import (
     8  	"strings"
     9  
    10  	"github.com/vmware/govmomi/object"
    11  	"github.com/vmware/govmomi/simulator/esx"
    12  	"github.com/vmware/govmomi/simulator/vpx"
    13  	"github.com/vmware/govmomi/vim25/methods"
    14  	"github.com/vmware/govmomi/vim25/mo"
    15  	"github.com/vmware/govmomi/vim25/soap"
    16  	"github.com/vmware/govmomi/vim25/types"
    17  )
    18  
    19  // OptionManager is used in at least two locations for ESX:
    20  // 1. ServiceContent.setting - this is empty on ESX and //TODO on VC
    21  // 2. ConfigManager.advancedOption - this is where the bulk of the ESX settings are found
    22  type OptionManager struct {
    23  	mo.OptionManager
    24  
    25  	// mirror is an array to keep in sync with OptionManager.Settings. Necessary because we use append.
    26  	// uni-directional - changes made to the mirrored array are not reflected back to Settings
    27  	mirror *[]types.BaseOptionValue
    28  }
    29  
    30  // NewOptionManager constructs the type. If mirror is non-nil it takes precedence over settings, and settings is ignored.
    31  // Args:
    32  //   - ref - used to set OptionManager.Self if non-nil
    33  //   - setting - initial options, may be nil.
    34  //   - mirror - options array to keep updated with the OptionManager.Settings, may be nil.
    35  func NewOptionManager(ref *types.ManagedObjectReference, setting []types.BaseOptionValue, mirror *[]types.BaseOptionValue) object.Reference {
    36  	s := &OptionManager{}
    37  
    38  	s.Setting = setting
    39  	if mirror != nil {
    40  		s.mirror = mirror
    41  		s.Setting = *mirror
    42  	}
    43  
    44  	if ref != nil {
    45  		s.Self = *ref
    46  	}
    47  
    48  	return s
    49  }
    50  
    51  // init constructs the OptionManager for ServiceContent.setting from the template directories.
    52  // This does _not_ construct the OptionManager for ConfigManager.advancedOption.
    53  func (m *OptionManager) init(r *Registry) {
    54  	if len(m.Setting) == 0 {
    55  		if r.IsVPX() {
    56  			m.Setting = vpx.Setting
    57  		} else {
    58  			m.Setting = esx.Setting
    59  		}
    60  	}
    61  }
    62  
    63  func (m *OptionManager) model(model *Model) error {
    64  	return model.createRootTempDir(m)
    65  }
    66  
    67  func (m *OptionManager) QueryOptions(req *types.QueryOptions) soap.HasFault {
    68  	body := &methods.QueryOptionsBody{}
    69  	res := &types.QueryOptionsResponse{}
    70  
    71  	for _, opt := range m.Setting {
    72  		if strings.HasPrefix(opt.GetOptionValue().Key, req.Name) {
    73  			res.Returnval = append(res.Returnval, opt)
    74  		}
    75  	}
    76  
    77  	if len(res.Returnval) == 0 {
    78  		body.Fault_ = Fault("", &types.InvalidName{Name: req.Name})
    79  	} else {
    80  		body.Res = res
    81  	}
    82  
    83  	return body
    84  }
    85  
    86  func (m *OptionManager) find(key string) *types.OptionValue {
    87  	for _, opt := range m.Setting {
    88  		setting := opt.GetOptionValue()
    89  		if setting.Key == key {
    90  			return setting
    91  		}
    92  	}
    93  	return nil
    94  }
    95  
    96  func (m *OptionManager) UpdateOptions(req *types.UpdateOptions) soap.HasFault {
    97  	body := new(methods.UpdateOptionsBody)
    98  
    99  	for _, change := range req.ChangedValue {
   100  		setting := change.GetOptionValue()
   101  
   102  		// We don't currently include the entire list of default settings for ESX and vCenter,
   103  		// this prefix is currently used to test the failure path.
   104  		// Real vCenter seems to only allow new options if Key has a "config." prefix.
   105  		// TODO: consider behaving the same, which would require including 2 long lists of options in vpx.Setting and esx.Setting
   106  		if strings.HasPrefix(setting.Key, "ENOENT.") {
   107  			body.Fault_ = Fault("", &types.InvalidName{Name: setting.Key})
   108  			return body
   109  		}
   110  
   111  		opt := m.find(setting.Key)
   112  		if opt != nil {
   113  			// This is an existing option.
   114  			opt.Value = setting.Value
   115  			continue
   116  		}
   117  
   118  		m.Setting = append(m.Setting, change)
   119  		if m.mirror != nil {
   120  			*m.mirror = m.Setting
   121  		}
   122  	}
   123  
   124  	body.Res = new(types.UpdateOptionsResponse)
   125  	return body
   126  }