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

     1  /*
     2  Copyright (c) 2017 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package simulator
    18  
    19  import (
    20  	"strings"
    21  
    22  	"github.com/vmware/govmomi/object"
    23  	"github.com/vmware/govmomi/simulator/esx"
    24  	"github.com/vmware/govmomi/simulator/vpx"
    25  	"github.com/vmware/govmomi/vim25/methods"
    26  	"github.com/vmware/govmomi/vim25/mo"
    27  	"github.com/vmware/govmomi/vim25/soap"
    28  	"github.com/vmware/govmomi/vim25/types"
    29  )
    30  
    31  // OptionManager is used in at least two locations for ESX:
    32  // 1. ServiceContent.setting - this is empty on ESX and //TODO on VC
    33  // 2. ConfigManager.advancedOption - this is where the bulk of the ESX settings are found
    34  type OptionManager struct {
    35  	mo.OptionManager
    36  
    37  	// mirror is an array to keep in sync with OptionManager.Settings. Necessary because we use append.
    38  	// uni-directional - changes made to the mirrored array are not reflected back to Settings
    39  	mirror *[]types.BaseOptionValue
    40  }
    41  
    42  func asOptionManager(ctx *Context, obj mo.Reference) (*OptionManager, bool) {
    43  	om, ok := ctx.Map.Get(obj.Reference()).(*OptionManager)
    44  	return om, ok
    45  }
    46  
    47  // NewOptionManager constructs the type. If mirror is non-nil it takes precedence over settings, and settings is ignored.
    48  // Args:
    49  //   - ref - used to set OptionManager.Self if non-nil
    50  //   - setting - initial options, may be nil.
    51  //   - mirror - options array to keep updated with the OptionManager.Settings, may be nil.
    52  func NewOptionManager(ref *types.ManagedObjectReference, setting []types.BaseOptionValue, mirror *[]types.BaseOptionValue) object.Reference {
    53  	s := &OptionManager{}
    54  
    55  	s.Setting = setting
    56  	if mirror != nil {
    57  		s.mirror = mirror
    58  		s.Setting = *mirror
    59  	}
    60  
    61  	if ref != nil {
    62  		s.Self = *ref
    63  	}
    64  
    65  	return s
    66  }
    67  
    68  // init constructs the OptionManager for ServiceContent.setting from the template directories.
    69  // This does _not_ construct the OptionManager for ConfigManager.advancedOption.
    70  func (m *OptionManager) init(r *Registry) {
    71  	if len(m.Setting) == 0 {
    72  		if r.IsVPX() {
    73  			m.Setting = vpx.Setting
    74  		} else {
    75  			m.Setting = esx.Setting
    76  		}
    77  	}
    78  }
    79  
    80  func (m *OptionManager) QueryOptions(req *types.QueryOptions) soap.HasFault {
    81  	body := &methods.QueryOptionsBody{}
    82  	res := &types.QueryOptionsResponse{}
    83  
    84  	for _, opt := range m.Setting {
    85  		if strings.HasPrefix(opt.GetOptionValue().Key, req.Name) {
    86  			res.Returnval = append(res.Returnval, opt)
    87  		}
    88  	}
    89  
    90  	if len(res.Returnval) == 0 {
    91  		body.Fault_ = Fault("", &types.InvalidName{Name: req.Name})
    92  	} else {
    93  		body.Res = res
    94  	}
    95  
    96  	return body
    97  }
    98  
    99  func (m *OptionManager) find(key string) *types.OptionValue {
   100  	for _, opt := range m.Setting {
   101  		setting := opt.GetOptionValue()
   102  		if setting.Key == key {
   103  			return setting
   104  		}
   105  	}
   106  	return nil
   107  }
   108  
   109  func (m *OptionManager) UpdateOptions(req *types.UpdateOptions) soap.HasFault {
   110  	body := new(methods.UpdateOptionsBody)
   111  
   112  	for _, change := range req.ChangedValue {
   113  		setting := change.GetOptionValue()
   114  
   115  		// We don't currently include the entire list of default settings for ESX and vCenter,
   116  		// this prefix is currently used to test the failure path.
   117  		// Real vCenter seems to only allow new options if Key has a "config." prefix.
   118  		// TODO: consider behaving the same, which would require including 2 long lists of options in vpx.Setting and esx.Setting
   119  		if strings.HasPrefix(setting.Key, "ENOENT.") {
   120  			body.Fault_ = Fault("", &types.InvalidName{Name: setting.Key})
   121  			return body
   122  		}
   123  
   124  		opt := m.find(setting.Key)
   125  		if opt != nil {
   126  			// This is an existing option.
   127  			opt.Value = setting.Value
   128  			continue
   129  		}
   130  
   131  		m.Setting = append(m.Setting, change)
   132  		if m.mirror != nil {
   133  			*m.mirror = m.Setting
   134  		}
   135  	}
   136  
   137  	body.Res = new(types.UpdateOptionsResponse)
   138  	return body
   139  }