github.com/vmware/govmomi@v0.51.0/pbm/client.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 pbm
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  
    11  	"github.com/vmware/govmomi/pbm/methods"
    12  	"github.com/vmware/govmomi/pbm/types"
    13  	"github.com/vmware/govmomi/vim25"
    14  	"github.com/vmware/govmomi/vim25/soap"
    15  	vim "github.com/vmware/govmomi/vim25/types"
    16  )
    17  
    18  const (
    19  	Namespace = "pbm"
    20  	Path      = "/pbm"
    21  )
    22  
    23  var (
    24  	ServiceInstance = vim.ManagedObjectReference{
    25  		Type:  "PbmServiceInstance",
    26  		Value: "ServiceInstance",
    27  	}
    28  )
    29  
    30  type Client struct {
    31  	*soap.Client
    32  
    33  	ServiceContent types.PbmServiceInstanceContent
    34  
    35  	RoundTripper soap.RoundTripper
    36  }
    37  
    38  func NewClient(ctx context.Context, c *vim25.Client) (*Client, error) {
    39  	sc := c.Client.NewServiceClient(Path, Namespace)
    40  	sc.Cookie = c.SessionCookie // vcSessionCookie soap.Header, value must be from vim25.Client
    41  
    42  	req := types.PbmRetrieveServiceContent{
    43  		This: ServiceInstance,
    44  	}
    45  
    46  	res, err := methods.PbmRetrieveServiceContent(ctx, sc, &req)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	return &Client{sc, res.Returnval, sc}, nil
    52  }
    53  
    54  // RoundTrip dispatches to the RoundTripper field.
    55  func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error {
    56  	return c.RoundTripper.RoundTrip(ctx, req, res)
    57  }
    58  
    59  func (c *Client) QueryProfile(ctx context.Context, rtype types.PbmProfileResourceType, category string) ([]types.PbmProfileId, error) {
    60  	req := types.PbmQueryProfile{
    61  		This:            c.ServiceContent.ProfileManager,
    62  		ResourceType:    rtype,
    63  		ProfileCategory: category,
    64  	}
    65  
    66  	res, err := methods.PbmQueryProfile(ctx, c, &req)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	return res.Returnval, nil
    72  }
    73  
    74  func (c *Client) RetrieveContent(ctx context.Context, ids []types.PbmProfileId) ([]types.BasePbmProfile, error) {
    75  	req := types.PbmRetrieveContent{
    76  		This:       c.ServiceContent.ProfileManager,
    77  		ProfileIds: ids,
    78  	}
    79  
    80  	res, err := methods.PbmRetrieveContent(ctx, c, &req)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	return res.Returnval, nil
    86  }
    87  
    88  type PlacementCompatibilityResult []types.PbmPlacementCompatibilityResult
    89  
    90  func (c *Client) CheckRequirements(ctx context.Context, hubs []types.PbmPlacementHub, ref *types.PbmServerObjectRef, preq []types.BasePbmPlacementRequirement) (PlacementCompatibilityResult, error) {
    91  	req := types.PbmCheckRequirements{
    92  		This:                        c.ServiceContent.PlacementSolver,
    93  		HubsToSearch:                hubs,
    94  		PlacementSubjectRef:         ref,
    95  		PlacementSubjectRequirement: preq,
    96  	}
    97  
    98  	res, err := methods.PbmCheckRequirements(ctx, c, &req)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	return res.Returnval, nil
   104  }
   105  
   106  func (l PlacementCompatibilityResult) CompatibleDatastores() []types.PbmPlacementHub {
   107  	var compatibleDatastores []types.PbmPlacementHub
   108  
   109  	for _, res := range l {
   110  		if len(res.Error) == 0 {
   111  			compatibleDatastores = append(compatibleDatastores, res.Hub)
   112  		}
   113  	}
   114  	return compatibleDatastores
   115  }
   116  
   117  func (l PlacementCompatibilityResult) NonCompatibleDatastores() []types.PbmPlacementHub {
   118  	var nonCompatibleDatastores []types.PbmPlacementHub
   119  
   120  	for _, res := range l {
   121  		if len(res.Error) > 0 {
   122  			nonCompatibleDatastores = append(nonCompatibleDatastores, res.Hub)
   123  		}
   124  	}
   125  	return nonCompatibleDatastores
   126  }
   127  
   128  func (c *Client) CreateProfile(ctx context.Context, capabilityProfileCreateSpec types.PbmCapabilityProfileCreateSpec) (*types.PbmProfileId, error) {
   129  	req := types.PbmCreate{
   130  		This:       c.ServiceContent.ProfileManager,
   131  		CreateSpec: capabilityProfileCreateSpec,
   132  	}
   133  
   134  	res, err := methods.PbmCreate(ctx, c, &req)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	return &res.Returnval, nil
   140  }
   141  
   142  func (c *Client) UpdateProfile(ctx context.Context, id types.PbmProfileId, updateSpec types.PbmCapabilityProfileUpdateSpec) error {
   143  	req := types.PbmUpdate{
   144  		This:       c.ServiceContent.ProfileManager,
   145  		ProfileId:  id,
   146  		UpdateSpec: updateSpec,
   147  	}
   148  
   149  	_, err := methods.PbmUpdate(ctx, c, &req)
   150  	if err != nil {
   151  		return err
   152  	}
   153  
   154  	return nil
   155  }
   156  
   157  func (c *Client) DeleteProfile(ctx context.Context, ids []types.PbmProfileId) ([]types.PbmProfileOperationOutcome, error) {
   158  	req := types.PbmDelete{
   159  		This:      c.ServiceContent.ProfileManager,
   160  		ProfileId: ids,
   161  	}
   162  
   163  	res, err := methods.PbmDelete(ctx, c, &req)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  
   168  	return res.Returnval, nil
   169  }
   170  
   171  func (c *Client) QueryAssociatedEntity(ctx context.Context, id types.PbmProfileId, entityType string) ([]types.PbmServerObjectRef, error) {
   172  	req := types.PbmQueryAssociatedEntity{
   173  		This:       c.ServiceContent.ProfileManager,
   174  		Profile:    id,
   175  		EntityType: entityType,
   176  	}
   177  
   178  	res, err := methods.PbmQueryAssociatedEntity(ctx, c, &req)
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  
   183  	return res.Returnval, nil
   184  }
   185  
   186  func (c *Client) QueryAssociatedEntities(ctx context.Context, ids []types.PbmProfileId) ([]types.PbmQueryProfileResult, error) {
   187  	req := types.PbmQueryAssociatedEntities{
   188  		This:     c.ServiceContent.ProfileManager,
   189  		Profiles: ids,
   190  	}
   191  
   192  	res, err := methods.PbmQueryAssociatedEntities(ctx, c, &req)
   193  	if err != nil {
   194  		return nil, err
   195  	}
   196  
   197  	return res.Returnval, nil
   198  }
   199  
   200  func (c *Client) ProfileIDByName(ctx context.Context, profileName string) (string, error) {
   201  	resourceType := types.PbmProfileResourceType{
   202  		ResourceType: string(types.PbmProfileResourceTypeEnumSTORAGE),
   203  	}
   204  	category := types.PbmProfileCategoryEnumREQUIREMENT
   205  	ids, err := c.QueryProfile(ctx, resourceType, string(category))
   206  	if err != nil {
   207  		return "", err
   208  	}
   209  
   210  	profiles, err := c.RetrieveContent(ctx, ids)
   211  	if err != nil {
   212  		return "", err
   213  	}
   214  
   215  	for i := range profiles {
   216  		profile := profiles[i].GetPbmProfile()
   217  		if profile.Name == profileName {
   218  			return profile.ProfileId.UniqueId, nil
   219  		}
   220  	}
   221  	return "", fmt.Errorf("no pbm profile found with name: %q", profileName)
   222  }
   223  
   224  func (c *Client) FetchCapabilityMetadata(ctx context.Context, rtype *types.PbmProfileResourceType, vendorUuid string) ([]types.PbmCapabilityMetadataPerCategory, error) {
   225  	req := types.PbmFetchCapabilityMetadata{
   226  		This:         c.ServiceContent.ProfileManager,
   227  		ResourceType: rtype,
   228  		VendorUuid:   vendorUuid,
   229  	}
   230  
   231  	res, err := methods.PbmFetchCapabilityMetadata(ctx, c, &req)
   232  	if err != nil {
   233  		return nil, err
   234  	}
   235  
   236  	return res.Returnval, nil
   237  }
   238  
   239  func (c *Client) FetchComplianceResult(ctx context.Context, entities []types.PbmServerObjectRef) ([]types.PbmComplianceResult, error) {
   240  	req := types.PbmFetchComplianceResult{
   241  		This:     c.ServiceContent.ComplianceManager,
   242  		Entities: entities,
   243  	}
   244  
   245  	res, err := methods.PbmFetchComplianceResult(ctx, c, &req)
   246  	if err != nil {
   247  		return nil, err
   248  	}
   249  
   250  	return res.Returnval, nil
   251  }
   252  
   253  // GetProfileNameByID gets storage profile name by ID
   254  func (c *Client) GetProfileNameByID(ctx context.Context, profileID string) (string, error) {
   255  	resourceType := types.PbmProfileResourceType{
   256  		ResourceType: string(types.PbmProfileResourceTypeEnumSTORAGE),
   257  	}
   258  	category := types.PbmProfileCategoryEnumREQUIREMENT
   259  	ids, err := c.QueryProfile(ctx, resourceType, string(category))
   260  	if err != nil {
   261  		return "", err
   262  	}
   263  
   264  	profiles, err := c.RetrieveContent(ctx, ids)
   265  	if err != nil {
   266  		return "", err
   267  	}
   268  
   269  	for i := range profiles {
   270  		profile := profiles[i].GetPbmProfile()
   271  		if profile.ProfileId.UniqueId == profileID {
   272  			return profile.Name, nil
   273  		}
   274  	}
   275  	return "", fmt.Errorf("no pbm profile found with id: %q", profileID)
   276  }
   277  
   278  func (c *Client) QueryAssociatedProfile(ctx context.Context, entity types.PbmServerObjectRef) ([]types.PbmProfileId, error) {
   279  	req := types.PbmQueryAssociatedProfile{
   280  		This:   c.ServiceContent.ProfileManager,
   281  		Entity: entity,
   282  	}
   283  
   284  	res, err := methods.PbmQueryAssociatedProfile(ctx, c, &req)
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  
   289  	return res.Returnval, nil
   290  }
   291  
   292  func (c *Client) QueryAssociatedProfiles(ctx context.Context, entities []types.PbmServerObjectRef) ([]types.PbmQueryProfileResult, error) {
   293  	req := types.PbmQueryAssociatedProfiles{
   294  		This:     c.ServiceContent.ProfileManager,
   295  		Entities: entities,
   296  	}
   297  
   298  	res, err := methods.PbmQueryAssociatedProfiles(ctx, c, &req)
   299  	if err != nil {
   300  		return nil, err
   301  	}
   302  
   303  	return res.Returnval, nil
   304  }
   305  
   306  func (c *Client) QueryIOFiltersFromProfileId(
   307  	ctx context.Context, profileID string) ([]types.PbmProfileToIofilterMap, error) {
   308  
   309  	req := types.PbmQueryIOFiltersFromProfileId{
   310  		This:       c.ServiceContent.ProfileManager,
   311  		ProfileIds: []types.PbmProfileId{{UniqueId: profileID}},
   312  	}
   313  	res, err := methods.PbmQueryIOFiltersFromProfileId(ctx, c, &req)
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  	return res.Returnval, nil
   318  }
   319  
   320  func (c *Client) SupportsEncryption(
   321  	ctx context.Context, profileID string) (bool, error) {
   322  
   323  	list, err := c.QueryIOFiltersFromProfileId(ctx, profileID)
   324  	if err != nil {
   325  		return false, err
   326  	}
   327  	for i := range list {
   328  		for j := range list[i].Iofilters {
   329  			f := list[i].Iofilters[j]
   330  			if f.FilterType == string(types.PbmIofilterInfoFilterTypeENCRYPTION) {
   331  				return true, nil
   332  			}
   333  		}
   334  	}
   335  	return false, nil
   336  }