github.com/vmware/govmomi@v0.37.2/simulator/custom_fields_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  	"github.com/vmware/govmomi/vim25/methods"
    21  	"github.com/vmware/govmomi/vim25/mo"
    22  	"github.com/vmware/govmomi/vim25/soap"
    23  	"github.com/vmware/govmomi/vim25/types"
    24  )
    25  
    26  type CustomFieldsManager struct {
    27  	mo.CustomFieldsManager
    28  
    29  	nextKey int32
    30  }
    31  
    32  // Iterates through all entities of passed field type;
    33  // Removes found field from their custom field properties.
    34  func entitiesFieldRemove(ctx *Context, field types.CustomFieldDef) {
    35  	entities := ctx.Map.All(field.ManagedObjectType)
    36  	for _, e := range entities {
    37  		entity := e.Entity()
    38  		ctx.WithLock(entity, func() {
    39  			aFields := entity.AvailableField
    40  			for i, aField := range aFields {
    41  				if aField.Key == field.Key {
    42  					entity.AvailableField = append(aFields[:i], aFields[i+1:]...)
    43  					break
    44  				}
    45  			}
    46  
    47  			values := e.Entity().Value
    48  			for i, value := range values {
    49  				if value.(*types.CustomFieldStringValue).Key == field.Key {
    50  					entity.Value = append(values[:i], values[i+1:]...)
    51  					break
    52  				}
    53  			}
    54  
    55  			cValues := e.Entity().CustomValue
    56  			for i, cValue := range cValues {
    57  				if cValue.(*types.CustomFieldStringValue).Key == field.Key {
    58  					entity.CustomValue = append(cValues[:i], cValues[i+1:]...)
    59  					break
    60  				}
    61  			}
    62  		})
    63  	}
    64  }
    65  
    66  // Iterates through all entities of passed field type;
    67  // Renames found field in entity's AvailableField property.
    68  func entitiesFieldRename(ctx *Context, field types.CustomFieldDef) {
    69  	entities := ctx.Map.All(field.ManagedObjectType)
    70  	for _, e := range entities {
    71  		entity := e.Entity()
    72  		ctx.WithLock(entity, func() {
    73  			aFields := entity.AvailableField
    74  			for i, aField := range aFields {
    75  				if aField.Key == field.Key {
    76  					aFields[i].Name = field.Name
    77  					break
    78  				}
    79  			}
    80  		})
    81  	}
    82  }
    83  
    84  func (c *CustomFieldsManager) findByNameType(name, moType string) (int, *types.CustomFieldDef) {
    85  	for i, field := range c.Field {
    86  		if (field.ManagedObjectType == "" || field.ManagedObjectType == moType || moType == "") &&
    87  			field.Name == name {
    88  			return i, &c.Field[i]
    89  		}
    90  	}
    91  
    92  	return -1, nil
    93  }
    94  
    95  func (c *CustomFieldsManager) findByKey(key int32) (int, *types.CustomFieldDef) {
    96  	for i, field := range c.Field {
    97  		if field.Key == key {
    98  			return i, &c.Field[i]
    99  		}
   100  	}
   101  
   102  	return -1, nil
   103  }
   104  
   105  func (c *CustomFieldsManager) AddCustomFieldDef(ctx *Context, req *types.AddCustomFieldDef) soap.HasFault {
   106  	body := &methods.AddCustomFieldDefBody{}
   107  
   108  	_, field := c.findByNameType(req.Name, req.MoType)
   109  	if field != nil {
   110  		body.Fault_ = Fault("", &types.DuplicateName{
   111  			Name:   req.Name,
   112  			Object: c.Reference(),
   113  		})
   114  		return body
   115  	}
   116  
   117  	def := types.CustomFieldDef{
   118  		Key:                     c.nextKey,
   119  		Name:                    req.Name,
   120  		ManagedObjectType:       req.MoType,
   121  		Type:                    req.MoType,
   122  		FieldDefPrivileges:      req.FieldDefPolicy,
   123  		FieldInstancePrivileges: req.FieldPolicy,
   124  	}
   125  
   126  	entities := ctx.Map.All(req.MoType)
   127  	for _, e := range entities {
   128  		entity := e.Entity()
   129  		ctx.WithLock(entity, func() {
   130  			entity.AvailableField = append(entity.AvailableField, def)
   131  		})
   132  	}
   133  
   134  	c.Field = append(c.Field, def)
   135  	c.nextKey++
   136  
   137  	body.Res = &types.AddCustomFieldDefResponse{
   138  		Returnval: def,
   139  	}
   140  	return body
   141  }
   142  
   143  func (c *CustomFieldsManager) RemoveCustomFieldDef(ctx *Context, req *types.RemoveCustomFieldDef) soap.HasFault {
   144  	body := &methods.RemoveCustomFieldDefBody{}
   145  
   146  	i, field := c.findByKey(req.Key)
   147  	if field == nil {
   148  		body.Fault_ = Fault("", &types.NotFound{})
   149  		return body
   150  	}
   151  
   152  	entitiesFieldRemove(ctx, *field)
   153  
   154  	c.Field = append(c.Field[:i], c.Field[i+1:]...)
   155  
   156  	body.Res = &types.RemoveCustomFieldDefResponse{}
   157  	return body
   158  }
   159  
   160  func (c *CustomFieldsManager) RenameCustomFieldDef(ctx *Context, req *types.RenameCustomFieldDef) soap.HasFault {
   161  	body := &methods.RenameCustomFieldDefBody{}
   162  
   163  	_, field := c.findByKey(req.Key)
   164  	if field == nil {
   165  		body.Fault_ = Fault("", &types.NotFound{})
   166  		return body
   167  	}
   168  
   169  	field.Name = req.Name
   170  
   171  	entitiesFieldRename(ctx, *field)
   172  
   173  	body.Res = &types.RenameCustomFieldDefResponse{}
   174  	return body
   175  }
   176  
   177  func (c *CustomFieldsManager) SetField(ctx *Context, req *types.SetField) soap.HasFault {
   178  	body := &methods.SetFieldBody{}
   179  
   180  	_, field := c.findByKey(req.Key)
   181  	if field == nil {
   182  		body.Fault_ = Fault("", &types.InvalidArgument{InvalidProperty: "key"})
   183  		return body
   184  	}
   185  
   186  	newValue := &types.CustomFieldStringValue{
   187  		CustomFieldValue: types.CustomFieldValue{Key: req.Key},
   188  		Value:            req.Value,
   189  	}
   190  
   191  	removeIndex := func(s []types.BaseCustomFieldValue, i int) []types.BaseCustomFieldValue {
   192  		new := make([]types.BaseCustomFieldValue, 0)
   193  		new = append(new, s[:i]...)
   194  		return append(new, s[i+1:]...)
   195  	}
   196  
   197  	removeExistingValues := func(s []types.BaseCustomFieldValue) []types.BaseCustomFieldValue {
   198  		for i := 0; i < len(s); {
   199  			if s[i].GetCustomFieldValue().Key == newValue.GetCustomFieldValue().Key {
   200  				s = removeIndex(s, i)
   201  			}
   202  			i++
   203  		}
   204  		return s
   205  	}
   206  
   207  	entity := ctx.Map.Get(req.Entity).(mo.Entity).Entity()
   208  
   209  	ctx.WithLock(entity, func() {
   210  		// Check if custom value and value are already set. If so, remove them.
   211  		entity.CustomValue = removeExistingValues(entity.CustomValue)
   212  		entity.Value = removeExistingValues(entity.Value)
   213  
   214  		// Add the new value
   215  		entity.CustomValue = append(entity.CustomValue, newValue)
   216  		entity.Value = append(entity.Value, newValue)
   217  	})
   218  
   219  	body.Res = &types.SetFieldResponse{}
   220  	return body
   221  }