github.com/vmware/govmomi@v0.51.0/pbm/simulator/simulator.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  	"slices"
     9  	"time"
    10  
    11  	"github.com/google/uuid"
    12  
    13  	"github.com/vmware/govmomi/pbm"
    14  	"github.com/vmware/govmomi/pbm/methods"
    15  	"github.com/vmware/govmomi/pbm/types"
    16  	"github.com/vmware/govmomi/simulator"
    17  	"github.com/vmware/govmomi/vim25"
    18  	"github.com/vmware/govmomi/vim25/soap"
    19  	vim "github.com/vmware/govmomi/vim25/types"
    20  )
    21  
    22  var content = types.PbmServiceInstanceContent{
    23  	AboutInfo: types.PbmAboutInfo{
    24  		Name:         "PBM",
    25  		Version:      "2.0",
    26  		InstanceUuid: "df09f335-be97-4f33-8c27-315faaaad6fc",
    27  	},
    28  	SessionManager:            vim.ManagedObjectReference{Type: "PbmSessionManager", Value: "SessionManager"},
    29  	CapabilityMetadataManager: vim.ManagedObjectReference{Type: "PbmCapabilityMetadataManager", Value: "CapabilityMetadataManager"},
    30  	ProfileManager:            vim.ManagedObjectReference{Type: "PbmProfileProfileManager", Value: "ProfileManager"},
    31  	ComplianceManager:         vim.ManagedObjectReference{Type: "PbmComplianceManager", Value: "complianceManager"},
    32  	PlacementSolver:           vim.ManagedObjectReference{Type: "PbmPlacementSolver", Value: "placementSolver"},
    33  	ReplicationManager:        &vim.ManagedObjectReference{Type: "PbmReplicationManager", Value: "ReplicationManager"},
    34  }
    35  
    36  func init() {
    37  	simulator.RegisterEndpoint(func(s *simulator.Service, r *simulator.Registry) {
    38  		if r.IsVPX() {
    39  			s.RegisterSDK(New())
    40  		}
    41  	})
    42  }
    43  
    44  func New() *simulator.Registry {
    45  	r := simulator.NewRegistry()
    46  	r.Namespace = pbm.Namespace
    47  	r.Path = pbm.Path
    48  	r.Cookie = simulator.SOAPCookie
    49  
    50  	r.Put(&ServiceInstance{
    51  		ManagedObjectReference: pbm.ServiceInstance,
    52  		Content:                content,
    53  	})
    54  
    55  	profileManager := &ProfileManager{
    56  		ManagedObjectReference: content.ProfileManager,
    57  	}
    58  	profileManager.init(r)
    59  	r.Put(profileManager)
    60  
    61  	r.Put(&PlacementSolver{
    62  		ManagedObjectReference: content.PlacementSolver,
    63  	})
    64  
    65  	return r
    66  }
    67  
    68  type ServiceInstance struct {
    69  	vim.ManagedObjectReference
    70  
    71  	Content types.PbmServiceInstanceContent
    72  }
    73  
    74  func (s *ServiceInstance) PbmRetrieveServiceContent(_ *types.PbmRetrieveServiceContent) soap.HasFault {
    75  	return &methods.PbmRetrieveServiceContentBody{
    76  		Res: &types.PbmRetrieveServiceContentResponse{
    77  			Returnval: s.Content,
    78  		},
    79  	}
    80  }
    81  
    82  type ProfileManager struct {
    83  	vim.ManagedObjectReference
    84  
    85  	profiles       []types.BasePbmProfile
    86  	profileDetails map[string]types.PbmProfileDetails
    87  }
    88  
    89  func (m *ProfileManager) init(_ *simulator.Registry) {
    90  	m.profiles = slices.Clone(vcenter67DefaultProfiles)
    91  
    92  	// Ensure the default encryption profile has the encryption IOFILTER as this
    93  	// is required when detecting whether a policy supports encryption.
    94  	m.profileDetails = map[string]types.PbmProfileDetails{
    95  		defaultEncryptionProfile.ProfileId.UniqueId: {
    96  			Profile: defaultEncryptionProfile,
    97  			IofInfos: []types.PbmIofilterInfo{
    98  				{
    99  					FilterType: string(types.PbmIofilterInfoFilterTypeENCRYPTION),
   100  				},
   101  			},
   102  		},
   103  	}
   104  }
   105  
   106  func (m *ProfileManager) PbmQueryProfile(req *types.PbmQueryProfile) soap.HasFault {
   107  	body := new(methods.PbmQueryProfileBody)
   108  	body.Res = new(types.PbmQueryProfileResponse)
   109  
   110  	for i := range m.profiles {
   111  		b, ok := m.profiles[i].(types.BasePbmCapabilityProfile)
   112  		if !ok {
   113  			continue
   114  		}
   115  		p := b.GetPbmCapabilityProfile()
   116  
   117  		if p.ResourceType != req.ResourceType {
   118  			continue
   119  		}
   120  
   121  		if req.ProfileCategory != "" {
   122  			if p.ProfileCategory != req.ProfileCategory {
   123  				continue
   124  			}
   125  		}
   126  
   127  		body.Res.Returnval = append(body.Res.Returnval, types.PbmProfileId{
   128  			UniqueId: p.ProfileId.UniqueId,
   129  		})
   130  	}
   131  
   132  	return body
   133  }
   134  
   135  func (m *ProfileManager) PbmQueryAssociatedProfile(req *types.PbmQueryAssociatedProfile) soap.HasFault {
   136  	body := new(methods.PbmQueryAssociatedProfileBody)
   137  	body.Res = new(types.PbmQueryAssociatedProfileResponse)
   138  
   139  	return body
   140  }
   141  
   142  func (m *ProfileManager) PbmQueryAssociatedProfiles(req *types.PbmQueryAssociatedProfiles) soap.HasFault {
   143  	body := new(methods.PbmQueryAssociatedProfilesBody)
   144  	body.Res = new(types.PbmQueryAssociatedProfilesResponse)
   145  
   146  	return body
   147  }
   148  
   149  func (m *ProfileManager) PbmRetrieveContent(req *types.PbmRetrieveContent) soap.HasFault {
   150  	body := new(methods.PbmRetrieveContentBody)
   151  	if len(req.ProfileIds) == 0 {
   152  		body.Fault_ = simulator.Fault("", new(vim.InvalidRequest))
   153  		return body
   154  	}
   155  
   156  	var res []types.BasePbmProfile
   157  
   158  	match := func(id string) bool {
   159  		for _, p := range m.profiles {
   160  			if id == p.GetPbmProfile().ProfileId.UniqueId {
   161  				res = append(res, p)
   162  				return true
   163  			}
   164  		}
   165  		return false
   166  	}
   167  
   168  	for _, p := range req.ProfileIds {
   169  		if match(p.UniqueId) {
   170  			continue
   171  		}
   172  
   173  		body.Fault_ = simulator.Fault("", &vim.InvalidArgument{InvalidProperty: "profileId"})
   174  		return body
   175  	}
   176  
   177  	body.Res = &types.PbmRetrieveContentResponse{Returnval: res}
   178  
   179  	return body
   180  }
   181  
   182  func (m *ProfileManager) PbmCreate(ctx *simulator.Context, req *types.PbmCreate) soap.HasFault {
   183  	body := new(methods.PbmCreateBody)
   184  	body.Res = new(types.PbmCreateResponse)
   185  
   186  	profile := &types.PbmCapabilityProfile{
   187  		PbmProfile: types.PbmProfile{
   188  			ProfileId: types.PbmProfileId{
   189  				UniqueId: uuid.New().String(),
   190  			},
   191  			Name:            req.CreateSpec.Name,
   192  			Description:     req.CreateSpec.Description,
   193  			CreationTime:    time.Now(),
   194  			CreatedBy:       ctx.Session.UserName,
   195  			LastUpdatedTime: time.Now(),
   196  			LastUpdatedBy:   ctx.Session.UserName,
   197  		},
   198  		ProfileCategory:          req.CreateSpec.Category,
   199  		ResourceType:             req.CreateSpec.ResourceType,
   200  		Constraints:              req.CreateSpec.Constraints,
   201  		GenerationId:             0,
   202  		IsDefault:                false,
   203  		SystemCreatedProfileType: "",
   204  		LineOfService:            "",
   205  	}
   206  
   207  	m.profiles = append(m.profiles, profile)
   208  	body.Res.Returnval.UniqueId = profile.PbmProfile.ProfileId.UniqueId
   209  
   210  	return body
   211  }
   212  
   213  func (m *ProfileManager) PbmDelete(req *types.PbmDelete) soap.HasFault {
   214  	body := new(methods.PbmDeleteBody)
   215  
   216  	for _, id := range req.ProfileId {
   217  		for i, p := range m.profiles {
   218  			pid := p.GetPbmProfile().ProfileId
   219  
   220  			if id == pid {
   221  				m.profiles = append(m.profiles[:i], m.profiles[i+1:]...)
   222  				break
   223  			}
   224  		}
   225  	}
   226  
   227  	body.Res = new(types.PbmDeleteResponse)
   228  
   229  	return body
   230  }
   231  
   232  func (m *ProfileManager) PbmQueryIOFiltersFromProfileId(req *types.PbmQueryIOFiltersFromProfileId) soap.HasFault {
   233  	body := methods.PbmQueryIOFiltersFromProfileIdBody{
   234  		Res: &types.PbmQueryIOFiltersFromProfileIdResponse{},
   235  	}
   236  
   237  	for i := range req.ProfileIds {
   238  		profileID := req.ProfileIds[i]
   239  		if profileDetails, ok := m.profileDetails[profileID.UniqueId]; ok {
   240  			body.Res.Returnval = append(
   241  				body.Res.Returnval,
   242  				types.PbmProfileToIofilterMap{
   243  					Key:       profileID,
   244  					Iofilters: profileDetails.IofInfos,
   245  				})
   246  		} else {
   247  			body.Fault_ = simulator.Fault("Invalid profile ID", &vim.RuntimeFault{})
   248  			break
   249  		}
   250  	}
   251  
   252  	if body.Fault_ != nil {
   253  		body.Res = nil
   254  	}
   255  
   256  	return &body
   257  }
   258  
   259  type PlacementSolver struct {
   260  	vim.ManagedObjectReference
   261  }
   262  
   263  func (m *PlacementSolver) PbmCheckRequirements(ctx *simulator.Context, req *types.PbmCheckRequirements) soap.HasFault {
   264  	body := new(methods.PbmCheckRequirementsBody)
   265  	body.Res = new(types.PbmCheckRequirementsResponse)
   266  
   267  	for _, ds := range ctx.For(vim25.Path).Map.All("Datastore") {
   268  		// TODO: filter
   269  		ref := ds.Reference()
   270  		body.Res.Returnval = append(body.Res.Returnval, types.PbmPlacementCompatibilityResult{
   271  			Hub: types.PbmPlacementHub{
   272  				HubType: ref.Type,
   273  				HubId:   ref.Value,
   274  			},
   275  			MatchingResources: nil,
   276  			HowMany:           0,
   277  			Utilization:       nil,
   278  			Warning:           nil,
   279  			Error:             nil,
   280  		})
   281  	}
   282  
   283  	return body
   284  }
   285  
   286  func (m *PlacementSolver) PbmCheckCompatibility(ctx *simulator.Context, _ *types.PbmCheckCompatibility) soap.HasFault {
   287  	body := new(methods.PbmCheckCompatibilityBody)
   288  	body.Res = new(types.PbmCheckCompatibilityResponse)
   289  
   290  	for _, ds := range ctx.For(vim25.Path).Map.All("Datastore") {
   291  		// TODO: filter
   292  		ref := ds.Reference()
   293  		body.Res.Returnval = append(body.Res.Returnval, types.PbmPlacementCompatibilityResult{
   294  			Hub: types.PbmPlacementHub{
   295  				HubType: ref.Type,
   296  				HubId:   ref.Value,
   297  			},
   298  			MatchingResources: nil,
   299  			HowMany:           0,
   300  			Utilization:       nil,
   301  			Warning:           nil,
   302  			Error:             nil,
   303  		})
   304  	}
   305  
   306  	return body
   307  }